Skip to content

Commit aec88ce

Browse files
fix: resolve the netflify timeout error on learning modules
1 parent 420d6f0 commit aec88ce

File tree

4 files changed

+74
-24
lines changed

4 files changed

+74
-24
lines changed

src/pages/communities/[slug]/challenges/[challenge_id]/learning-modules/[id].tsx

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { initChallengeNavigationMenu } from "@/store/feature/communities/navigat
1414
import { setColors } from "@/store/feature/ui.slice";
1515
import useNavigation from "@/hooks/useNavigation";
1616
import { GetServerSideProps } from "next";
17-
import { wrapper } from "@/store";
17+
import { IRootState, wrapper } from "@/store";
1818
import { fetchCurrentCommunity } from "@/store/services/community.service";
1919
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
2020
import ChallengeOverviewCard from "@/components/cards/challenge/Overview";
@@ -23,6 +23,10 @@ import { fetchChallenge } from "@/store/services/communities/challenges";
2323
import PageNavigation from "@/components/sections/courses/PageNavigation";
2424
import ChallengeCard from "@/components/cards/challenge/Challenge";
2525
import { useTranslation } from "next-i18next";
26+
import { useMultiSelector } from "@/hooks/useTypedSelector";
27+
import Section from "@/components/ui/Section";
28+
import Loader from "@/components/ui/Loader";
29+
import { useRouter } from "next/router";
2630

2731
/**
2832
* Learning module page props interfae
@@ -39,6 +43,11 @@ interface LearningModulePageProps {
3943
};
4044
}
4145

46+
interface LearningModuleMultiselector {
47+
learningModule: LearningModule,
48+
loading: boolean
49+
}
50+
4251
/**
4352
* Learning module module view page
4453
* @date 4/24/2023 - 8:35:52 PM
@@ -48,27 +57,45 @@ interface LearningModulePageProps {
4857
* @returns
4958
*/
5059
export default function LearningModulePage(props: LearningModulePageProps) {
51-
const { community, learningModule, challenge } = props.pageProps;
60+
const { community, challenge } = props.pageProps;
61+
const { learningModule, loading } = useMultiSelector<unknown, LearningModuleMultiselector>({
62+
learningModule: (state: IRootState) => state.learningModules.current,
63+
loading: (state: IRootState) => state.learningModules.loading
64+
})
5265
const dispatch = useDispatch();
5366
const { t } = useTranslation();
5467
const navigation = useNavigation();
68+
const router = useRouter()
69+
const { query, locale } = router
5570

5671
useEffect(() => {
5772
dispatch(setCurrentCommunity(community));
5873
dispatch(setCurrentLearningModule(learningModule));
5974
dispatch(setColors(community.colors));
6075
dispatch(initChallengeNavigationMenu(navigation.community));
61-
}, [community, learningModule, navigation.community]);
76+
dispatch(findLearningModule({ id: query?.id as string, locale }))
77+
}, [community?.colors, locale]);
78+
6279

6380
const title = getMetadataTitle(learningModule?.title);
6481
const descriptions = getMetadataDescription(learningModule?.description);
6582

66-
const paths = useMemo(() => [challenge.name, learningModule?.title], [challenge.name, learningModule?.title]);
83+
const paths = useMemo(() => [challenge.name, learningModule?.title], [challenge.name, learningModule]);
6784

