Skip to content

Commit 74cca8b

Browse files
authored
Merge pull request #218 from Markkos89/feat/t3-siwe
feat: added completed badge to completed lessons quizzes
2 parents 5d79cd8 + e769144 commit 74cca8b

File tree

31 files changed

+1093
-223
lines changed

31 files changed

+1093
-223
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,5 @@ yarn-error.log*
4040

4141
# typescript
4242
*.tsbuildinfo
43+
44+
todo.md

src/contexts/AppContext.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { useSession } from "next-auth/react";
2+
import { createContext, useState } from "react";
3+
4+
type ContextProps = {
5+
message: string;
6+
setMessage: (message: string) => void;
7+
children: React.ReactElement;
8+
};
9+
10+
const initialState = {
11+
message: "",
12+
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
13+
setMessage: (message: string) => {},
14+
};
15+
16+
export const AppContext = createContext(initialState);
17+
18+
function Context({ children }: ContextProps) {
19+
const [message, setMessage] = useState("");
20+
const { data: sessionData } = useSession();
21+
22+
console.log({ sessionData });
23+
24+
return (
25+
<AppContext.Provider value={{ message, setMessage }}>
26+
{children}
27+
</AppContext.Provider>
28+
);
29+
}
30+
31+
export default Context;

src/pages/getting-started.tsx

Lines changed: 167 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,117 @@ import {
1616
Link,
1717
Divider,
1818
Box,
19+
Badge,
1920
} from "@chakra-ui/react";
2021
import fs from "fs";
2122
import path from "path";
2223
import matter from "gray-matter";
2324
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";
2528

26-
interface Lesson {
29+
export interface Lesson {
2730
frontMatter: any;
2831
slug: string;
2932
path: string;
33+
completed?: boolean;
3034
}
31-
interface LessonProps {
35+
export interface Lessons {
3236
lessons: {
3337
frontMatter: any;
3438
slug: string;
3539
}[];
3640
}
3741

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+
}
4280

43-
useEffect(() => {
44-
const result: LessonProps = lessons.reduce((acc: any, curr: any) => {
45-
if (!acc[curr.path]) acc[curr.path] = [];
81+
const GettingStarted: React.FC<Lessons> = ({ lessons }) => {
82+
const [formattedLessons, setFormattedLessons] = useState<LessonProps>();
83+
const [completedQuizzesSlugs, setCompletedQuizzesSlugs] = useState<string[]>(
84+
[]
85+
);
86+
87+
const [fetchNow, setFetchNow] = useState<boolean>(true);
88+
const { data: sessionData } = useSession();
89+
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] = [];
46111

47-
acc[curr.path].push(curr);
48-
return acc;
49-
}, {});
112+
acc[curr.path].push(curr);
113+
return acc;
114+
}, {});
50115

51-
setFormattedLessons(result);
52-
}, [lessons]);
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+
126+
setFormattedLessons({ ...result, projects: completedQuizzes });
127+
setFetchNow(false);
128+
}
129+
}, [completedQuizzesAllData, fetchNow, lessons]);
53130

54131
return (
55132
<Flex
@@ -96,44 +173,65 @@ const GettingStarted: React.FC<LessonProps> = ({ lessons }) => {
96173
>
97174
Current Lessons
98175
</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-
}}
176+
{formattedLessons
177+
? Object.entries(formattedLessons).map((track: any, idx: number) => {
178+
return (
179+
<UnorderedList
180+
listStyleType="none"
181+
textAlign="center"
182+
as="div"
183+
key={idx}
184+
>
185+
<Heading size="md" color="yellow.300">
186+
{track[0].toUpperCase()}
187+
</Heading>
188+
<>
189+
{track[1].map((lesson: Lesson, idx: number) => (
190+
<ListItem
191+
key={idx}
192+
my="2"
193+
py="2"
194+
maxW="40vw"
195+
margin="0 auto"
127196
>
128-
{lesson.frontMatter.title}
129-
</Button>
130-
</Link>
131-
</ListItem>
132-
))}
133-
</>
134-
</UnorderedList>
135-
);
136-
})}
197+
<Link
198+
as={NextLink}
199+
href={`/lessons/${lesson.path}/${lesson.slug}`}
200+
passHref
201+
>
202+
<Button
203+
height="auto"
204+
style={{
205+
whiteSpace: "normal",
206+
wordWrap: "break-word",
207+
padding: "0.5rem",
208+
width: "100%",
209+
fontSize: "xl",
210+
}}
211+
>
212+
{lesson.frontMatter.title}
213+
{lesson &&
214+
lesson.completed &&
215+
lesson.completed === true ? (
216+
<Badge
217+
ml="1"
218+
alignItems={"flex-end"}
219+
colorScheme="green"
220+
position="absolute"
221+
right={3}
222+
>
223+
Completed
224+
</Badge>
225+
) : null}
226+
</Button>
227+
</Link>
228+
</ListItem>
229+
))}
230+
</>
231+
</UnorderedList>
232+
);
233+
})
234+
: null}
137235
<Divider />
138236

139237
<Heading apply="mdx.h3" as="h3" fontSize="2xl" textAlign="center" p={5}>
@@ -205,8 +303,6 @@ const GettingStarted: React.FC<LessonProps> = ({ lessons }) => {
205303
);
206304
};
207305

208-
export default GettingStarted;
209-
210306
export const getStaticProps = () => {
211307
const contentDir = path.join(CONTENT_PATH);
212308
const directories = fs.readdirSync(path.resolve(contentDir));
@@ -221,18 +317,30 @@ export const getStaticProps = () => {
221317
);
222318

223319
const { data: frontMatter } = matter(markdownWithMeta);
224-
lessons.push({
225-
path: folder,
226-
frontMatter,
227-
slug: file.replace(".mdx", ""),
228-
});
320+
if (folder === "fundamentals") {
321+
lessons.push({
322+
path: folder,
323+
frontMatter,
324+
slug: file.replace(".mdx", ""),
325+
});
326+
} else {
327+
lessons.push({
328+
path: folder,
329+
frontMatter,
330+
slug: file.replace(".mdx", ""),
331+
completed: false,
332+
});
333+
}
229334
}
230335
});
231336
}
232337
});
338+
233339
return {
234340
props: {
235341
lessons,
236342
},
237343
};
238344
};
345+
346+
export default GettingStarted;

0 commit comments

Comments
 (0)