adding modal control

This commit is contained in:
2024-11-02 13:29:36 -06:00
parent 14003d52c9
commit b47a7f88a4
11 changed files with 122 additions and 21 deletions

View File

@@ -1,4 +1,4 @@
import Modal from "@/components/Modal"; import Modal, { useModal } from "@/components/Modal";
import { useLecturesByWeekQuery } from "@/hooks/localCourse/lectureHooks"; import { useLecturesByWeekQuery } from "@/hooks/localCourse/lectureHooks";
import { getLectureUrl } from "@/services/urlUtils"; import { getLectureUrl } from "@/services/urlUtils";
import Link from "next/link"; import Link from "next/link";
@@ -13,6 +13,8 @@ export function DayTitle({ day, dayAsDate }: { day: string; dayAsDate: Date }) {
const { data: weeks } = useLecturesByWeekQuery(); const { data: weeks } = useLecturesByWeekQuery();
const { setIsDragging } = useDragStyleContext(); const { setIsDragging } = useDragStyleContext();
const todaysLecture = getLectureForDay(weeks, dayAsDate); const todaysLecture = getLectureForDay(weeks, dayAsDate);
const modal = useModal();
return ( return (
<div className="flex justify-between"> <div className="flex justify-between">
<Link <Link
@@ -37,6 +39,7 @@ export function DayTitle({ day, dayAsDate }: { day: string; dayAsDate: Date }) {
{dayAsDate.getDate()} {todaysLecture?.name} {dayAsDate.getDate()} {todaysLecture?.name}
</Link> </Link>
<Modal <Modal
modalControl={modal}
buttonText="+" buttonText="+"
buttonClass="unstyled hover:font-bold hover:scale-125 px-1 mb-auto mt-0 pt-0" buttonClass="unstyled hover:font-bold hover:scale-125 px-1 mb-auto mt-0 pt-0"
> >

View File

@@ -253,8 +253,10 @@ export default function DraggingContextProvider({
settings.defaultDueTime.hour, settings.defaultDueTime.hour,
settings.defaultDueTime.minute, settings.defaultDueTime.minute,
updateAssignmentMutation, updateAssignmentMutation,
updateLectureMutation,
updatePageMutation, updatePageMutation,
updateQuizMutation, updateQuizMutation,
weeks,
] ]
); );

View File

@@ -12,6 +12,7 @@ import {
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import LecturePreview from "./LecturePreview"; import LecturePreview from "./LecturePreview";
import EditLectureTitle from "./EditLectureTitle"; import EditLectureTitle from "./EditLectureTitle";
import LectureButtons from "./LectureButtons";
export default function EditLecture({ lectureDay }: { lectureDay: string }) { export default function EditLecture({ lectureDay }: { lectureDay: string }) {
const { data: weeks } = useLecturesByWeekQuery(); const { data: weeks } = useLecturesByWeekQuery();
@@ -63,6 +64,7 @@ Date: ${lectureDay}
{lecture && <LecturePreview lecture={lecture} />} {lecture && <LecturePreview lecture={lecture} />}
</div> </div>
</div> </div>
<LectureButtons lectureDay={lectureDay} />
</div> </div>
); );
} }

View File

@@ -3,7 +3,6 @@ import { getDayOfWeek } from "@/models/local/localCourse";
import { getDateFromString } from "@/models/local/timeUtils"; import { getDateFromString } from "@/models/local/timeUtils";
import { getLectureWeekName } from "@/services/fileStorage/utils/lectureUtils"; import { getLectureWeekName } from "@/services/fileStorage/utils/lectureUtils";
import { getCourseUrl, getLecturePreviewUrl } from "@/services/urlUtils"; import { getCourseUrl, getLecturePreviewUrl } from "@/services/urlUtils";
import { useRouter } from "next/navigation";
import { useCourseContext } from "../../context/courseContext"; import { useCourseContext } from "../../context/courseContext";
import Link from "next/link"; import Link from "next/link";

View File

@@ -0,0 +1,64 @@
"use client";
import Modal, { useModal } from "@/components/Modal";
import { Spinner } from "@/components/Spinner";
import { getCourseUrl } from "@/services/urlUtils";
import { useQueryClient } from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useCourseContext } from "../../context/courseContext";
import { deleteLecture } from "@/services/fileStorage/lectureFileStorageService";
import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks";
import { lectureKeys } from "@/hooks/localCourse/lectureKeys";
export default function LectureButtons({ lectureDay }: { lectureDay: string }) {
const queryClient = useQueryClient();
const { courseName } = useCourseContext();
const { data: settings } = useLocalCourseSettingsQuery();
const router = useRouter();
const [isLoading, setIsLoading] = useState(false);
const modal = useModal();
return (
<div className="p-5 flex flex-row justify-end gap-3">
<div>
<Modal
modalControl={modal}
buttonText="Delete Lecture"
buttonClass="btn-danger"
modalWidth="w-1/5"
>
{({ closeModal }) => (
<div>
<div className="text-center">
Are you sure you want to delete this lecture?
</div>
<br />
<div className="flex justify-around gap-3">
<button
onClick={async () => {
setIsLoading(true);
router.push(getCourseUrl(courseName));
await deleteLecture(courseName, settings, lectureDay);
await queryClient.invalidateQueries({
queryKey: lectureKeys.allLectures(courseName),
});
}}
disabled={isLoading}
className="btn-danger"
>
Yes
</button>
<button onClick={closeModal} disabled={isLoading}>
No
</button>
</div>
{isLoading && <Spinner />}
</div>
)}
</Modal>
{isLoading && <Spinner />}
</div>
</div>
);
}

