1
1
import { useEffect , useReducer } from 'react'
2
+ import ErrorMsg from './ErrorMsg'
3
+ import FinishScreen from './FinishScreen'
4
+ import Footer from './Footer'
2
5
import Header from './Header'
3
- import Main from './Main'
4
6
import Loader from './Loader'
5
- import Error from './Error'
6
- import StartScreen from './StartScreen'
7
+ import Main from './Main'
8
+ import NextButton from './NextButton'
9
+ import Progress from './Progress'
7
10
import Question from './Question'
11
+ import StartScreen from './StartScreen'
12
+ import Timer from './Timer'
13
+
14
+ const SEC_PER_QUESTION = 5
8
15
9
16
const initialState = {
10
17
questions : [ ] ,
@@ -14,6 +21,8 @@ const initialState = {
14
21
index : 0 ,
15
22
answer : null ,
16
23
points : 0 ,
24
+ highscore : 0 ,
25
+ secondsRemaining : null ,
17
26
}
18
27
19
28
function reducer ( state , action ) {
@@ -33,6 +42,7 @@ function reducer(state, action) {
33
42
return {
34
43
...state ,
35
44
status : 'active' ,
45
+ secondsRemaining : state . questions . length * SEC_PER_QUESTION ,
36
46
}
37
47
case 'newAnswer' :
38
48
const question = state . questions [ state . index ]
@@ -47,22 +57,65 @@ function reducer(state, action) {
47
57
? state . points + question . points
48
58
: state . points ,
49
59
}
60
+ case 'nextQuestion' :
61
+ return {
62
+ ...state ,
63
+ index : state . index + 1 ,
64
+ answer : null ,
65
+ }
66
+ case 'finish' :
67
+ return {
68
+ ...state ,
69
+ status : 'finished' ,
70
+ highscore :
71
+ state . points > state . highscore
72
+ ? state . points
73
+ : state . highscore ,
74
+ }
75
+ case 'restart' :
76
+ return {
77
+ ...initialState ,
78
+ status : 'ready' ,
79
+ questions : state . questions ,
80
+ highscore : state . highscore ,
81
+ }
82
+ case 'tick' :
83
+ return {
84
+ ...state ,
85
+ secondsRemaining : state . secondsRemaining - 1 ,
86
+ status :
87
+ state . secondsRemaining - 1 <= 0 ? 'finished' : state . status ,
88
+ }
50
89
default :
51
- throw new Error ( `Invalid action ${ action . type } ` )
90
+ throw new Error ( `Invalid action " ${ action . type } " ` )
52
91
}
53
92
}
54
93
55
94
function App ( ) {
56
- const [ { questions, status, index, answer, points } , dispatch ] = useReducer (
57
- reducer ,
58
- initialState ,
59
- )
95
+ const [
96
+ {
97
+ questions,
98
+ status,
99
+ index,
100
+ answer,
101
+ points,
102
+ highscore,
103
+ secondsRemaining,
104
+ } ,
105
+ dispatch ,
106
+ ] = useReducer ( reducer , initialState )
60
107
const numQuestions = questions . length
108
+ const totalPoints = questions . reduce ( ( prev , { points } ) => prev + points , 0 )
61
109
62
110
useEffect ( ( ) => {
63
111
fetch ( 'http://localhost:8000/questions' )
64
112
. then ( ( res ) => res . json ( ) )
65
- . then ( ( data ) => dispatch ( { type : 'dataReceived' , payload : data } ) )
113
+ . then ( ( data ) =>
114
+ dispatch ( {
115
+ type : 'dataReceived' ,
116
+ payload : data ,
117
+ } ) ,
118
+ )
66
119
. catch ( ( err ) => dispatch ( { type : 'dataFailed' } ) )
67
120
} , [ ] )
68
121
@@ -71,18 +124,47 @@ function App() {
71
124
< Header />
72
125
< Main >
73
126
{ status === 'loading' && < Loader /> }
74
- { status === 'error' && < Error /> }
127
+ { status === 'error' && < ErrorMsg /> }
75
128
{ status === 'ready' && (
76
129
< StartScreen
77
130
numQuestions = { numQuestions }
78
131
dispatch = { dispatch }
79
132
/>
80
133
) }
81
134
{ status === 'active' && (
82
- < Question
83
- question = { questions [ index ] }
135
+ < >
136
+ < Progress
137
+ index = { index }
138
+ numQuestions = { numQuestions }
139
+ points = { points }
140
+ totalPoints = { totalPoints }
141
+ answer = { answer }
142
+ />
143
+ < Question
144
+ question = { questions [ index ] }
145
+ dispatch = { dispatch }
146
+ answer = { answer }
147
+ />
148
+ < Footer >
149
+ < Timer
150
+ secondsRemaining = { secondsRemaining }
151
+ dispatch = { dispatch }
152
+ />
153
+ < NextButton
154
+ dispatch = { dispatch }
155
+ answer = { answer }
156
+ index = { index }
157
+ numQuestions = { numQuestions }
158
+ />
159
+ </ Footer >
160
+ </ >
161
+ ) }
162
+ { status === 'finished' && (
163
+ < FinishScreen
164
+ points = { points }
165
+ totalPoints = { totalPoints }
166
+ highscore = { highscore }
84
167
dispatch = { dispatch }
85
- answer = { answer }
86
168
/>
87
169
) }
88
170
</ Main >
0 commit comments