@@ -7,20 +7,31 @@ import {
7
7
Modal ,
8
8
Input ,
9
9
Dropdown ,
10
+ Table ,
11
+ Tooltip ,
12
+ Progress ,
10
13
} from '@nextui-org/react' ;
11
14
import { useEffect , useState , useRef , Fragment } from 'react' ;
12
15
import { useNavigate } from 'react-router-dom' ;
13
16
import classes from './Home.module.css' ;
14
17
import { nanoid } from 'nanoid' ;
15
18
import CrawlData from '../CrawlData/CrawlData' ;
16
- import { FcDownload , FcFile , FcMultipleInputs } from 'react-icons/fc' ;
19
+ import {
20
+ FcDeleteDatabase ,
21
+ FcDownload ,
22
+ FcFile ,
23
+ FcMultipleInputs ,
24
+ } from 'react-icons/fc' ;
25
+ import { HiOutlineEye } from 'react-icons/hi' ;
17
26
18
27
const Home = ( ) => {
19
28
const [ listCourse , setListCourse ] = useState ( [ ] ) ;
20
29
const [ showImport , setShowImport ] = useState ( false ) ;
21
30
const [ isGettingData , setIsGettingData ] = useState ( false ) ;
22
31
const [ isFailed , setIsFailed ] = useState ( false ) ;
23
32
const [ showModalCrawl , setShowModalCrawl ] = useState ( false ) ;
33
+ const [ selection , setSelection ] = useState ( [ ] ) ;
34
+ const [ isDeleteMode , setIsDeleteMode ] = useState ( false ) ;
24
35
25
36
const codeRef = useRef ( ) ;
26
37
const navigate = useNavigate ( ) ;
@@ -45,6 +56,28 @@ const Home = () => {
45
56
navigate ( '/create' ) ;
46
57
} ;
47
58
59
+ const handleChangeSelect = ( e ) => {
60
+ console . log ( e ) ;
61
+ setSelection ( [ ...e ] ) ;
62
+ } ;
63
+
64
+ const handleDelete = ( ) => {
65
+ console . log ( selection ) ;
66
+ selection . forEach ( ( item ) => {
67
+ localStorage . removeItem ( item ) ;
68
+ } ) ;
69
+ getData ( ) ;
70
+ setSelection ( [ ] ) ;
71
+ setIsDeleteMode ( false ) ;
72
+ } ;
73
+
74
+ useEffect ( ( ) => {
75
+ const interval = setInterval ( ( ) => {
76
+ getData ( ) ;
77
+ } , 2000 ) ;
78
+ return ( ) => clearInterval ( interval ) ;
79
+ } , [ ] ) ;
80
+
48
81
const handleImport = ( ) => {
49
82
const code = codeRef . current . value . trim ( ) ;
50
83
@@ -80,10 +113,14 @@ const Home = () => {
80
113
81
114
return (
82
115
< div >
83
- < CrawlData open = { showModalCrawl } setClose = { setShowModalCrawl } onSuccess = { ( ) => {
84
- setShowModalCrawl ( false ) ;
85
- getData ( ) ;
86
- } } />
116
+ < CrawlData
117
+ open = { showModalCrawl }
118
+ setClose = { setShowModalCrawl }
119
+ onSuccess = { ( ) => {
120
+ setShowModalCrawl ( false ) ;
121
+ getData ( ) ;
122
+ } }
123
+ />
87
124
< Modal
88
125
open = { showImport }
89
126
blur
@@ -133,7 +170,7 @@ const Home = () => {
133
170
>
134
171
< Dropdown disableAnimation >
135
172
< Dropdown . Button flat color = "secondary" >
136
- Create new course
173
+ Menu
137
174
</ Dropdown . Button >
138
175
< Dropdown . Menu
139
176
color = "secondary"
@@ -151,6 +188,9 @@ const Home = () => {
151
188
case 'crawl' :
152
189
setShowModalCrawl ( true ) ;
153
190
break ;
191
+ case 'delete' :
192
+ setIsDeleteMode ( ! isDeleteMode ) ;
193
+ setSelection ( [ ] ) ;
154
194
default :
155
195
break ;
156
196
}
@@ -184,41 +224,154 @@ const Home = () => {
184
224
Import code
185
225
</ Dropdown . Item >
186
226
</ Dropdown . Section >
227
+ < Dropdown . Section title = "Danger" >
228
+ < Dropdown . Item
229
+ key = "delete"
230
+ description = "Delete selected course"
231
+ color = "error"
232
+ icon = { < FcDeleteDatabase /> }
233
+ >
234
+ { isDeleteMode ? 'Cancel delete mode' : 'Delete mode' }
235
+ </ Dropdown . Item >
236
+ </ Dropdown . Section >
187
237
</ Dropdown . Menu >
188
238
</ Dropdown >
189
239
</ div >
190
240
</ div >
191
241
< Spacer y = { 1.4 } />
192
- < Text h2 > List courses:</ Text >
242
+ < Text
243
+ p
244
+ b
245
+ size = { 16 }
246
+ css = { {
247
+ width : '100%' ,
248
+ textAlign : 'center' ,
249
+ } }
250
+ >
251
+ List courses
252
+ </ Text >
193
253
< Spacer />
194
- < Grid . Container gap = { 3 } >
195
- { listCourse . length > 0 &&
196
- listCourse . map ( ( item ) => (
197
- < Grid xs = { 4 } key = { item . id } >
198
- < Card css = { { cursor : 'pointer' } } >
199
- < Card . Body
200
- onClick = { ( ) => {
201
- navigate ( `/course/${ item . id } ` ) ;
202
- } }
203
- >
204
- < Text size = { 10 } >
205
- Id: < strong > { item . id } </ strong >
206
- </ Text >
207
- < Spacer y = { 1 } />
208
- < Text >
209
- Name: < strong > { item . data . name } </ strong >
210
- </ Text >
211
- < Text >
212
- Create at:{ ' ' }
213
- < strong >
254
+ { listCourse . length > 0 && (
255
+ < Table
256
+ selectionMode = { isDeleteMode ? 'multiple' : 'none' }
257
+ onSelectionChange = { handleChangeSelect }
258
+ color = { isDeleteMode ? 'error' : 'primary' }
259
+ selectedKeys = { selection }
260
+ >
261
+ < Table . Header >
262
+ < Table . Column width = { 200 } > ID</ Table . Column >
263
+ < Table . Column > name</ Table . Column >
264
+ < Table . Column > quantity</ Table . Column >
265
+ < Table . Column > Progress</ Table . Column >
266
+ < Table . Column width = { 190 } > Create at</ Table . Column >
267
+ < Table . Column width = { 40 } align = { 'end' } > </ Table . Column >
268
+ </ Table . Header >
269
+ < Table . Pagination
270
+ shadow
271
+ noMargin
272
+ align = "center"
273
+ rowsPerPage = { 10 }
274
+ color = { isDeleteMode ? 'error' : 'primary' }
275
+ />
276
+ < Table . Body >
277
+ { listCourse
278
+ . sort ( ( a , b ) => {
279
+ return new Date ( b . data . createdAt ) - new Date ( a . data . createdAt ) ;
280
+ } )
281
+ . map ( ( item ) => {
282
+ const progress =
283
+ (
284
+ item . data . data . filter ( ( item ) => {
285
+ return item . learned ;
286
+ } ) . length / item . data . data . length
287
+ ) . toFixed ( 2 ) * 100 ;
288
+ return (
289
+ < Table . Row key = { item . id } >
290
+ < Table . Cell > { item . id } </ Table . Cell >
291
+ < Table . Cell > { item . data . name } </ Table . Cell >
292
+ < Table . Cell > { item . data . data . length } </ Table . Cell >
293
+ < Table . Cell >
294
+ < Text
295
+ p
296
+ b
297
+ color = {
298
+ progress >= 90
299
+ ? 'success'
300
+ : progress > 0
301
+ ? 'warning'
302
+ : 'error'
303
+ }
304
+ >
305
+ { progress } %
306
+ </ Text >
307
+ < Progress
308
+ size = { 'xs' }
309
+ value = { progress }
310
+ color = {
311
+ progress >= 90
312
+ ? 'success'
313
+ : progress > 0
314
+ ? 'warning'
315
+ : 'error'
316
+ }
317
+ />
318
+ </ Table . Cell >
319
+ < Table . Cell >
214
320
{ new Date ( item . data . createdAt ) . toLocaleString ( ) }
215
- </ strong >
216
- </ Text >
217
- </ Card . Body >
218
- </ Card >
219
- </ Grid >
220
- ) ) }
221
- </ Grid . Container >
321
+ </ Table . Cell >
322
+ < Table . Cell
323
+ style = { {
324
+ display : 'flex' ,
325
+ justifyContent : 'flex-end' ,
326
+ } }
327
+ >
328
+ { ! isDeleteMode && (
329
+ < Tooltip content = { 'View detail' } >
330
+ < HiOutlineEye
331
+ size = { 20 }
332
+ color = "#005FCC"
333
+ style = { {
334
+ cursor : 'pointer' ,
335
+ } }
336
+ onClick = { ( ) => {
337
+ navigate ( `/course/${ item . id } ` ) ;
338
+ } }
339
+ />
340
+ </ Tooltip >
341
+ ) }
342
+ </ Table . Cell >
343
+ </ Table . Row >
344
+ ) ;
345
+ } ) }
346
+ </ Table . Body >
347
+ </ Table >
348
+ ) }
349
+ { selection . length > 0 && (
350
+ < Fragment >
351
+ < Spacer y = { 1 } />
352
+ < Button
353
+ auto
354
+ color = "error"
355
+ onClick = { ( ) => {
356
+ handleDelete ( ) ;
357
+ } }
358
+ css = { {
359
+ margin : '0 auto' ,
360
+ } }
361
+ >
362
+ < Text color = "#fff" > Delete selected</ Text >
363
+ </ Button >
364
+ < Text
365
+ css = { {
366
+ textAlign : 'center' ,
367
+ } }
368
+ size = { 12 }
369
+ color = "error"
370
+ >
371
+ Careful, < b > this action cannot be undone.</ b > Gods help you.
372
+ </ Text >
373
+ </ Fragment >
374
+ ) }
222
375
</ div >
223
376
) ;
224
377
} ;
0 commit comments