diff --git a/nextjs/src/app/course/[courseName]/calendar/day/Day.tsx b/nextjs/src/app/course/[courseName]/calendar/day/Day.tsx index 5c23b46..f962c4e 100644 --- a/nextjs/src/app/course/[courseName]/calendar/day/Day.tsx +++ b/nextjs/src/app/course/[courseName]/calendar/day/Day.tsx @@ -3,7 +3,7 @@ import { getDateFromStringOrThrow, getDateOnlyMarkdownString, } from "@/models/local/timeUtils"; -import { useDraggingContext } from "../../context/draggingContext"; +import { useDraggingContext } from "../../context/drag/draggingContext"; import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; import { getDayOfWeek } from "@/models/local/localCourse"; import { ItemInDay } from "./ItemInDay"; diff --git a/nextjs/src/app/course/[courseName]/calendar/day/DayTitle.tsx b/nextjs/src/app/course/[courseName]/calendar/day/DayTitle.tsx index 9ba2fb1..ececcc4 100644 --- a/nextjs/src/app/course/[courseName]/calendar/day/DayTitle.tsx +++ b/nextjs/src/app/course/[courseName]/calendar/day/DayTitle.tsx @@ -4,8 +4,8 @@ import { getLectureUrl } from "@/services/urlUtils"; import Link from "next/link"; import { useCourseContext } from "../../context/courseContext"; import NewItemForm from "../../modules/NewItemForm"; -import { DraggableItem } from "../../context/draggingContext"; -import { useDragStyleContext } from "../../context/dragStyleContext"; +import { DraggableItem } from "../../context/drag/draggingContext"; +import { useDragStyleContext } from "../../context/drag/dragStyleContext"; import { getLectureForDay } from "@/models/local/lectureUtils"; export function DayTitle({ day, dayAsDate }: { day: string; dayAsDate: Date }) { diff --git a/nextjs/src/app/course/[courseName]/calendar/day/ItemInDay.tsx b/nextjs/src/app/course/[courseName]/calendar/day/ItemInDay.tsx index 27c59d7..da6a99d 100644 --- a/nextjs/src/app/course/[courseName]/calendar/day/ItemInDay.tsx +++ b/nextjs/src/app/course/[courseName]/calendar/day/ItemInDay.tsx @@ -6,10 +6,10 @@ import { useCourseContext } from "../../context/courseContext"; import { useDraggingContext, DraggableItem, -} from "../../context/draggingContext"; +} from "../../context/drag/draggingContext"; import { createPortal } from "react-dom"; import ClientOnly from "@/components/ClientOnly"; -import { useDragStyleContext } from "../../context/dragStyleContext"; +import { useDragStyleContext } from "../../context/drag/dragStyleContext"; export function ItemInDay({ type, diff --git a/nextjs/src/app/course/[courseName]/context/DraggingContextProvider.tsx b/nextjs/src/app/course/[courseName]/context/drag/DraggingContextProvider.tsx similarity index 90% rename from nextjs/src/app/course/[courseName]/context/DraggingContextProvider.tsx rename to nextjs/src/app/course/[courseName]/context/drag/DraggingContextProvider.tsx index deadfd9..d2d541f 100644 --- a/nextjs/src/app/course/[courseName]/context/DraggingContextProvider.tsx +++ b/nextjs/src/app/course/[courseName]/context/drag/DraggingContextProvider.tsx @@ -3,8 +3,9 @@ import { ReactNode, useEffect, useState } from "react"; import { DraggingContext } from "./draggingContext"; import { useDragStyleContext } from "./dragStyleContext"; import { useModal } from "@/components/Modal"; -import { LectureReplaceModal } from "./LectureReplaceModal"; -import { useItemDropOnDay, useItemDropOnModule } from "./draggingContextUtils"; +import { LectureReplaceModal } from "../LectureReplaceModal"; +import { useItemDropOnModule } from "./useItemDropOnModule"; +import { useItemDropOnDay } from "./useItemDropOnDay"; export default function DraggingContextProvider({ children, diff --git a/nextjs/src/app/course/[courseName]/context/dragStyleContext.tsx b/nextjs/src/app/course/[courseName]/context/drag/dragStyleContext.tsx similarity index 100% rename from nextjs/src/app/course/[courseName]/context/dragStyleContext.tsx rename to nextjs/src/app/course/[courseName]/context/drag/dragStyleContext.tsx diff --git a/nextjs/src/app/course/[courseName]/context/draggingContext.tsx b/nextjs/src/app/course/[courseName]/context/drag/draggingContext.tsx similarity index 100% rename from nextjs/src/app/course/[courseName]/context/draggingContext.tsx rename to nextjs/src/app/course/[courseName]/context/drag/draggingContext.tsx diff --git a/nextjs/src/app/course/[courseName]/context/drag/getNewLockDate.ts b/nextjs/src/app/course/[courseName]/context/drag/getNewLockDate.ts new file mode 100644 index 0000000..3e614a1 --- /dev/null +++ b/nextjs/src/app/course/[courseName]/context/drag/getNewLockDate.ts @@ -0,0 +1,25 @@ +"use client"; +import { getDateFromStringOrThrow, dateToMarkdownString } from "@/models/local/timeUtils"; + + +export function getNewLockDate( + originalDueDate: string, + originalLockDate: string | undefined, + dayAsDate: Date +): string | undefined { + // todo: preserve previous due date / lock date offset + const dueDate = getDateFromStringOrThrow(originalDueDate, "dueAt date"); + const lockDate = originalLockDate === undefined + ? undefined + : getDateFromStringOrThrow(originalLockDate, "lockAt date"); + + const originalOffset = lockDate === undefined ? undefined : lockDate.getTime() - dueDate.getTime(); + + const newLockDate = originalOffset === undefined + ? undefined + : new Date(dayAsDate.getTime() + originalOffset); + + return newLockDate === undefined + ? undefined + : dateToMarkdownString(newLockDate); +} diff --git a/nextjs/src/app/course/[courseName]/context/draggingContextUtils.ts b/nextjs/src/app/course/[courseName]/context/drag/useItemDropOnDay.ts similarity index 62% rename from nextjs/src/app/course/[courseName]/context/draggingContextUtils.ts rename to nextjs/src/app/course/[courseName]/context/drag/useItemDropOnDay.ts index 6227933..d9c6411 100644 --- a/nextjs/src/app/course/[courseName]/context/draggingContextUtils.ts +++ b/nextjs/src/app/course/[courseName]/context/drag/useItemDropOnDay.ts @@ -1,10 +1,7 @@ "use client"; - import { useUpdateAssignmentMutation } from "@/hooks/localCourse/assignmentHooks"; -import { - useLecturesByWeekQuery, - useLectureUpdateMutation, -} from "@/hooks/localCourse/lectureHooks"; +import { useLecturesByWeekQuery, useLectureUpdateMutation } from "@/hooks/localCourse/lectureHooks"; +import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; import { useUpdatePageMutation } from "@/hooks/localCourse/pageHooks"; import { useUpdateQuizMutation } from "@/hooks/localCourse/quizHooks"; import { LocalAssignment } from "@/models/local/assignment/localAssignment"; @@ -12,27 +9,20 @@ import { Lecture } from "@/models/local/lecture"; import { getLectureForDay } from "@/models/local/lectureUtils"; import { LocalCoursePage } from "@/models/local/page/localCoursePage"; import { LocalQuiz } from "@/models/local/quiz/localQuiz"; -import { - getDateFromStringOrThrow, - getDateOnlyMarkdownString, - dateToMarkdownString, -} from "@/models/local/timeUtils"; +import { getDateFromStringOrThrow, getDateOnlyMarkdownString, dateToMarkdownString } from "@/models/local/timeUtils"; import { Dispatch, SetStateAction, useCallback, DragEvent } from "react"; import { DraggableItem } from "./draggingContext"; -import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; +import { getNewLockDate } from "./getNewLockDate"; + export function useItemDropOnDay({ - setIsDragging, - setModalText, - setModalCallback, - setIsLoading, - modal, + setIsDragging, setModalText, setModalCallback, setIsLoading, modal, }: { setIsDragging: Dispatch>; setModalText: Dispatch>; setModalCallback: Dispatch void>>; setIsLoading: Dispatch>; - modal: { isOpen: boolean; openModal: () => void; closeModal: () => void }; + modal: { isOpen: boolean; openModal: () => void; closeModal: () => void; }; }) { const { data: settings } = useLocalCourseSettingsQuery(); const { data: weeks } = useLecturesByWeekQuery(); @@ -91,7 +81,7 @@ export function useItemDropOnDay({ }, }); setModalText(""); - setModalCallback(() => {}); + setModalCallback(() => { }); modal.closeModal(); setIsLoading(false); }); @@ -195,116 +185,3 @@ export function useItemDropOnDay({ ] ); } -export function useItemDropOnModule({ - setIsDragging, -}: { - setIsDragging: Dispatch>; -}) { - const updateQuizMutation = useUpdateQuizMutation(); - const updateAssignmentMutation = useUpdateAssignmentMutation(); - const updatePageMutation = useUpdatePageMutation(); - - return useCallback( - (e: DragEvent, dropModuleName: string) => { - console.log("dropping on module"); - const rawData = e.dataTransfer.getData("draggableItem"); - if (!rawData) return; - const itemBeingDragged: DraggableItem = JSON.parse(rawData); - - if (itemBeingDragged) { - if (itemBeingDragged.type === "quiz") { - updateQuiz(); - } else if (itemBeingDragged.type === "assignment") { - updateAssignment(); - } else if (itemBeingDragged.type === "page") { - updatePage(); - } else if (itemBeingDragged.type === "lecture") { - console.log("cannot drop lecture on module, only on days"); - } - } - setIsDragging(false); - - function updateQuiz() { - const quiz = itemBeingDragged.item as LocalQuiz; - if (itemBeingDragged.sourceModuleName) { - updateQuizMutation.mutate({ - item: quiz, - itemName: quiz.name, - moduleName: dropModuleName, - previousModuleName: itemBeingDragged.sourceModuleName, - previousItemName: quiz.name, - }); - } else { - console.error( - `error dropping quiz, sourceModuleName is undefined `, - quiz - ); - } - } - function updateAssignment() { - const assignment = itemBeingDragged.item as LocalAssignment; - if (itemBeingDragged.sourceModuleName) { - updateAssignmentMutation.mutate({ - item: assignment, - previousModuleName: itemBeingDragged.sourceModuleName, - moduleName: dropModuleName, - itemName: assignment.name, - previousItemName: assignment.name, - }); - } else { - console.error( - `error dropping assignment, sourceModuleName is undefined `, - assignment - ); - } - } - function updatePage() { - const page = itemBeingDragged.item as LocalCoursePage; - if (itemBeingDragged.sourceModuleName) { - updatePageMutation.mutate({ - item: page, - moduleName: dropModuleName, - itemName: page.name, - previousItemName: page.name, - previousModuleName: itemBeingDragged.sourceModuleName, - }); - } else { - console.error( - `error dropping page, sourceModuleName is undefined `, - page - ); - } - } - }, - [ - setIsDragging, - updateAssignmentMutation, - updatePageMutation, - updateQuizMutation, - ] - ); -} -export function getNewLockDate( - originalDueDate: string, - originalLockDate: string | undefined, - dayAsDate: Date -): string | undefined { - // todo: preserve previous due date / lock date offset - const dueDate = getDateFromStringOrThrow(originalDueDate, "dueAt date"); - const lockDate = - originalLockDate === undefined - ? undefined - : getDateFromStringOrThrow(originalLockDate, "lockAt date"); - - const originalOffset = - lockDate === undefined ? undefined : lockDate.getTime() - dueDate.getTime(); - - const newLockDate = - originalOffset === undefined - ? undefined - : new Date(dayAsDate.getTime() + originalOffset); - - return newLockDate === undefined - ? undefined - : dateToMarkdownString(newLockDate); -} diff --git a/nextjs/src/app/course/[courseName]/context/drag/useItemDropOnModule.ts b/nextjs/src/app/course/[courseName]/context/drag/useItemDropOnModule.ts new file mode 100644 index 0000000..bb5c5b1 --- /dev/null +++ b/nextjs/src/app/course/[courseName]/context/drag/useItemDropOnModule.ts @@ -0,0 +1,99 @@ +"use client"; +import { useUpdateAssignmentMutation } from "@/hooks/localCourse/assignmentHooks"; +import { useUpdatePageMutation } from "@/hooks/localCourse/pageHooks"; +import { useUpdateQuizMutation } from "@/hooks/localCourse/quizHooks"; +import { LocalAssignment } from "@/models/local/assignment/localAssignment"; +import { LocalCoursePage } from "@/models/local/page/localCoursePage"; +import { LocalQuiz } from "@/models/local/quiz/localQuiz"; +import { Dispatch, SetStateAction, useCallback, DragEvent } from "react"; +import { DraggableItem } from "./draggingContext"; + +export function useItemDropOnModule({ + setIsDragging, +}: { + setIsDragging: Dispatch>; +}) { + const updateQuizMutation = useUpdateQuizMutation(); + const updateAssignmentMutation = useUpdateAssignmentMutation(); + const updatePageMutation = useUpdatePageMutation(); + + return useCallback( + (e: DragEvent, dropModuleName: string) => { + console.log("dropping on module"); + const rawData = e.dataTransfer.getData("draggableItem"); + if (!rawData) return; + const itemBeingDragged: DraggableItem = JSON.parse(rawData); + + if (itemBeingDragged) { + if (itemBeingDragged.type === "quiz") { + updateQuiz(); + } else if (itemBeingDragged.type === "assignment") { + updateAssignment(); + } else if (itemBeingDragged.type === "page") { + updatePage(); + } else if (itemBeingDragged.type === "lecture") { + console.log("cannot drop lecture on module, only on days"); + } + } + setIsDragging(false); + + function updateQuiz() { + const quiz = itemBeingDragged.item as LocalQuiz; + if (itemBeingDragged.sourceModuleName) { + updateQuizMutation.mutate({ + item: quiz, + itemName: quiz.name, + moduleName: dropModuleName, + previousModuleName: itemBeingDragged.sourceModuleName, + previousItemName: quiz.name, + }); + } else { + console.error( + `error dropping quiz, sourceModuleName is undefined `, + quiz + ); + } + } + function updateAssignment() { + const assignment = itemBeingDragged.item as LocalAssignment; + if (itemBeingDragged.sourceModuleName) { + updateAssignmentMutation.mutate({ + item: assignment, + previousModuleName: itemBeingDragged.sourceModuleName, + moduleName: dropModuleName, + itemName: assignment.name, + previousItemName: assignment.name, + }); + } else { + console.error( + `error dropping assignment, sourceModuleName is undefined `, + assignment + ); + } + } + function updatePage() { + const page = itemBeingDragged.item as LocalCoursePage; + if (itemBeingDragged.sourceModuleName) { + updatePageMutation.mutate({ + item: page, + moduleName: dropModuleName, + itemName: page.name, + previousItemName: page.name, + previousModuleName: itemBeingDragged.sourceModuleName, + }); + } else { + console.error( + `error dropping page, sourceModuleName is undefined `, + page + ); + } + } + }, + [ + setIsDragging, + updateAssignmentMutation, + updatePageMutation, + updateQuizMutation, + ] + ); +} diff --git a/nextjs/src/app/course/[courseName]/modules/ExpandableModule.tsx b/nextjs/src/app/course/[courseName]/modules/ExpandableModule.tsx index 8fd2b87..ed7bf3a 100644 --- a/nextjs/src/app/course/[courseName]/modules/ExpandableModule.tsx +++ b/nextjs/src/app/course/[courseName]/modules/ExpandableModule.tsx @@ -14,12 +14,12 @@ import NewItemForm from "./NewItemForm"; import { ModuleCanvasStatus } from "./ModuleCanvasStatus"; import ClientOnly from "@/components/ClientOnly"; import ExpandIcon from "../../../../components/icons/ExpandIcon"; -import { DraggableItem, useDraggingContext } from "../context/draggingContext"; +import { DraggableItem, useDraggingContext } from "../context/drag/draggingContext"; import Link from "next/link"; import { getModuleItemUrl } from "@/services/urlUtils"; import { useCourseContext } from "../context/courseContext"; import { Expandable } from "../../../../components/Expandable"; -import { useDragStyleContext } from "../context/dragStyleContext"; +import { useDragStyleContext } from "../context/drag/dragStyleContext"; export default function ExpandableModule({ moduleName, diff --git a/nextjs/src/app/course/[courseName]/page.tsx b/nextjs/src/app/course/[courseName]/page.tsx index 79d6fe0..23b2625 100644 --- a/nextjs/src/app/course/[courseName]/page.tsx +++ b/nextjs/src/app/course/[courseName]/page.tsx @@ -1,10 +1,10 @@ import CourseCalendar from "./calendar/CourseCalendar"; import CourseSettingsLink from "./CourseSettingsLink"; import ModuleList from "./modules/ModuleList"; -import DraggingContextProvider from "./context/DraggingContextProvider"; +import DraggingContextProvider from "./context/drag/DraggingContextProvider"; import CourseTitle from "./CourseTitle"; import { CourseNavigation } from "./CourseNavigation"; -import { DragStyleContextProvider } from "./context/dragStyleContext"; +import { DragStyleContextProvider } from "./context/drag/dragStyleContext"; export default async function CoursePage({}: {}) { return (