diff --git a/nextjs/src/app/course/[courseName]/calendar/CourseCalendar.tsx b/nextjs/src/app/course/[courseName]/calendar/CourseCalendar.tsx
index 698a1b3..150278e 100644
--- a/nextjs/src/app/course/[courseName]/calendar/CourseCalendar.tsx
+++ b/nextjs/src/app/course/[courseName]/calendar/CourseCalendar.tsx
@@ -3,20 +3,21 @@ import { getDateFromStringOrThrow } from "@/models/local/timeUtils";
import { useCourseContext } from "../context/courseContext";
import { getMonthsBetweenDates } from "./calendarMonthUtils";
import { CalendarMonth } from "./CalendarMonth";
+import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
export default function CourseCalendar() {
- // const {
- // localCourse: {
- // settings: { startDate, endDate },
- // },
- // } = useCourseContext();
+ const { courseName } = useCourseContext();
+ const { data: settings } = useLocalCourseSettingsQuery(courseName);
- // const startDateTime = getDateFromStringOrThrow(
- // startDate,
- // "course start date"
- // );
- // const endDateTime = getDateFromStringOrThrow(endDate, "course end date");
- // const months = getMonthsBetweenDates(startDateTime, endDateTime);
+ const startDateTime = getDateFromStringOrThrow(
+ settings.startDate,
+ "course start date"
+ );
+ const endDateTime = getDateFromStringOrThrow(
+ settings.endDate,
+ "course end date"
+ );
+ const months = getMonthsBetweenDates(startDateTime, endDateTime);
return (
Month Goes Here
- {/* {months.map((month) => (
+ {months.map((month) => (
- ))} */}
+ ))}
);
}
diff --git a/nextjs/src/app/course/[courseName]/calendar/Day.tsx b/nextjs/src/app/course/[courseName]/calendar/Day.tsx
index e640758..7e9b618 100644
--- a/nextjs/src/app/course/[courseName]/calendar/Day.tsx
+++ b/nextjs/src/app/course/[courseName]/calendar/Day.tsx
@@ -1,93 +1,29 @@
"use client";
-
-import { getDateFromStringOrThrow } from "@/models/local/timeUtils";
import { useCourseContext } from "../context/courseContext";
+import { useModuleNamesQuery } from "@/hooks/localCourse/localCoursesHooks";
+import DayItemsInModule from "./DayItemsInModule";
export default function Day({ day, month }: { day: Date; month: number }) {
- const {
- localCourse: { modules },
- startItemDrag,
- endItemDrag,
- itemDrop,
- } = useCourseContext();
-
+ const { courseName, itemDrop } = useCourseContext();
+ const { data: moduleNames } = useModuleNamesQuery(courseName);
const isInSameMonth = day.getMonth() + 1 != month;
const backgroundClass = isInSameMonth ? "" : "bg-slate-900";
- const todaysAssignments = modules
- .flatMap((m) => m.assignments)
- .filter((a) => {
- const dueDate = getDateFromStringOrThrow(
- a.dueAt,
- "due at for assignment in day"
- );
- return (
- dueDate.getFullYear() === day.getFullYear() &&
- dueDate.getMonth() === day.getMonth() &&
- dueDate.getDate() === day.getDate()
- );
- });
- const todaysQuizzes = modules
- .flatMap((m) => m.quizzes)
- .filter((q) => {
- const dueDate = getDateFromStringOrThrow(
- q.dueAt,
- "due at for quiz in day"
- );
- return (
- dueDate.getFullYear() === day.getFullYear() &&
- dueDate.getMonth() === day.getMonth() &&
- dueDate.getDate() === day.getDate()
- );
- });
- const todaysPages = modules
- .flatMap((m) => m.pages)
- .filter((p) => {
- const dueDate = getDateFromStringOrThrow(
- p.dueAt,
- "due at for page in day"
- );
- return (
- dueDate.getFullYear() === day.getFullYear() &&
- dueDate.getMonth() === day.getMonth() &&
- dueDate.getDate() === day.getDate()
- );
- });
return (
- itemDrop(day)}
- onDragOver={(e) => e.preventDefault()}
- >
- {day.getDate()}
-
- {todaysAssignments.map((a) => (
- - {a.name}
- ))}
- {todaysQuizzes.map((q) => (
- - startItemDrag({ type: "quiz", item: q })}
- onDragEnd={endItemDrag}
- >
- {q.name}
-
- ))}
- {todaysPages.map((p) => (
- - startItemDrag({ type: "page", item: p })}
- >
- {p.name}
-
- ))}
-
-
+ <>
+ {moduleNames.map((moduleName) => (
+ itemDrop(day)}
+ onDragOver={(e) => e.preventDefault()}
+ >
+ {day.getDate()}
+
+
+ ))}
+ >
);
}
diff --git a/nextjs/src/app/course/[courseName]/calendar/DayItemsInModule.tsx b/nextjs/src/app/course/[courseName]/calendar/DayItemsInModule.tsx
new file mode 100644
index 0000000..75f053b
--- /dev/null
+++ b/nextjs/src/app/course/[courseName]/calendar/DayItemsInModule.tsx
@@ -0,0 +1,76 @@
+import React from "react";
+import { useCourseContext } from "../context/courseContext";
+import { useModuleDataQuery } from "@/hooks/localCourse/localCoursesHooks";
+import { getDateFromStringOrThrow } from "@/models/local/timeUtils";
+
+export default function DayItemsInModule({
+ day,
+ moduleName,
+}: {
+ day: Date;
+ moduleName: string;
+}) {
+ const { courseName, endItemDrag, startItemDrag } = useCourseContext();
+ const { assignments, quizzes, pages } = useModuleDataQuery(
+ courseName,
+ moduleName
+ );
+
+ const todaysAssignments = assignments.filter((a) => {
+ const dueDate = getDateFromStringOrThrow(
+ a.dueAt,
+ "due at for assignment in day"
+ );
+ return (
+ dueDate.getFullYear() === day.getFullYear() &&
+ dueDate.getMonth() === day.getMonth() &&
+ dueDate.getDate() === day.getDate()
+ );
+ });
+ const todaysQuizzes = quizzes.filter((q) => {
+ const dueDate = getDateFromStringOrThrow(q.dueAt, "due at for quiz in day");
+ return (
+ dueDate.getFullYear() === day.getFullYear() &&
+ dueDate.getMonth() === day.getMonth() &&
+ dueDate.getDate() === day.getDate()
+ );
+ });
+ const todaysPages = pages.filter((p) => {
+ const dueDate = getDateFromStringOrThrow(p.dueAt, "due at for page in day");
+ return (
+ dueDate.getFullYear() === day.getFullYear() &&
+ dueDate.getMonth() === day.getMonth() &&
+ dueDate.getDate() === day.getDate()
+ );
+ });
+ return (
+ <>
+
+ {todaysAssignments.map((a) => (
+ - {a.name}
+ ))}
+ {todaysQuizzes.map((q) => (
+ - startItemDrag({ type: "quiz", item: q })}
+ onDragEnd={endItemDrag}
+ >
+ {q.name}
+
+ ))}
+ {todaysPages.map((p) => (
+ - startItemDrag({ type: "page", item: p })}
+ >
+ {p.name}
+
+ ))}
+
+ >
+ );
+}
diff --git a/nextjs/src/app/course/[courseName]/modules/ExpandableModule.tsx b/nextjs/src/app/course/[courseName]/modules/ExpandableModule.tsx
index ca7c89f..ad3c9f5 100644
--- a/nextjs/src/app/course/[courseName]/modules/ExpandableModule.tsx
+++ b/nextjs/src/app/course/[courseName]/modules/ExpandableModule.tsx
@@ -1,20 +1,8 @@
import { IModuleItem } from "@/models/local/IModuleItem";
-import { LocalModule } from "@/models/local/localModules";
import { getDateFromStringOrThrow } from "@/models/local/timeUtils";
-import React, { useState } from "react";
+import { useState } from "react";
import { useCourseContext } from "../context/courseContext";
-import {
- useAssignmentNamesQuery,
- useAssignmentsQueries,
-} from "@/hooks/localCourse/assignmentHooks";
-import {
- useQuizNamesQuery,
- useQuizzesQueries,
-} from "@/hooks/localCourse/quizHooks";
-import {
- usePageNamesQuery,
- usePagesQueries,
-} from "@/hooks/localCourse/pageHooks";
+import { useModuleDataQuery } from "@/hooks/localCourse/localCoursesHooks";
export default function ExpandableModule({
moduleName,
@@ -22,23 +10,10 @@ export default function ExpandableModule({
moduleName: string;
}) {
const { courseName } = useCourseContext();
- const { data: assignmentNames } = useAssignmentNamesQuery(
+ const { assignments, quizzes, pages } = useModuleDataQuery(
courseName,
moduleName
);
- const { data: assignments } = useAssignmentsQueries(
- courseName,
- moduleName,
- assignmentNames
- );
- const { data: quizNames } = useQuizNamesQuery(courseName, moduleName);
- const { data: quizzes } = useQuizzesQueries(
- courseName,
- moduleName,
- quizNames
- );
- const { data: pageNames } = usePageNamesQuery(courseName, moduleName);
- const { data: pages } = usePagesQueries(courseName, moduleName, pageNames);
const [expanded, setExpanded] = useState(false);
diff --git a/nextjs/src/app/course/[courseName]/modules/ModuleList.tsx b/nextjs/src/app/course/[courseName]/modules/ModuleList.tsx
index 3c74ef7..529e3b3 100644
--- a/nextjs/src/app/course/[courseName]/modules/ModuleList.tsx
+++ b/nextjs/src/app/course/[courseName]/modules/ModuleList.tsx
@@ -8,7 +8,6 @@ export default function ModuleList() {
const { data: moduleNames } = useModuleNamesQuery(courseName);
return (
- modules here
{moduleNames.map((m) => (
))}
diff --git a/nextjs/src/app/providers.tsx b/nextjs/src/app/providers.tsx
index 717c15c..aefb57c 100644
--- a/nextjs/src/app/providers.tsx
+++ b/nextjs/src/app/providers.tsx
@@ -12,7 +12,7 @@ function makeQueryClient() {
queries: {
// With SSR, we usually want to set some default staleTime
// above 0 to avoid refetching immediately on the client
- // staleTime: 1000,
+ staleTime: 1000,
},
},
});
@@ -39,6 +39,7 @@ export default function Providers({ children }: { children: ReactNode }) {
// have a suspense boundary between this and the code that may
// suspend because React will throw away the client on the initial
// render if it suspends and there is no boundary
+
const queryClient = getQueryClient();
return (
diff --git a/nextjs/src/hooks/hookHydration.ts b/nextjs/src/hooks/hookHydration.ts
index c2f067f..c0f6139 100644
--- a/nextjs/src/hooks/hookHydration.ts
+++ b/nextjs/src/hooks/hookHydration.ts
@@ -1,5 +1,5 @@
import { QueryClient } from "@tanstack/react-query";
-import { localCourseKeys } from "./localCourse/localCoursesHooks";
+import { localCourseKeys } from "./localCourse/localCourseKeys";
import { fileStorageService } from "@/services/fileStorage/fileStorageService";
export const hydrateCourses = async (queryClient: QueryClient) => {
@@ -14,7 +14,52 @@ export const hydrateCourse = async (
courseName: string
) => {
const settings = await fileStorageService.getCourseSettings(courseName);
- const moduleNames = await fileStorageService.getModuleNames(courseName)
+ const moduleNames = await fileStorageService.getModuleNames(courseName);
+ const modulesData = await Promise.all(
+ moduleNames.map(async (moduleName) => {
+ const [assignmentNames, pageNames, quizNames] = await Promise.all([
+ await fileStorageService.getAssignmentNames(courseName, moduleName),
+ await fileStorageService.getPageNames(courseName, moduleName),
+ await fileStorageService.getQuizNames(courseName, moduleName),
+ ]);
+
+ const [assignments, quizzes, pages] = await Promise.all([
+ await Promise.all(
+ assignmentNames.map(
+ async (assignmentName) =>
+ await fileStorageService.getAssignment(
+ courseName,
+ moduleName,
+ assignmentName
+ )
+ )
+ ),
+ await Promise.all(
+ quizNames.map(
+ async (quizName) =>
+ await fileStorageService.getQuiz(courseName, moduleName, quizName)
+ )
+ ),
+ await Promise.all(
+ pageNames.map(
+ async (pageName) =>
+ await fileStorageService.getPage(courseName, moduleName, pageName)
+ )
+ ),
+ ]);
+
+ return {
+ moduleName,
+ assignmentNames,
+ pageNames,
+ quizNames,
+ assignments,
+ quizzes,
+ pages,
+ };
+ })
+ );
+
await queryClient.prefetchQuery({
queryKey: localCourseKeys.settings(courseName),
queryFn: () => settings,
@@ -23,4 +68,70 @@ export const hydrateCourse = async (
queryKey: localCourseKeys.moduleNames(courseName),
queryFn: () => moduleNames,
});
+
+ await Promise.all(
+ modulesData.map(
+ async ({
+ moduleName,
+ assignmentNames,
+ pageNames,
+ quizNames,
+ assignments,
+ quizzes,
+ pages,
+ }) => {
+ await queryClient.prefetchQuery({
+ queryKey: localCourseKeys.assignmentNames(courseName, moduleName),
+ queryFn: () => assignmentNames,
+ });
+ await Promise.all(
+ assignments.map(
+ async (assignment) =>
+ await queryClient.prefetchQuery({
+ queryKey: localCourseKeys.assignment(
+ courseName,
+ moduleName,
+ assignment.name
+ ),
+ queryFn: () => assignment,
+ })
+ )
+ );
+ await queryClient.prefetchQuery({
+ queryKey: localCourseKeys.quizNames(courseName, moduleName),
+ queryFn: () => quizNames,
+ });
+ await Promise.all(
+ quizzes.map(
+ async (quiz) =>
+ await queryClient.prefetchQuery({
+ queryKey: localCourseKeys.quiz(
+ courseName,
+ moduleName,
+ quiz.name
+ ),
+ queryFn: () => quiz,
+ })
+ )
+ );
+ await queryClient.prefetchQuery({
+ queryKey: localCourseKeys.pageNames(courseName, moduleName),
+ queryFn: () => pageNames,
+ });
+ await Promise.all(
+ pages.map(
+ async (page) =>
+ await queryClient.prefetchQuery({
+ queryKey: localCourseKeys.page(
+ courseName,
+ moduleName,
+ page.name
+ ),
+ queryFn: () => page,
+ })
+ )
+ );
+ }
+ )
+ );
};
diff --git a/nextjs/src/hooks/localCourse/assignmentHooks.ts b/nextjs/src/hooks/localCourse/assignmentHooks.ts
index 99ab1fb..4601334 100644
--- a/nextjs/src/hooks/localCourse/assignmentHooks.ts
+++ b/nextjs/src/hooks/localCourse/assignmentHooks.ts
@@ -1,5 +1,5 @@
import axios from "axios";
-import { localCourseKeys } from "./localCoursesHooks";
+import { localCourseKeys } from "./localCourseKeys";
import { LocalAssignment } from "@/models/local/assignmnet/localAssignment";
import { useSuspenseQuery, useSuspenseQueries } from "@tanstack/react-query";
@@ -8,7 +8,7 @@ export const useAssignmentNamesQuery = (
moduleName: string
) =>
useSuspenseQuery({
- queryKey: localCourseKeys.moduleAssignmentNames(courseName, moduleName),
+ queryKey: localCourseKeys.assignmentNames(courseName, moduleName),
queryFn: async (): Promise => {
const url = `/api/courses/${courseName}/modules/${moduleName}/assignments`;
const response = await axios.get(url);
diff --git a/nextjs/src/hooks/localCourse/localCourseKeys.ts b/nextjs/src/hooks/localCourse/localCourseKeys.ts
new file mode 100644
index 0000000..e142f01
--- /dev/null
+++ b/nextjs/src/hooks/localCourse/localCourseKeys.ts
@@ -0,0 +1,55 @@
+export const localCourseKeys = {
+ allCourses: ["all courses"] as const,
+ settings: (courseName: string) =>
+ ["course details", courseName, "settings"] as const,
+ moduleNames: (courseName: string) =>
+ [
+ "course details",
+ courseName,
+ "modules",
+ { type: "names" } as const,
+ ] as const,
+ assignmentNames: (courseName: string, moduleName: string) =>
+ [
+ "course details",
+ courseName,
+ "modules",
+ moduleName,
+ "assignments",
+ ] as const,
+ quizNames: (courseName: string, moduleName: string) =>
+ ["course details", courseName, "modules", moduleName, "quizzes"] as const,
+ pageNames: (courseName: string, moduleName: string) =>
+ ["course details", courseName, "modules", moduleName, "pages"] as const,
+ assignment: (
+ courseName: string,
+ moduleName: string,
+ assignmentName: string
+ ) =>
+ [
+ "course details",
+ courseName,
+ "modules",
+ moduleName,
+ "assignments",
+ assignmentName,
+ ] as const,
+ quiz: (courseName: string, moduleName: string, quizName: string) =>
+ [
+ "course details",
+ courseName,
+ "modules",
+ moduleName,
+ "quizzes",
+ quizName,
+ ] as const,
+ page: (courseName: string, moduleName: string, pageName: string) =>
+ [
+ "course details",
+ courseName,
+ "modules",
+ moduleName,
+ "pages",
+ pageName,
+ ] as const,
+};
diff --git a/nextjs/src/hooks/localCourse/localCoursesHooks.ts b/nextjs/src/hooks/localCourse/localCoursesHooks.ts
index b638489..cb807bf 100644
--- a/nextjs/src/hooks/localCourse/localCoursesHooks.ts
+++ b/nextjs/src/hooks/localCourse/localCoursesHooks.ts
@@ -1,64 +1,13 @@
import { LocalCourseSettings } from "@/models/local/localCourse";
-import {
- useSuspenseQuery,
-} from "@tanstack/react-query";
+import { useSuspenseQuery } from "@tanstack/react-query";
import axios from "axios";
-
-export const localCourseKeys = {
- allCourses: ["all courses"] as const,
- settings: (courseName: string) =>
- ["course details", courseName, "settings"] as const,
- moduleNames: (courseName: string) =>
- [
- "course details",
- courseName,
- "modules",
- { type: "names" } as const,
- ] as const,
- moduleAssignmentNames: (courseName: string, moduleName: string) =>
- [
- "course details",
- courseName,
- "modules",
- moduleName,
- "assignments",
- ] as const,
- moduleQuizzeNames: (courseName: string, moduleName: string) =>
- ["course details", courseName, "modules", moduleName, "quizzes"] as const,
- modulePageNames: (courseName: string, moduleName: string) =>
- ["course details", courseName, "modules", moduleName, "pages"] as const,
- assignment: (
- courseName: string,
- moduleName: string,
- assignmentName: string
- ) =>
- [
- "course details",
- courseName,
- "modules",
- moduleName,
- "assignments",
- assignmentName,
- ] as const,
- quiz: (courseName: string, moduleName: string, quizName: string) =>
- [
- "course details",
- courseName,
- "modules",
- moduleName,
- "quizzes",
- quizName,
- ] as const,
- page: (courseName: string, moduleName: string, pageName: string) =>
- [
- "course details",
- courseName,
- "modules",
- moduleName,
- "pages",
- pageName,
- ] as const,
-};
+import { localCourseKeys } from "./localCourseKeys";
+import {
+ useAssignmentNamesQuery,
+ useAssignmentsQueries,
+} from "./assignmentHooks";
+import { usePageNamesQuery, usePagesQueries } from "./pageHooks";
+import { useQuizNamesQuery, useQuizzesQueries } from "./quizHooks";
export const useLocalCourseNamesQuery = () =>
useSuspenseQuery({
@@ -90,7 +39,33 @@ export const useModuleNamesQuery = (courseName: string) =>
},
});
+export const useModuleDataQuery = (courseName: string, moduleName: string) => {
+ const { data: assignmentNames } = useAssignmentNamesQuery(
+ courseName,
+ moduleName
+ );
+ const { data: quizNames } = useQuizNamesQuery(courseName, moduleName);
+ const { data: pageNames } = usePageNamesQuery(courseName, moduleName);
+ const { data: assignments } = useAssignmentsQueries(
+ courseName,
+ moduleName,
+ assignmentNames
+ );
+ const { data: quizzes } = useQuizzesQueries(
+ courseName,
+ moduleName,
+ quizNames
+ );
+ const { data: pages } = usePagesQueries(courseName, moduleName, pageNames);
+
+
+ return {
+ assignments,
+ quizzes,
+ pages,
+ };
+};
// export const useUpdateCourseMutation = (courseName: string) => {
// const queryClient = useQueryClient();
diff --git a/nextjs/src/hooks/localCourse/pageHooks.ts b/nextjs/src/hooks/localCourse/pageHooks.ts
index 7db4e70..bcfc158 100644
--- a/nextjs/src/hooks/localCourse/pageHooks.ts
+++ b/nextjs/src/hooks/localCourse/pageHooks.ts
@@ -1,11 +1,11 @@
import { LocalCoursePage } from "@/models/local/page/localCoursePage";
import { useSuspenseQueries, useSuspenseQuery } from "@tanstack/react-query";
import axios from "axios";
-import { localCourseKeys } from "./localCoursesHooks";
+import { localCourseKeys } from "./localCourseKeys";
export const usePageNamesQuery = (courseName: string, moduleName: string) =>
useSuspenseQuery({
- queryKey: localCourseKeys.modulePageNames(courseName, moduleName),
+ queryKey: localCourseKeys.pageNames(courseName, moduleName),
queryFn: async (): Promise => {
const url = `/api/courses/${courseName}/modules/${moduleName}/pages`;
const response = await axios.get(url);
diff --git a/nextjs/src/hooks/localCourse/quizHooks.ts b/nextjs/src/hooks/localCourse/quizHooks.ts
index 1b95d94..c1aaab9 100644
--- a/nextjs/src/hooks/localCourse/quizHooks.ts
+++ b/nextjs/src/hooks/localCourse/quizHooks.ts
@@ -1,11 +1,11 @@
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
import { useSuspenseQueries, useSuspenseQuery } from "@tanstack/react-query";
import axios from "axios";
-import { localCourseKeys } from "./localCoursesHooks";
+import { localCourseKeys } from "./localCourseKeys";
export const useQuizNamesQuery = (courseName: string, moduleName: string) =>
useSuspenseQuery({
- queryKey: localCourseKeys.moduleQuizzeNames(courseName, moduleName),
+ queryKey: localCourseKeys.quizNames(courseName, moduleName),
queryFn: async (): Promise => {
const url = `/api/courses/${courseName}/modules/${moduleName}/quizzes`;
const response = await axios.get(url);