@@ -14,7 +14,7 @@ import {
14
14
TableProps ,
15
15
Tabs ,
16
16
Tag ,
17
- Modal
17
+ Modal ,
18
18
} from "antd" ;
19
19
import { Content } from "antd/es/layout/layout" ;
20
20
import {
@@ -25,41 +25,58 @@ import {
25
25
} from "@ant-design/icons" ;
26
26
import "./styles.scss" ;
27
27
import { useEffect , useState } from "react" ;
28
- import { DeleteQuestion as DeleteQuestionByDocref , GetQuestions , Question } from "./services/question" ;
28
+ import {
29
+ DeleteQuestion as DeleteQuestionByDocref ,
30
+ GetQuestions ,
31
+ Question ,
32
+ } from "./services/question" ;
29
33
import {
30
34
CategoriesOption ,
31
35
DifficultyOption ,
32
36
OrderOption ,
33
- } from "./utils/SelectOptions" ;
37
+ } from "../utils/SelectOptions" ;
38
+ import Link from "next/link" ;
34
39
35
40
/**
36
41
* defines the State of the page whe a user is deleing an object. Has 3 general states:
37
42
* - {}: user is not deleting anything. The page's normal state
38
43
* - {index: docref string, deleteConfirmed: false}: Modal popup asking whether to delete the question, pending user's decision to confirm or cancel
39
44
* - {index: docref string, deleteConfirmed: true}: Currently deleting the question and reloading the database
40
45
*/
41
- type DeletionStage = { } | { index : Question , deleteConfirmed : boolean }
46
+ type DeletionStage = { } | { index : Question ; deleteConfirmed : boolean } ;
42
47
43
- function DeleteModal ( { isDeleting, questionTitle, okHandler, cancelHandler} : { questionTitle : string , okHandler : ( ) => void , cancelHandler : ( ) => void , isDeleting : boolean } ) {
44
- const title : string = `Delete Question \"${ questionTitle } \"?`
45
- const text : string = 'This action is irreversible(?)!'
48
+ function DeleteModal ( {
49
+ isDeleting,
50
+ questionTitle,
51
+ okHandler,
52
+ cancelHandler,
53
+ } : {
54
+ questionTitle : string ;
55
+ okHandler : ( ) => void ;
56
+ cancelHandler : ( ) => void ;
57
+ isDeleting : boolean ;
58
+ } ) {
59
+ const title : string = `Delete Question \"${ questionTitle } \"?` ;
60
+ const text : string = "This action is irreversible(?)!" ;
46
61
47
- return < Modal
48
- open = { true }
49
- title = { title }
50
- onOk = { okHandler }
51
- onCancel = { cancelHandler }
52
- confirmLoading = { isDeleting }
53
- okButtonProps = { { danger : true } }
54
- cancelButtonProps = { { disabled : isDeleting } } >
55
- < p > { text } </ p >
56
- </ Modal >
62
+ return (
63
+ < Modal
64
+ open = { true }
65
+ title = { title }
66
+ onOk = { okHandler }
67
+ onCancel = { cancelHandler }
68
+ confirmLoading = { isDeleting }
69
+ okButtonProps = { { danger : true } }
70
+ cancelButtonProps = { { disabled : isDeleting } }
71
+ >
72
+ < p > { text } </ p >
73
+ </ Modal >
74
+ ) ;
57
75
}
58
76
59
77
export default function Home ( ) {
60
-
61
78
// State of Deletion
62
- const [ deletionStage , setDeletionStage ] = useState < DeletionStage > ( { } )
79
+ const [ deletionStage , setDeletionStage ] = useState < DeletionStage > ( { } ) ;
63
80
64
81
// Table States
65
82
const [ questions , setQuestions ] = useState < Question [ ] | undefined > ( undefined ) ; // Store the questions
@@ -107,7 +124,13 @@ export default function Home() {
107
124
setIsLoading ( true ) ;
108
125
}
109
126
110
- let data = await GetQuestions ( currentPage , limit , sortBy , difficulty , delayedSearch ) ;
127
+ let data = await GetQuestions (
128
+ currentPage ,
129
+ limit ,
130
+ sortBy ,
131
+ difficulty ,
132
+ delayedSearch
133
+ ) ;
111
134
setQuestions ( data . questions ) ;
112
135
setTotalCount ( data . totalCount ) ;
113
136
setTotalPages ( data . totalPages ) ;
@@ -116,7 +139,18 @@ export default function Home() {
116
139
setIsLoading ( false ) ;
117
140
}
118
141
119
- useEffect ( ( ) => { loadQuestions ( ) } , [ limit , currentPage , sortBy , difficulty , delayedSearch ] ) ;
142
+ useEffect ( ( ) => {
143
+ loadQuestions ( ) ;
144
+ } , [ limit , currentPage , sortBy , difficulty , delayedSearch ] ) ;
145
+
146
+ // Delay the fetching of data only after user stops typing for awhile
147
+ useEffect ( ( ) => {
148
+ const timeout = setTimeout ( ( ) => {
149
+ setDelayedSearch ( search ) ;
150
+ setCurrentPage ( 1 ) ; // Reset the current page
151
+ } , 800 ) ;
152
+ return ( ) => clearTimeout ( timeout ) ;
153
+ } , [ search ] ) ;
120
154
121
155
// Table column specification
122
156
const columns : TableProps < Question > [ "columns" ] = [
@@ -130,7 +164,16 @@ export default function Home() {
130
164
title : "Title" ,
131
165
dataIndex : "title" ,
132
166
key : "title" ,
133
- render : ( text : string ) => < Button type = "link" > { text } </ Button > , // TODO (Sean): Onclick links to the individual question page
167
+ render : ( text : string , question : Question ) => (
168
+ < Link
169
+ href = { {
170
+ pathname : `/question/${ question . id } ` ,
171
+ query : { data : question . docRefId } , // the data
172
+ } }
173
+ >
174
+ < Button type = "link" > { text } </ Button >
175
+ </ Link >
176
+ ) , // TODO (Sean): Onclick links to the individual question page
134
177
} ,
135
178
{
136
179
title : "Categories" ,
@@ -145,14 +188,18 @@ export default function Home() {
145
188
key : "complexity" ,
146
189
render : ( difficulty : string ) => {
147
190
let color = "" ;
148
- if ( difficulty === "Easy " ) {
191
+ if ( difficulty === "easy " ) {
149
192
color = "#2DB55D" ;
150
- } else if ( difficulty === "Medium " ) {
193
+ } else if ( difficulty === "medium " ) {
151
194
color = "orange" ;
152
- } else if ( difficulty === "Hard " ) {
195
+ } else if ( difficulty === "hard " ) {
153
196
color = "red" ;
154
197
}
155
- return < div style = { { color } } > { difficulty } </ div > ;
198
+ return (
199
+ < div style = { { color } } >
200
+ { difficulty . charAt ( 0 ) . toUpperCase ( ) + difficulty . slice ( 1 ) }
201
+ </ div >
202
+ ) ;
156
203
} ,
157
204
} ,
158
205
{
@@ -169,8 +216,8 @@ export default function Home() {
169
216
danger
170
217
icon = { < DeleteOutlined /> }
171
218
onClick = { ( ) => {
172
- setDeletionStage ( { index : question , deleteConfirmed : false } ) }
173
- }
219
+ setDeletionStage ( { index : question , deleteConfirmed : false } ) ;
220
+ } }
174
221
> </ Button >
175
222
</ div >
176
223
) ,
@@ -219,7 +266,7 @@ export default function Home() {
219
266
error ( "Cannot delete: questions does not exist" ) ;
220
267
return ;
221
268
}
222
-
269
+
223
270
setDeletionStage ( { index : deletionStage . index , deleteConfirmed : true } ) ;
224
271
await DeleteQuestionByDocref ( deletionStage . index . docRefId ) ;
225
272
if ( questions . length == 1 && currentPage > 1 ) {
@@ -230,13 +277,12 @@ export default function Home() {
230
277
await loadQuestions ( ) ;
231
278
success ( "Question deleted successfully" ) ;
232
279
} catch ( err ) {
233
- if ( typeof err == ' string' ) {
280
+ if ( typeof err == " string" ) {
234
281
error ( err ) ;
235
282
}
236
283
}
237
284
}
238
285
setDeletionStage ( { } ) ;
239
-
240
286
} ;
241
287
return (
242
288
< div >
@@ -333,11 +379,14 @@ export default function Home() {
333
379
</ div >
334
380
</ Content >
335
381
</ Layout >
336
- { ( "index" in deletionStage && questions != undefined ) && < DeleteModal
337
- okHandler = { confirmDeleteHandler }
338
- cancelHandler = { ( ) => setDeletionStage ( { } ) }
339
- questionTitle = { deletionStage . index . title }
340
- isDeleting = { deletionStage . deleteConfirmed } /> }
382
+ { "index" in deletionStage && questions != undefined && (
383
+ < DeleteModal
384
+ okHandler = { confirmDeleteHandler }
385
+ cancelHandler = { ( ) => setDeletionStage ( { } ) }
386
+ questionTitle = { deletionStage . index . title }
387
+ isDeleting = { deletionStage . deleteConfirmed }
388
+ />
389
+ ) }
341
390
</ div >
342
391
) ;
343
392
}
0 commit comments