mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-26 07:38:33 -06:00
adding modal control
This commit is contained in:
@@ -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"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -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,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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>
|
||||||
</>
|
</>
|
||||||
|
|||||||
Reference in New Issue
Block a user