View File

@@ -1,5 +1,8 @@
import EditLecture from "./EditLecture"; import EditLecture from "./EditLecture";
import { getDateFromStringOrThrow, getDateOnlyMarkdownString } from "@/models/local/timeUtils"; import {
getDateFromStringOrThrow,
getDateOnlyMarkdownString,
} from "@/models/local/timeUtils";
export default function page({ export default function page({
params: { lectureDay }, params: { lectureDay },
@@ -8,7 +11,10 @@ export default function page({
}) { }) {
const decodedLectureDay = decodeURIComponent(lectureDay); const decodedLectureDay = decodeURIComponent(lectureDay);
console.log(decodedLectureDay); console.log(decodedLectureDay);
const lectureDate = getDateFromStringOrThrow(decodedLectureDay, "lecture day in lecture page") const lectureDate = getDateFromStringOrThrow(
const lectureDayOnly = getDateOnlyMarkdownString(lectureDate) decodedLectureDay,
"lecture day in lecture page"
);
const lectureDayOnly = getDateOnlyMarkdownString(lectureDate);
return <EditLecture lectureDay={lectureDayOnly} />; return <EditLecture lectureDay={lectureDayOnly} />;
} }

View File

@@ -9,7 +9,7 @@ import {
getDateOnlyMarkdownString, getDateOnlyMarkdownString,
} from "@/models/local/timeUtils"; } from "@/models/local/timeUtils";
import { Fragment } from "react"; import { Fragment } from "react";
import Modal from "../../../../components/Modal"; import Modal, { useModal } from "../../../../components/Modal";
import NewItemForm from "./NewItemForm"; import NewItemForm from "./NewItemForm";
import { ModuleCanvasStatus } from "./ModuleCanvasStatus"; import { ModuleCanvasStatus } from "./ModuleCanvasStatus";
import ClientOnly from "@/components/ClientOnly"; import ClientOnly from "@/components/ClientOnly";
@@ -31,6 +31,7 @@ export default function ExpandableModule({
const { data: assignments } = useAssignmentsQueries(moduleName); const { data: assignments } = useAssignmentsQueries(moduleName);
const { data: quizzes } = useQuizzesQueries(moduleName); const { data: quizzes } = useQuizzesQueries(moduleName);
const { data: pages } = usePagesQueries(moduleName); const { data: pages } = usePagesQueries(moduleName);
const modal = useModal();
const moduleItems: { const moduleItems: {
type: "assignment" | "quiz" | "page"; type: "assignment" | "quiz" | "page";
@@ -91,7 +92,7 @@ export default function ExpandableModule({
)} )}
> >
<> <>
<Modal buttonText="New Item"> <Modal modalControl={modal} buttonText="New Item">
{({ closeModal }) => ( {({ closeModal }) => (
<div> <div>
<NewItemForm <NewItemForm

View File

@@ -1,5 +1,5 @@
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext"; import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import Modal from "@/components/Modal"; import Modal, { useModal } from "@/components/Modal";
import { Spinner } from "@/components/Spinner"; import { Spinner } from "@/components/Spinner";
import { import {
useCanvasAssignmentsQuery, useCanvasAssignmentsQuery,
@@ -45,6 +45,7 @@ export function AssignmentButtons({
const updateAssignment = useUpdateAssignmentInCanvasMutation(); const updateAssignment = useUpdateAssignmentInCanvasMutation();
const deleteLocal = useDeleteAssignmentMutation(); const deleteLocal = useDeleteAssignmentMutation();
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const modal = useModal();
const assignmentInCanvas = canvasAssignments.find( const assignmentInCanvas = canvasAssignments.find(
(a) => a.name === assignmentName (a) => a.name === assignmentName
@@ -116,6 +117,7 @@ export function AssignmentButtons({
)} )}
{!assignmentInCanvas && ( {!assignmentInCanvas && (
<Modal <Modal
modalControl={modal}
buttonText="Delete Localy" buttonText="Delete Localy"
buttonClass="btn-danger" buttonClass="btn-danger"
modalWidth="w-1/5" modalWidth="w-1/5"

View File

@@ -1,5 +1,5 @@
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext"; import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import Modal from "@/components/Modal"; import Modal, { useModal } from "@/components/Modal";
import { Spinner } from "@/components/Spinner"; import { Spinner } from "@/components/Spinner";
import { import {
useCanvasPagesQuery, useCanvasPagesQuery,
@@ -14,7 +14,6 @@ import {
} from "@/hooks/localCourse/pageHooks"; } from "@/hooks/localCourse/pageHooks";
import { baseCanvasUrl } from "@/services/canvas/canvasServiceUtils"; import { baseCanvasUrl } from "@/services/canvas/canvasServiceUtils";
import { getCourseUrl } from "@/services/urlUtils"; import { getCourseUrl } from "@/services/urlUtils";
import { revalidatePath } from "next/cache";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import React from "react"; import React from "react";
@@ -35,6 +34,7 @@ export default function EditPageButtons({
const updatePageInCanvas = useUpdateCanvasPageMutation(); const updatePageInCanvas = useUpdateCanvasPageMutation();
const deletePageInCanvas = useDeleteCanvasPageMutation(); const deletePageInCanvas = useDeleteCanvasPageMutation();
const deletePageLocal = useDeletePageMutation(); const deletePageLocal = useDeletePageMutation();
const modal = useModal();
const pageInCanvas = canvasPages?.find((p) => p.title === pageName); const pageInCanvas = canvasPages?.find((p) => p.title === pageName);
@@ -88,6 +88,7 @@ export default function EditPageButtons({
{!pageInCanvas && ( {!pageInCanvas && (
<Modal <Modal
modalControl={modal}
buttonText="Delete Localy" buttonText="Delete Localy"
buttonClass="btn-danger" buttonClass="btn-danger"
modalWidth="w-1/5" modalWidth="w-1/5"

View File

@@ -1,5 +1,5 @@
import { useCourseContext } from "@/app/course/[courseName]/context/courseContext"; import { useCourseContext } from "@/app/course/[courseName]/context/courseContext";
import Modal from "@/components/Modal"; import Modal, { useModal } from "@/components/Modal";
import { Spinner } from "@/components/Spinner"; import { Spinner } from "@/components/Spinner";
import { import {
useCanvasQuizzesQuery, useCanvasQuizzesQuery,
@@ -33,6 +33,7 @@ export function QuizButtons({
const addToCanvas = useAddQuizToCanvasMutation(); const addToCanvas = useAddQuizToCanvasMutation();
const deleteFromCanvas = useDeleteQuizFromCanvasMutation(); const deleteFromCanvas = useDeleteQuizFromCanvasMutation();
const deleteLocal = useDeleteQuizMutation(); const deleteLocal = useDeleteQuizMutation();
const modal = useModal();
const quizInCanvas = canvasQuizzes.find((c) => c.title === quizName); const quizInCanvas = canvasQuizzes.find((c) => c.title === quizName);
@@ -74,6 +75,7 @@ export function QuizButtons({
)} )}
{!quizInCanvas && ( {!quizInCanvas && (
<Modal <Modal
modalControl={modal}
buttonText="Delete Localy" buttonText="Delete Localy"
buttonClass="btn-danger" buttonClass="btn-danger"
modalWidth="w-1/5" modalWidth="w-1/5"

View File

@@ -1,25 +1,41 @@
"use client"; "use client";
import React, { ReactNode, useState } from "react"; import React, { ReactNode, useState } from "react";
export interface ModalControl {
isOpen: boolean;
openModal: () => void;
closeModal: () => void;
}
export function useModal() {
const [isOpen, setIsOpen] = useState(false);
const openModal = () => setIsOpen(true);
const closeModal = () => setIsOpen(false);
return {
isOpen,
openModal,
closeModal,
};
}
export default function Modal({ export default function Modal({
children, children,
buttonText, buttonText,
buttonClass = "", buttonClass = "",
modalWidth = "w-1/3", modalWidth = "w-1/3",
modalControl,
}: { }: {
children: (props: { closeModal: () => void }) => ReactNode; children: (props: { closeModal: () => void }) => ReactNode;
buttonText: string; buttonText: string;
buttonClass?: string; buttonClass?: string;
modalWidth?: string; modalWidth?: string;
modalControl: ModalControl;
}) { }) {
const [isOpen, setIsOpen] = useState(false);
const openModal = () => setIsOpen(true);
const closeModal = () => setIsOpen(false);
return ( return (
<> <>
<button onClick={openModal} className={buttonClass}> <button onClick={modalControl.openModal} className={buttonClass}>
{buttonText} {buttonText}
</button> </button>
@@ -27,9 +43,11 @@ export default function Modal({
className={ className={
" fixed inset-0 flex items-center justify-center transition-all duration-400 h-screen " + " fixed inset-0 flex items-center justify-center transition-all duration-400 h-screen " +
" bg-black" + " bg-black" +
(isOpen ? " bg-opacity-50 z-50 " : " bg-opacity-0 -z-50 ") (modalControl.isOpen
? " bg-opacity-50 z-50 "
: " bg-opacity-0 -z-50 ")
} }
onClick={closeModal} onClick={modalControl.closeModal}
> >
<div <div
onClick={(e) => { onClick={(e) => {
@@ -40,10 +58,11 @@ export default function Modal({
` bg-slate-800 p-6 rounded-lg shadow-lg ` + ` bg-slate-800 p-6 rounded-lg shadow-lg ` +
modalWidth + modalWidth +
` transition-all duration-400 ` + ` transition-all duration-400 ` +
` ${isOpen ? "opacity-100" : "opacity-0"}` ` ${modalControl.isOpen ? "opacity-100" : "opacity-0"}`
} }
> >
{isOpen && children({ closeModal })} {modalControl.isOpen &&
children({ closeModal: modalControl.closeModal })}
</div> </div>
</div> </div>
</> </>