Skip to content

Commit 1512758

Browse files
authored
Merge pull request #232 from Markkos89/feat/db-refact
Feat/db refact + new context provider
2 parents 72c63e8 + f2ae0ac commit 1512758

File tree

13 files changed

+376
-537
lines changed

13 files changed

+376
-537
lines changed

.env.example

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,9 @@
1717
# You can generate a new secret on the command line with:
1818
# openssl rand -base64 32
1919
# https://next-auth.js.org/configuration/options#secret
20-
# NEXTAUTH_SECRET=""
20+
NEXTAUTH_SECRET=""
2121
NEXTAUTH_URL="http://localhost:3000"
2222

23-
POSTGRES_HOST=127.0.0.1
24-
POSTGRES_PORT=6500
25-
POSTGRES_USER=admin
26-
POSTGRES_PASSWORD=password123
27-
POSTGRES_DATABASE=nextauth_prisma
28-
29-
DATABASE_URL=postgresql://admin:password123@localhost:6500/nextauth_prisma?schema=public
30-
3123
POSTGRES_URL=
3224
POSTGRES_PRISMA_URL=postgresql://admin:password123@localhost:6500/nextauth_prisma?schema=public
3325
POSTGRES_URL_NON_POOLING=postgresql://admin:password123@localhost:6500/nextauth_prisma?schema=public

.eslintrc.cjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ const config = {
2929
},
3030
],
3131
"@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
32-
"@typescript-eslint/no-unsafe-assignment": "off", // or "off" if you want to disable it
33-
"@typescript-eslint/no-unsafe-call": "off", // or "off" if you want to disable it
34-
"@typescript-eslint/no-unsafe-return": "off",
35-
"@typescript-eslint/no-unsafe-member-access": "off",
32+
"@typescript-eslint/no-unsafe-assignment": 0, // or "off" if you want to disable it
33+
"@typescript-eslint/no-unsafe-call": 0, // or "off" if you want to disable it
34+
"@typescript-eslint/no-unsafe-return": 0,
35+
"@typescript-eslint/no-unsafe-member-access": 0,
3636
},
3737
};
3838

