@@ -16,40 +16,147 @@ import {
16
16
Link ,
17
17
Divider ,
18
18
Box ,
19
+ Badge ,
19
20
} from "@chakra-ui/react" ;
20
21
import fs from "fs" ;
21
22
import path from "path" ;
22
23
import matter from "gray-matter" ;
23
24
import { CONTENT_PATH } from "@/lib/constants" ;
24
- import { useEffect , useState } from "react" ;
25
+ import { useMemo , useState } from "react" ;
26
+ import { api } from "@/utils/api" ;
27
+ import { useSession } from "next-auth/react" ;
25
28
26
- interface Lesson {
29
+ export interface Lesson {
27
30
frontMatter : any ;
28
31
slug : string ;
29
32
path : string ;
33
+ completed ?: boolean ;
30
34
}
31
- interface LessonProps {
35
+ export interface Lessons {
32
36
lessons : {
33
37
frontMatter : any ;
34
38
slug : string ;
35
39
} [ ] ;
36
40
}
37
41
38
- const GettingStarted : React . FC < LessonProps > = ( { lessons } ) => {
39
- const [ formattedLessons , setFormattedLessons ] = useState < LessonProps > ( {
40
- lessons : [ ] ,
41
- } ) ;
42
+ export interface LessonProps {
43
+ projects : Project [ ] ;
44
+ fundamentals : Fundamental [ ] ;
45
+ }
46
+
47
+ export interface Fundamental {
48
+ path : Path ;
49
+ frontMatter : FundamentalFrontMatter ;
50
+ slug : string ;
51
+ }
52
+
53
+ export interface FundamentalFrontMatter {
54
+ title : string ;
55
+ description : string ;
56
+ icons : string [ ] ;
57
+ authors ?: string [ ] ;
58
+ i18n ?: string ;
59
+ author ?: string [ ] | string ;
60
+ }
61
+
62
+ export enum Path {
63
+ Fundamentals = "fundamentals" ,
64
+ }
65
+
66
+ export interface Project {
67
+ path : string ;
68
+ frontMatter : ProjectFrontMatter ;
69
+ slug : string ;
70
+ completed : boolean ;
71
+ }
72
+
73
+ export interface ProjectFrontMatter {
74
+ title : string ;
75
+ description : string ;
76
+ icons : string [ ] ;
77
+ i18n ?: string ;
78
+ author ?: string ;
79
+ }
80
+
81
+ const GettingStarted : React . FC < Lessons > = ( { lessons } ) => {
82
+ const [ formattedLessons , setFormattedLessons ] = useState < LessonProps > ( ) ;
83
+ const [ completedQuizzesSlugs , setCompletedQuizzesSlugs ] = useState < string [ ] > (
84
+ [ ]
85
+ ) ;
42
86
43
- useEffect ( ( ) => {
44
- const result : LessonProps = lessons . reduce ( ( acc : any , curr : any ) => {
45
- if ( ! acc [ curr . path ] ) acc [ curr . path ] = [ ] ;
87
+ const [ fetchNow , setFetchNow ] = useState < boolean > ( true ) ;
88
+ const { data : sessionData } = useSession ( ) ;
46
89
47
- acc [ curr . path ] . push ( curr ) ;
48
- return acc ;
49
- } , { } ) ;
90
+ // Requests
91
+ // - All
92
+ const {
93
+ data : completedQuizzesAllData ,
94
+ isLoading : completedQuizzesAllIsLoading ,
95
+ // refetch: completedQuizzesAllRefetch,
96
+ } = api . completedQuizzes . all . useQuery (
97
+ undefined , // no input
98
+ {
99
+ // Disable request if no session data
100
+ enabled : sessionData ?. user !== undefined && fetchNow ,
101
+ onSuccess : ( ) => {
102
+ // setNewTodo(""); // reset input form
103
+ } ,
104
+ }
105
+ ) ;
106
+
107
+ useMemo ( ( ) => {
108
+ if ( completedQuizzesAllData ?. length && fetchNow ) {
109
+ const result : LessonProps = lessons . reduce ( ( acc : any , curr : any ) => {
110
+ if ( ! acc [ curr . path ] ) acc [ curr . path ] = [ ] ;
111
+
112
+ acc [ curr . path ] . push ( curr ) ;
113
+ return acc ;
114
+ } , { } ) ;
115
+
116
+ let completedQuizzes : Project [ ] = [ ] ;
117
+ const completedSlugs : string [ ] = completedQuizzesAllData ?. map (
118
+ ( quiz : any ) => quiz . lesson . replace ( "quiz-lesson-" , "" ) || [ ]
119
+ ) ;
120
+ completedQuizzes = result ?. projects ?. map ( ( project : Project ) => {
121
+ if ( completedSlugs . includes ( project . slug ) ) project . completed = true ;
122
+ else project . completed = false ;
123
+ return project ;
124
+ } ) ;
125
+ // setFormattedLessons({ ...result, projects: completedQuizzes });
126
+
127
+ console . log ( { completedQuizzes } ) ;
128
+
129
+ setFormattedLessons ( { ...result , projects : completedQuizzes } ) ;
130
+ setFetchNow ( false ) ;
131
+ }
132
+ } , [ completedQuizzesAllData , fetchNow , lessons ] ) ;
50
133
51
- setFormattedLessons ( result ) ;
52
- } , [ lessons ] ) ;
134
+ // useMemo(() => {
135
+ // // get the slug of each completedQuizzesAllData from name
136
+ // if (!completedQuizzesAllIsLoading) {
137
+ // const completedQuizzesSlugsResult =
138
+ // completedQuizzesAllData?.map((quiz: any) =>
139
+ // quiz.lesson.replace("quiz-lesson-", "")
140
+ // ) || [];
141
+ // setCompletedQuizzesSlugs(completedQuizzesSlugsResult);
142
+ // }
143
+ // }, [completedQuizzesAllData, completedQuizzesAllIsLoading]);
144
+
145
+ // useMemo(() => {
146
+ // if (formattedLessons?.projects.length && completedQuizzesSlugs.length > 0) {
147
+ // const completedQuizzes = formattedLessons?.projects?.map(
148
+ // (project: Project) => {
149
+ // if (completedQuizzesSlugs.includes(project.slug))
150
+ // project.completed = true;
151
+ // else project.completed = false;
152
+ // return project;
153
+ // }
154
+ // );
155
+ // setFormattedLessons({ ...formattedLessons, projects: completedQuizzes });
156
+ // }
157
+ // }, [completedQuizzesSlugs, formattedLessons]);
158
+
159
+ // console.log({ f: formattedLessons, completedQuizzesAllData });
53
160
54
161
return (
55
162
< Flex
@@ -96,44 +203,65 @@ const GettingStarted: React.FC<LessonProps> = ({ lessons }) => {
96
203
>
97
204
Current Lessons
98
205
</ Heading >
99
- { Object . entries ( formattedLessons ) . map ( ( track : any , idx : number ) => {
100
- return (
101
- < UnorderedList
102
- listStyleType = "none"
103
- textAlign = "center"
104
- as = "div"
105
- key = { idx }
106
- >
107
- < Heading size = "md" color = "yellow.300" >
108
- { track [ 0 ] . toUpperCase ( ) }
109
- </ Heading >
110
- < >
111
- { track [ 1 ] . map ( ( lesson : Lesson , idx : number ) => (
112
- < ListItem key = { idx } my = "2" py = "2" maxW = "40vw" margin = "0 auto" >
113
- < Link
114
- as = { NextLink }
115
- href = { `/lessons/${ lesson . path } /${ lesson . slug } ` }
116
- passHref
117
- >
118
- < Button
119
- height = "auto"
120
- style = { {
121
- whiteSpace : "normal" ,
122
- wordWrap : "break-word" ,
123
- padding : "0.5rem" ,
124
- width : "100%" ,
125
- fontSize : "xl" ,
126
- } }
206
+ { formattedLessons
207
+ ? Object . entries ( formattedLessons ) . map ( ( track : any , idx : number ) => {
208
+ return (
209
+ < UnorderedList
210
+ listStyleType = "none"
211
+ textAlign = "center"
212
+ as = "div"
213
+ key = { idx }
214
+ >
215
+ < Heading size = "md" color = "yellow.300" >
216
+ { track [ 0 ] . toUpperCase ( ) }
217
+ </ Heading >
218
+ < >
219
+ { track [ 1 ] . map ( ( lesson : Lesson , idx : number ) => (
220
+ < ListItem
221
+ key = { idx }
222
+ my = "2"
223
+ py = "2"
224
+ maxW = "40vw"
225
+ margin = "0 auto"
127
226
>
128
- { lesson . frontMatter . title }
129
- </ Button >
130
- </ Link >
131
- </ ListItem >
132
- ) ) }
133
- </ >
134
- </ UnorderedList >
135
- ) ;
136
- } ) }
227
+ < Link
228
+ as = { NextLink }
229
+ href = { `/lessons/${ lesson . path } /${ lesson . slug } ` }
230
+ passHref
231
+ >
232
+ < Button
233
+ height = "auto"
234
+ style = { {
235
+ whiteSpace : "normal" ,
236
+ wordWrap : "break-word" ,
237
+ padding : "0.5rem" ,
238
+ width : "100%" ,
239
+ fontSize : "xl" ,
240
+ } }
241
+ >
242
+ { lesson . frontMatter . title }
243
+ { lesson &&
244
+ lesson . completed &&
245
+ lesson . completed === true ? (
246
+ < Badge
247
+ ml = "1"
248
+ alignItems = { "flex-end" }
249
+ colorScheme = "green"
250
+ position = "absolute"
251
+ right = { 3 }
252
+ >
253
+ Completed
254
+ </ Badge >
255
+ ) : null }
256
+ </ Button >
257
+ </ Link >
258
+ </ ListItem >
259
+ ) ) }
260
+ </ >
261
+ </ UnorderedList >
262
+ ) ;
263
+ } )
264
+ : null }
137
265
< Divider />
138
266
139
267
< Heading apply = "mdx.h3" as = "h3" fontSize = "2xl" textAlign = "center" p = { 5 } >
@@ -205,8 +333,6 @@ const GettingStarted: React.FC<LessonProps> = ({ lessons }) => {
205
333
) ;
206
334
} ;
207
335
208
- export default GettingStarted ;
209
-
210
336
export const getStaticProps = ( ) => {
211
337
const contentDir = path . join ( CONTENT_PATH ) ;
212
338
const directories = fs . readdirSync ( path . resolve ( contentDir ) ) ;
@@ -221,18 +347,30 @@ export const getStaticProps = () => {
221
347
) ;
222
348
223
349
const { data : frontMatter } = matter ( markdownWithMeta ) ;
224
- lessons . push ( {
225
- path : folder ,
226
- frontMatter,
227
- slug : file . replace ( ".mdx" , "" ) ,
228
- } ) ;
350
+ if ( folder === "fundamentals" ) {
351
+ lessons . push ( {
352
+ path : folder ,
353
+ frontMatter,
354
+ slug : file . replace ( ".mdx" , "" ) ,
355
+ } ) ;
356
+ } else {
357
+ lessons . push ( {
358
+ path : folder ,
359
+ frontMatter,
360
+ slug : file . replace ( ".mdx" , "" ) ,
361
+ completed : false ,
362
+ } ) ;
363
+ }
229
364
}
230
365
} ) ;
231
366
}
232
367
} ) ;
368
+
233
369
return {
234
370
props : {
235
371
lessons,
236
372
} ,
237
373
} ;
238
374
} ;
375
+
376
+ export default GettingStarted ;
0 commit comments