diff --git a/nextjs/src/app/course/[courseName]/context/DraggingContextProvider.tsx b/nextjs/src/app/course/[courseName]/context/DraggingContextProvider.tsx index ac952b3..14f94cf 100644 --- a/nextjs/src/app/course/[courseName]/context/DraggingContextProvider.tsx +++ b/nextjs/src/app/course/[courseName]/context/DraggingContextProvider.tsx @@ -1,5 +1,5 @@ "use client"; -import { ReactNode, useCallback, DragEvent, useEffect } from "react"; +import { ReactNode, useCallback, DragEvent, useEffect, useState } from "react"; import { DraggableItem, DraggingContext } from "./draggingContext"; import { useUpdateQuizMutation } from "@/hooks/localCourse/quizHooks"; import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; @@ -20,6 +20,8 @@ import { useLectureUpdateMutation, } from "@/hooks/localCourse/lectureHooks"; import { getLectureForDay } from "@/models/local/lectureUtils"; +import Modal, { useModal } from "@/components/Modal"; +import { Spinner } from "@/components/Spinner"; export default function DraggingContextProvider({ children, @@ -33,6 +35,10 @@ export default function DraggingContextProvider({ const updatePageMutation = useUpdatePageMutation(); const { data: settings } = useLocalCourseSettingsQuery(); const { data: weeks } = useLecturesByWeekQuery(); + const [isLoading, setIsLoading] = useState(false); + const [modalText, setModalText] = useState(""); + const modal = useModal(); + const [modalCallback, setModalCallback] = useState<() => void>(() => {}); useEffect(() => { const handleDrop = () => { @@ -166,7 +172,28 @@ export default function DraggingContextProvider({ const existingLecture = getLectureForDay(weeks, dayAsDate); if (existingLecture) { console.log("attempting to drop on existing lecture"); + setModalText( + `Are you sure you want to replace ${existingLecture?.name} with ${lecture.name}? This will delete ${existingLecture.name}.` + ); + + setModalCallback(() => async () => { // because sometimes setStates receive a function + console.log("running callback"); + setIsLoading(true); + await updateLectureMutation.mutateAsync({ + previousDay: lecture.date, + lecture: { + ...lecture, + date: getDateOnlyMarkdownString(dayAsDate), + }, + }); + setModalText(""); + setModalCallback(() => {}); + modal.closeModal(); + setIsLoading(false); + }); + modal.openModal(); } else { + console.log("updating lecture on unique day"); updateLectureMutation.mutate({ previousDay: lecture.date, lecture: { @@ -249,6 +276,7 @@ export default function DraggingContextProvider({ } }, [ + modal, setIsDragging, settings.defaultDueTime.hour, settings.defaultDueTime.minute, @@ -267,6 +295,30 @@ export default function DraggingContextProvider({ itemDropOnModule, }} > + + {({ closeModal }) => ( +
+
{modalText}
+
+
+ + +
+ {isLoading && } +
+ )} +
{children} ); diff --git a/nextjs/src/components/Modal.tsx b/nextjs/src/components/Modal.tsx index 0e4e71d..f9faf5d 100644 --- a/nextjs/src/components/Modal.tsx +++ b/nextjs/src/components/Modal.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { ReactNode, useState } from "react"; +import React, { ReactNode, useCallback, useMemo, useState } from "react"; export interface ModalControl { isOpen: boolean; @@ -10,14 +10,17 @@ export interface ModalControl { export function useModal() { const [isOpen, setIsOpen] = useState(false); - const openModal = () => setIsOpen(true); - const closeModal = () => setIsOpen(false); + const openModal = useCallback(() => setIsOpen(true), []); + const closeModal = useCallback(() => setIsOpen(false), []); - return { - isOpen, - openModal, - closeModal, - }; + return useMemo( + () => ({ + isOpen, + openModal, + closeModal, + }), + [closeModal, isOpen, openModal] + ); } export default function Modal({