prisma/seed.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,20 @@ async function main() {
1515
// },
1616
// });
1717
// console.log({ user });
18-
19-
const lesson1 = await prisma.lessons.create({
18+
// const lesson1 = await prisma.lessons.create({
19+
// data: {
20+
// quizFileName: "lesson-4-quiz.json",
21+
// },
22+
// });
23+
// console.log({ lesson1 });
24+
const completed2 = await prisma.completedQuizzes.create({
2025
data: {
21-
quizFileName: "quiz-lesson-1.json",
26+
userId: "cll3hcuim00001wujlay766tk",
27+
lesson: "2",
28+
completed: true,
2229
},
2330
});
24-
console.log({ lesson1 });
31+
console.log({ completed2 });
2532
}
2633

2734
main()

src/contexts/AppContext.tsx

Lines changed: 21 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,24 @@
1-
import { api } from "@/utils/api";
2-
import { useSession } from "next-auth/react";
3-
import { createContext, useState } from "react";
1+
import { type IFormatedLessons } from "@/interfaces";
2+
import { createContext, useContext } from "react";
43

5-
type ContextProps = {
6-
message: string;
7-
setMessage: (message: string) => void;
8-
children: React.ReactElement;
9-
};
10-
11-
const initialState = {
12-
message: "",
13-
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
14-
setMessage: (message: string) => {},
15-
};
16-
17-
export const AppContext = createContext(initialState);
18-
19-
function Context({ children }: ContextProps) {
20-
const [message, setMessage] = useState("");
21-
const { data: sessionData } = useSession();
22-
const [fetchNow, setFetchNow] = useState(true);
23-
24-
console.log({ sessionData });
25-
26-
// Requests
27-
// - All
28-
const {
29-
// data: completedQuizzesAllData,
30-
// isLoading: completedQuizzesAllIsLoading,
31-
// refetch: refetchCompletedQuizzesAll,
32-
} = api.completedQuizzes.all.useQuery(
33-
undefined, // no input
34-
{
35-
// Disable request if no session data
36-
enabled: sessionData?.user !== undefined && fetchNow,
37-
},
38-
);
39-
40-
return (
41-
<AppContext.Provider value={{ message, setMessage }}>
42-
{children}
43-
</AppContext.Provider>
44-
);
4+
interface IAppContext {
5+
formattedLessons: IFormatedLessons;
6+
completedQuizzesSlugs: string[];
7+
lessonsWithStatus: IFormatedLessons;
458
}
469

47-
export default Context;
10+
export const AppContext = createContext<IAppContext>({
11+
formattedLessons: {
12+
projects: [],
13+
fundamentals: [],
14+
},
15+
completedQuizzesSlugs: [],
16+
lessonsWithStatus: {
17+
projects: [],
18+
fundamentals: [],
19+
},
20+
});
21+
22+
AppContext.displayName = "AcademyAppContext";
23+
24+
export const useAppContext = () => useContext(AppContext);

src/contexts/AppContextProvider.tsx

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
/* eslint-disable @typescript-eslint/no-unsafe-return */
3+
/* eslint-disable @typescript-eslint/no-unsafe-call */
4+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
5+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
6+
import { type ReactNode, useEffect, useState } from "react";
7+
import { AppContext } from "./AppContext";
8+
import { type IFormatedLessons } from "@/interfaces";
9+
import { useSession } from "next-auth/react";
10+
import { api } from "@/utils/api";
11+
12+
interface IProps {
13+
children: ReactNode;
14+
}
15+
16+
export function AppContextProvider({ children }: IProps) {
17+
const [formattedLessons, setFormattedLessons] = useState<IFormatedLessons>({
18+
projects: [],
19+
fundamentals: [],
20+
});
21+
const [completedQuizzesSlugs, setCompletedQuizzesSlugs] = useState<string[]>(
22+
[],
23+
);
24+
const [lessonsWithStatus, setLessonsWithStatus] = useState<IFormatedLessons>({
25+
projects: [],
26+
fundamentals: [],
27+
});
28+
29+
const { data: sessionData } = useSession();
30+
31+
// Requests
32+
// - All
33+
const {
34+
data: completedQuizzesAllData,
35+
// isLoading: completedQuizzesAllIsLoading,
36+
// refetch: refetchCompletedQuizzesAll,
37+
} = api.completedQuizzes.all.useQuery(
38+
undefined, // no input
39+
{
40+
// Disable request if no session data
41+
enabled: sessionData?.user !== undefined,
42+
},
43+
);
44+
45+
useEffect(() => {
46+
if (completedQuizzesAllData) {
47+
const slugs = completedQuizzesAllData.map((quiz: any) => quiz.lesson);
48+
if (slugs !== completedQuizzesSlugs) setCompletedQuizzesSlugs(slugs);
49+
}
50+
// eslint-disable-next-line react-hooks/exhaustive-deps
51+
}, [completedQuizzesAllData]);
52+
53+
const fetchFromDirs = async () => {
54+
const lessonsData = await fetch("/api/readfiles").then((res) => res.json());
55+
56+
const lessonsFormatResult: IFormatedLessons = lessonsData.reduce(
57+
(acc: any, curr: any) => {
58+
if (!acc[curr.path]) acc[curr.path] = [];
59+
60+
acc[curr.path].push(curr);
61+
return acc;
62+
},
63+
{},
64+
);
65+
66+
setFormattedLessons(lessonsFormatResult);
67+
};
68+
69+
useEffect(() => {
70+
void fetchFromDirs();
71+
}, []);
72+
73+
useEffect(() => {
74+
if (
75+
sessionData?.user &&
76+
formattedLessons.fundamentals &&
77+
formattedLessons.projects &&
78+
completedQuizzesSlugs.length !== 0
79+
) {
80+
const projectsWithCompleteStatus = formattedLessons.projects.map(
81+
(lesson) => {
82+
const completed = completedQuizzesSlugs.includes(lesson.slug);
83+
return { ...lesson, completed };
84+
},
85+
);
86+
87+
const obj = {
88+
projects: projectsWithCompleteStatus,
89+
fundamentals: formattedLessons.fundamentals,
90+
};
91+
92+
setLessonsWithStatus(obj);
93+
}
94+
// eslint-disable-next-line react-hooks/exhaustive-deps
95+
}, [completedQuizzesSlugs, formattedLessons]);
96+
97+
return (
98+
<AppContext.Provider
99+
value={{ formattedLessons, completedQuizzesSlugs, lessonsWithStatus }}
100+
>
101+
{children}
102+
</AppContext.Provider>
103+
);
104+
}

src/interfaces/index.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
export interface Lesson {
3+
frontMatter: any;
4+
slug: string;
5+
path: string;
6+
completed?: boolean;
7+
}
8+
export interface Lessons {
9+
lessons: {
10+
frontMatter: any;
11+
slug: string;
12+
}[];
13+
}
14+
15+
export interface IFormatedLessons {
16+
projects: Project[];
17+
fundamentals: Fundamental[];
18+
}
19+
20+
export interface Fundamental {
21+
path: Path;
22+
frontMatter: FundamentalFrontMatter;
23+
slug: string;
24+
}
25+
26+
export interface FundamentalFrontMatter {
27+
title: string;
28+
description: string;
29+
icons: string[];
30+
authors?: string[];
31+
i18n?: string;
32+
author?: string[] | string;
33+
}
34+
35+
export enum Path {
36+
Fundamentals = "fundamentals",
37+
}
38+
39+
export interface Project {
40+
path: string;
41+
frontMatter: ProjectFrontMatter;
42+
slug: string;
43+
completed?: boolean;
44+
}
45+
46+
export interface ProjectFrontMatter {
47+
title: string;
48+
description: string;
49+
icons: string[];
50+
i18n?: string;
51+
author?: string;
52+
}

src/pages/_app.tsx

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// Imports
22
// ========================================================
3-
import React from "react";
3+
import React, { type ReactElement, type ReactNode } from "react";
4+
import { type NextPage } from "next";
5+
import { type AppProps } from "next/app";
46

5-
import { type AppType } from "next/app";
67
import { type Session } from "next-auth";
78
import { SessionProvider } from "next-auth/react";
89
import { api } from "@/utils/api";
@@ -30,10 +31,8 @@ import { ChakraProvider } from "@chakra-ui/react";
3031
import { theme } from "@/theme";
3132
import { MDXProvider } from "@mdx-js/react";
3233
import Components from "@/components/mdx/Components";
33-
import Layout from "@/components/Layout";
3434
import { env } from "@/env.mjs";
35-
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
36-
35+
import { AppContextProvider } from "@/contexts/AppContextProvider";
3736
// Config
3837
// ========================================================
3938
/**
@@ -70,31 +69,39 @@ const wagmiConfig = createConfig({
7069
publicClient,
7170
});
7271

72+
// eslint-disable-next-line @typescript-eslint/ban-types
73+
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
74+
getLayout?: (page: ReactElement) => ReactNode;
75+
};
76+
77+
type AppPropsWithLayout<P> = AppProps<P> & {
78+
Component: NextPageWithLayout<P>;
79+
};
80+
7381
// App Wrapper Component
7482
// ========================================================
75-
const MyApp: AppType<{ session: Session | null }> = ({
83+
const MyApp = ({
7684
Component,
7785
pageProps,
78-
}) => {
86+
}: AppPropsWithLayout<{ session: Session }>) => {
87+
const getLayout = Component.getLayout || ((page) => page);
88+
7989
return (
80-
<ChakraProvider theme={theme}>
81-
<WagmiConfig config={wagmiConfig}>
90+
<WagmiConfig config={wagmiConfig}>
91+
<ChakraProvider theme={theme}>
8292
<SessionProvider refetchInterval={0} session={pageProps.session}>
8393
<RainbowKitSiweNextAuthProvider>
8494
<RainbowKitProvider chains={chains} initialChain={polygonMumbai}>
8595
<MDXProvider components={Components}>
86-
<Layout>
87-
<>
88-
<Component {...pageProps} />
89-
<ReactQueryDevtools />
90-
</>
91-
</Layout>
96+
<AppContextProvider>
97+
{getLayout(<Component {...pageProps} />)}
98+
</AppContextProvider>
9299
</MDXProvider>
93100
</RainbowKitProvider>
94101
</RainbowKitSiweNextAuthProvider>
95102
</SessionProvider>
96-
</WagmiConfig>
97-
</ChakraProvider>
103+
</ChakraProvider>
104+
</WagmiConfig>
98105
);
99106
};
100107

src/pages/api/auth/[...nextauth].ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import { authOptions } from "@/server/auth";
88
// Auth
99
// ========================================================
1010
const Auth = async (req: NextApiRequest, res: NextApiResponse) => {
11-
console.log("In [...nextauth].ts");
12-
1311
const authOpts: NextAuthOptions = authOptions({ req });
1412

1513
if (!Array.isArray(req.query.nextauth)) {

0 commit comments

Comments
 (0)