6885
const isLastLearningModule = useMemo(() => {
86+
if (!learningModule) return false
6987
if (!challenge.learningModules || !challenge.learningModules.length) return false;
7088
return learningModule.id === challenge.learningModules[challenge.learningModules.length - 1].id;
71-
}, [learningModule.id, challenge.learningModules]);
89+
}, [learningModule, challenge.learningModules]);
90+
91+
if (loading)
92+
93+
return (
94+
<Section className="h-[50vh] flex items-center justify-center">
95+
<Loader />
96+
</Section>
97+
);
98+
7299
return (
73100
<>
74101
<Head>
@@ -109,22 +136,19 @@ export const getServerSideProps: GetServerSideProps = wrapper.getServerSideProps
109136
try {
110137
const communitySlug = params?.slug as string;
111138
const challenge_id = params?.challenge_id as string;
112-
const learningModule_id = params?.id as string;
113139

114-
const [{ data: community }, { data: challenge }, { data: learningModule }, translations] = await Promise.all([
140+
const [{ data: community }, { data: challenge }, translations] = await Promise.all([
115141
store.dispatch(fetchCurrentCommunity({ slug: communitySlug, locale })),
116142
store.dispatch(fetchChallenge({ id: challenge_id, relations: ["learning-modules", "rubric"], locale })),
117-
store.dispatch(findLearningModule({ id: learningModule_id, locale })),
118143
serverSideTranslations(locale as string),
119144
]);
120145

121-
if (Object.entries(community).length === 0 || Object.entries(challenge).length === 0 || Object.entries(learningModule).length === 0)
146+
if (Object.entries(community).length === 0 || Object.entries(challenge).length === 0)
122147
throw new Error("Failed to fetch learning module");
123148

124149
return {
125150
props: {
126151
community,
127-
learningModule,
128152
challenge,
129153
...translations,
130154
},

src/pages/communities/[slug]/courses/[course_slug]/learning-modules/[id].tsx

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { getMetadataDescription, getMetadataTitle } from "@/utilities/Metadata";
99
import DefaultLayout from "@/components/layout/Default";
1010
import Header from "@/components/sections/learning-modules/Header";
1111
import { initCourseNavigationMenu } from "@/store/feature/communities/navigation.slice";
12-
import { wrapper } from "@/store";
12+
import { IRootState, wrapper } from "@/store";
1313
import { fetchCurrentCommunity } from "@/store/services/community.service";
1414
import { fetchCourse } from "@/store/services/course.service";
1515
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
@@ -20,6 +20,10 @@ import ChallengeCard from "@/components/cards/challenge/Challenge";
2020
import { useTranslation } from "next-i18next";
2121
import PageNavigation from "@/components/sections/courses/PageNavigation";
2222
import { NotFoundError } from "@/utilities/errors/NotFoundError";
23+
import { useRouter } from "next/router";
24+
import { useMultiSelector } from "@/hooks/useTypedSelector";
25+
import Section from "@/components/ui/Section";
26+
import Loader from "@/components/ui/Loader";
2327

2428
/**
2529
* Learning module page props interfae
@@ -32,11 +36,15 @@ interface LearningModulePageProps {
3236
pageProps: {
3337
community: Community;
3438
course: Course;
35-
learningModule: LearningModule;
3639
challenges: Challenge[];
3740
};
3841
}
3942

43+
interface LearningModuleMultiselector {
44+
learningModule: LearningModule,
45+
loading: boolean
46+
}
47+
4048
/**
4149
* Learning module module view page
4250
* @date 4/24/2023 - 8:35:52 PM
@@ -46,23 +54,37 @@ interface LearningModulePageProps {
4654
* @returns
4755
*/
4856
export default function LearningModulePage(props: LearningModulePageProps): ReactElement {
49-
const { course, learningModule, community } = props.pageProps;
57+
const { course, community } = props.pageProps;
58+
const { learningModule, loading } = useMultiSelector<unknown, LearningModuleMultiselector>({
59+
learningModule: (state: IRootState) => state.learningModules.current,
60+
loading: (state: IRootState) => state.learningModules.loading
61+
})
5062
const dispatch = useDispatch();
5163
const navigation = useNavigation();
5264
const { t } = useTranslation();
65+
const router = useRouter()
66+
const { query, locale } = router
5367

5468
useEffect(() => {
5569
dispatch(initCourseNavigationMenu(navigation.community));
56-
}, [dispatch]);
70+
dispatch(findLearningModule({ id: query?.id as string, locale }))
71+
}, [dispatch, locale]);
5772

58-
const title = getMetadataTitle(learningModule.title!, course.name!);
59-
const descriptions = getMetadataDescription(learningModule.description!);
73+
const title = useMemo(() => getMetadataTitle(learningModule?.title, course.name!), [course.name, learningModule]);
74+
const descriptions = useMemo(() => getMetadataDescription(learningModule?.description), [learningModule]);
6075
const paths = useMemo(() => [learningModule?.title], [learningModule?.title]);
6176
const isLastLearningModule = useMemo(() => {
77+
if (!learningModule) return false
6278
if (!course.learningModules || !course.learningModules.length) return false;
6379
return learningModule.id === course.learningModules[course.learningModules.length - 1].id;
64-
}, [learningModule.id, course.learningModules]);
80+
}, [learningModule, course.learningModules]);
6581

82+
if (loading)
83+
return (
84+
<Section className="h-[50vh] flex items-center justify-center">
85+
<Loader />
86+
</Section>
87+
);
6688
return (
6789
<>
6890
<Head>
@@ -107,20 +129,17 @@ export const getServerSideProps = wrapper.getServerSideProps((store) => async ({
107129
try {
108130
const communitySlug = params?.slug as string;
109131
const courseSlug = params?.course_slug as string;
110-
const id = params?.id as string;
111132

112-
const [{ data: community }, { data: course }, { data: learningModule }, translations] = await Promise.all([
133+
const [{ data: community }, { data: course }, translations] = await Promise.all([
113134
store.dispatch(fetchCurrentCommunity({ slug: communitySlug, locale })),
114135
store.dispatch(fetchCourse({ slug: courseSlug, locale })),
115-
store.dispatch(findLearningModule({ id, locale })),
116136
serverSideTranslations(locale as string),
117137
]);
118-
if (!community || !course || !learningModule) throw new NotFoundError();
138+
if (!community || !course) throw new NotFoundError();
119139
return {
120140
props: {
121141
community,
122142
course,
123-
learningModule,
124143
...translations,
125144
},
126145
};

src/store/feature/learningModules.slice.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ import { HYDRATE } from "next-redux-wrapper";
1313
interface LearningModulesState {
1414
list: LearningModule[];
1515
current?: LearningModule | null;
16+
loading: boolean;
1617
}
1718

1819
const initialState: LearningModulesState = {
1920
list: [],
2021
current: null,
22+
loading: false,
2123
};
2224

2325
export const learningModulesSlice = createSlice({
@@ -30,6 +32,9 @@ export const learningModulesSlice = createSlice({
3032
setLearningModuleList(state, action) {
3133
state.list = action.payload;
3234
},
35+
setLoading(state, action) {
36+
state.loading = action.payload;
37+
},
3338
},
3439
extraReducers: (builder) => {
3540
builder.addCase(HYDRATE, (state, action) => {
@@ -58,5 +63,5 @@ export const checkAnswer = async (ref: string) => {
5863
return data;
5964
};
6065

61-
export const { setCurrentLearningModule, setLearningModuleList } = learningModulesSlice.actions;
66+
export const { setCurrentLearningModule, setLearningModuleList, setLoading } = learningModulesSlice.actions;
6267
export default learningModulesSlice;

src/store/services/learningModules.service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { createApi } from "@reduxjs/toolkit/query/react";
22
import baseQuery from "@/config/baseQuery";
3-
import { setCurrentLearningModule, setLearningModuleList } from "../feature/learningModules.slice";
3+
import { setCurrentLearningModule, setLearningModuleList, setLoading } from "../feature/learningModules.slice";
44

55
/**
66
* Learning module api service
@@ -21,8 +21,10 @@ export const learningModulesService = createApi({
2121
},
2222
}),
2323
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
24+
dispatch(setLoading(true));
2425
const { data } = await queryFulfilled;
2526
dispatch(setCurrentLearningModule(data));
27+
dispatch(setLoading(false));
2628
},
2729
}),
2830

0 commit comments

Comments
 (0)