pushing state down with contexts

This commit is contained in:
2024-09-02 11:57:38 -06:00
parent 130035cc48
commit 895271743f
20 changed files with 517 additions and 439 deletions

View File

@@ -1,6 +1,7 @@
"use client";
import { ReactNode, useCallback, useState } from "react";
import { CourseContext, DraggableItem } from "./courseContext";
import { CourseContext } from "./courseContext";
import { DraggableItem } from "./DraggingContext";
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
import {
dateToMarkdownString,
@@ -16,60 +17,10 @@ export default function CourseContextProvider({
children: ReactNode;
localCourseName: string;
}) {
const updateQuizMutation = useUpdateQuizMutation(localCourseName);
const { data: settings } = useLocalCourseSettingsQuery(localCourseName);
const [itemBeingDragged, setItemBeingDragged] = useState<
DraggableItem | undefined
>();
const itemDrop = useCallback(
(day: Date | undefined) => {
if (itemBeingDragged && day) {
day.setHours(settings.defaultDueTime.hour);
day.setHours(settings.defaultDueTime.minute);
if (itemBeingDragged.type === "quiz") {
const previousQuiz = itemBeingDragged.item as LocalQuiz;
const quiz: LocalQuiz = {
...previousQuiz,
dueAt: dateToMarkdownString(day),
lockAt:
previousQuiz.lockAt &&
(getDateFromStringOrThrow(previousQuiz.lockAt, "lockAt date") >
day
? previousQuiz.lockAt
: dateToMarkdownString(day)),
};
updateQuizMutation.mutate({
quiz: quiz,
quizName: quiz.name,
moduleName: itemBeingDragged.sourceModuleName,
});
}
}
setItemBeingDragged(undefined);
},
[
itemBeingDragged,
settings.defaultDueTime.hour,
settings.defaultDueTime.minute,
updateQuizMutation,
]
);
const startItemDrag = useCallback((d: DraggableItem) => {
setItemBeingDragged(d);
}, []);
const endItemDrag = useCallback(() => {
setItemBeingDragged(undefined);
}, []);
return (
<CourseContext.Provider
value={{
courseName: localCourseName,
startItemDrag: startItemDrag,
endItemDrag: endItemDrag,
itemDrop,
}}
>
{children}

View File

@@ -0,0 +1,25 @@
"use client";
import { IModuleItem } from "@/models/local/IModuleItem";
import { createContext, useContext } from "react";
export interface DraggableItem {
item: IModuleItem;
sourceModuleName: string;
type: "quiz" | "assignment" | "page";
}
export interface DraggingContextInterface {
startItemDrag: (dragging: DraggableItem) => void;
endItemDrag: () => void;
itemDrop: (droppedOnDay?: string) => void;
}
const defaultDraggingValue: DraggingContextInterface = {
startItemDrag: () => { },
endItemDrag: () => { },
itemDrop: () => { },
};
export const DraggingContext = createContext<DraggingContextInterface>(defaultDraggingValue);
export function useDraggingContext() {
return useContext(DraggingContext);
}

View File

@@ -0,0 +1,82 @@
"use client";
import { ReactNode, useCallback, useState } from "react";
import { DraggableItem, DraggingContext } from "./DraggingContext";
import { LocalQuiz } from "@/models/local/quiz/localQuiz";
import {
dateToMarkdownString,
getDateFromStringOrThrow,
} from "@/models/local/timeUtils";
import { useUpdateQuizMutation } from "@/hooks/localCourse/quizHooks";
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
export default function DraggingContextProvider({
children,
}: {
children: ReactNode;
localCourseName: string;
}) {
const updateQuizMutation = useUpdateQuizMutation();
const { data: settings } = useLocalCourseSettingsQuery();
const [itemBeingDragged, setItemBeingDragged] = useState<
DraggableItem | undefined
>();
const itemDrop = useCallback(
(day: string | undefined) => {
if (itemBeingDragged && day) {
const dayAsDate = getDateFromStringOrThrow(day, "in drop callback");
dayAsDate.setHours(settings.defaultDueTime.hour);
dayAsDate.setHours(settings.defaultDueTime.minute);
if (itemBeingDragged.type === "quiz") {
console.log("dropping quiz");
const previousQuiz = itemBeingDragged.item as LocalQuiz;
const quiz: LocalQuiz = {
...previousQuiz,
dueAt: dateToMarkdownString(dayAsDate),
lockAt:
previousQuiz.lockAt &&
(getDateFromStringOrThrow(previousQuiz.lockAt, "lockAt date") >
dayAsDate
? previousQuiz.lockAt
: dateToMarkdownString(dayAsDate)),
};
updateQuizMutation.mutate({
quiz: quiz,
quizName: quiz.name,
moduleName: itemBeingDragged.sourceModuleName,
});
} else if (itemBeingDragged.type === "assignment") {
console.log("dropped assignment");
} else if (itemBeingDragged.type === "page") {
console.log("dropped page");
}
}
setItemBeingDragged(undefined);
},
[
itemBeingDragged,
settings.defaultDueTime.hour,
settings.defaultDueTime.minute,
updateQuizMutation,
]
);
const startItemDrag = useCallback((d: DraggableItem) => {
setItemBeingDragged(d);
}, []);
const endItemDrag = useCallback(() => {
setItemBeingDragged(undefined);
}, []);
return (
<DraggingContext.Provider
value={{
startItemDrag: startItemDrag,
endItemDrag: endItemDrag,
itemDrop,
}}
>
{children}
</DraggingContext.Provider>
);
}

View File

@@ -1,25 +1,12 @@
"use client";
import { IModuleItem } from "@/models/local/IModuleItem";
import { createContext, useContext } from "react";
export interface DraggableItem {
item: IModuleItem;
sourceModuleName: string;
type: "quiz" | "assignment" | "page";
}
export interface CourseContextInterface {
courseName: string;
startItemDrag: (dragging: DraggableItem) => void;
endItemDrag: () => void;
itemDrop: (droppedOnDay?: Date) => void;
}
const defaultValue: CourseContextInterface = {
startItemDrag: () => { },
endItemDrag: () => { },
itemDrop: () => { },
courseName: ""
courseName: "",
};
export const CourseContext =
@@ -28,3 +15,4 @@ export const CourseContext =
export function useCourseContext() {
return useContext(CourseContext);
}