diff --git a/client/src/common/ActionButton.tsx b/client/src/common/ActionButton.tsx index 23ca7b10d..0b389e7f4 100644 --- a/client/src/common/ActionButton.tsx +++ b/client/src/common/ActionButton.tsx @@ -72,7 +72,7 @@ export default function ActionButton(props: React.PropsWithChildren(moduleInitialValue); - + const queryResult = useQuery(GET_MODULE, { variables: { id: module.id } }); const getMakerspacesResult = useQuery(GET_FULL_MAKERSPACES); - const trainingModSavedAnimation = () => { - toast.success("Training Module Saved", { - position: "bottom-left", - autoClose: 3000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - theme: "colored", - }); - }; + const [publishModule] = useMutation(PUBLISH_MODULE, { + variables: { id: module.id }, + refetchQueries: [ + { query: GET_TRAINING_MODULES }, + { query: GET_ARCHIVED_TRAINING_MODULES }, + ], + awaitRefetchQueries: true, + onCompleted: () => { + setModule((draft) => { + draft.archived = false; + }); + toast.success("Training Module Published"); + queryResult.refetch(); + }, + onError: (error) => { + toast.error(`Failed to publish training module: ${error.message}`); + }, + }); + const [archiveModule] = useMutation(ARCHIVE_MODULE, { + variables: { id: module.id }, + refetchQueries: [ + { query: GET_TRAINING_MODULES }, + { query: GET_ARCHIVED_TRAINING_MODULES }, + ], + awaitRefetchQueries: true, + onCompleted: () => { + setModule((draft) => { + draft.archived = true; + }); + toast.success("Training Module Archived"); + queryResult.refetch(); + }, + onError: (error) => { + toast.error(`Failed to archive training module: ${error.message}`); + }, + }); - const trainingModDeletedAnimation = () => { - toast.success("Training Module Deleted", { - position: "bottom-left", - autoClose: 3000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - theme: "colored", - }); - }; + // Prefer server value for `archived` when available so buttons update after refetch + const moduleArchived = queryResult?.data?.module?.archived ?? module.archived; - const handleSaveClicked = async () => { + const handlePublishClicked = async () => { await updateModule(module); + await publishModule(); + }; - trainingModSavedAnimation(); + const handleHideClicked = async () => { + await archiveModule(); + }; - navigate(`/makerspace/${makerspaceID}/trainings`); + const handleSaveClicked = async () => { + try { + await updateModule(module); + toast.success("Training Module Saved"); + } catch (error) { + toast.error(`Failed to save training module: ${error}`); + } }; const handleDeleteClicked = async () => { @@ -93,40 +117,39 @@ export default function EditModulePage({ try { await deleteModule(); - trainingModDeletedAnimation(); + toast.success("Training Module Deleted"); navigate(`/makerspace/${makerspaceID}/trainings`); } catch (error: any) { - console.error(error); - toast.error("Failed to delete training module"); + toast.error(`Failed to delete training module: ${error.message}`); } }; const handleAddQuizItem = useCallback((item: QuizItem) => { - setModule((draft) => { - draft?.quiz.push(item); - }); + setModule((draft) => { + draft?.quiz.push(item); + }); }, [setModule]); const handleRemoveQuizItem = useCallback((itemId: string) => { - setModule((draft) => { - const index = draft!.quiz.findIndex((i) => i.id === itemId); - draft?.quiz.splice(index, 1); - }); + setModule((draft) => { + const index = draft!.quiz.findIndex((i) => i.id === itemId); + draft?.quiz.splice(index, 1); + }); }, [setModule]); const handleUpdateQuizItem = useCallback((updatedItem: QuizItem) => { - setModule((draft) => { - const index = draft!.quiz.findIndex((i) => i.id === updatedItem.id); - draft!.quiz[index] = updatedItem; - }); + setModule((draft) => { + const index = draft!.quiz.findIndex((i) => i.id === updatedItem.id); + draft!.quiz[index] = updatedItem; + }); }, [setModule]); const handleOnDragEnd = useCallback((result: DropResult) => { - setModule((draft) => { - if (!result.destination) return; - const [removed] = draft!.quiz.splice(result.source.index, 1); - draft!.quiz.splice(result.destination.index, 0, removed); - }); + setModule((draft) => { + if (!result.destination) return; + const [removed] = draft!.quiz.splice(result.source.index, 1); + draft!.quiz.splice(result.destination.index, 0, removed); + }); }, [setModule]); return ( @@ -181,15 +204,28 @@ export default function EditModulePage({ ); }} /> - - {module.archived ? ( - - ) : ( - - )} + + {moduleArchived ? ( + + ) : ( + + )} - + Save + + { + toast.success("Training Module Archived", { + position: "bottom-left", + autoClose: 3000, + }); + }, refetchQueries: [ { query: GET_TRAINING_MODULES }, { query: GET_ARCHIVED_TRAINING_MODULES }, diff --git a/client/src/pages/lab_management/training_modules/PublishTrainingModuleButton.tsx b/client/src/pages/lab_management/training_modules/PublishTrainingModuleButton.tsx index 6dc98d0e5..9753bc6e6 100644 --- a/client/src/pages/lab_management/training_modules/PublishTrainingModuleButton.tsx +++ b/client/src/pages/lab_management/training_modules/PublishTrainingModuleButton.tsx @@ -1,15 +1,23 @@ import { useMutation } from "@apollo/client"; import PublishButton from "../../../common/PublishButton"; -import GET_TRAINING_MODULES, { GET_ARCHIVED_TRAINING_MODULES, GET_MODULE, PUBLISH_MODULE } from "../../../queries/trainingQueries"; +import GET_TRAINING_MODULES, { GET_ARCHIVED_TRAINING_MODULES, GET_MODULE, PUBLISH_MODULE, UPDATE_MODULE } from "../../../queries/trainingQueries"; +import { toast } from "react-toastify"; interface PublishTrainingModuleButtonProps { moduleID: number; appearance: "icon-only" | "small" | "medium" | "large"; + onBeforePublish?: () => Promise; } export default function PublishTrainingModuleButton(props: PublishTrainingModuleButtonProps) { const [publishTrainingModule, { loading }] = useMutation(PUBLISH_MODULE, { variables: { id: props.moduleID }, + onCompleted: () => { + toast.success("Training Module Published", { + position: "bottom-left", + autoClose: 3000, + }); + }, refetchQueries: [ {query: GET_TRAINING_MODULES}, {query: GET_ARCHIVED_TRAINING_MODULES}, @@ -18,6 +26,14 @@ export default function PublishTrainingModuleButton(props: PublishTrainingModule }); const handleClick = async () => { + if (props.onBeforePublish) { + try { + await props.onBeforePublish(); + } catch (error) { + console.error("Error before publishing module:", error); + return; // Abort publishing if onBeforePublish fails + } + } await publishTrainingModule(); };