}>
{dateInfo}
diff --git a/frontend/src/components/organisms/EventForm.tsx b/frontend/src/components/organisms/EventForm.tsx
index 598c23b0..4f3325f7 100644
--- a/frontend/src/components/organisms/EventForm.tsx
+++ b/frontend/src/components/organisms/EventForm.tsx
@@ -26,6 +26,8 @@ import { api } from "@/utils/api";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import Dropzone from "../atoms/Dropzone";
import EditorComp from "@/components/atoms/Editor";
+import Modal from "../molecules/Modal";
+import Alert from "../atoms/Alert";
interface EventFormProps {
eventId?: string | string[] | undefined;
@@ -45,6 +47,7 @@ type FormValues = {
startTime: Date;
endTime: Date;
mode: string;
+ status: string;
};
/** An EventForm page */
@@ -86,6 +89,10 @@ const EventForm = ({
setStatus(status);
};
+ type modalBodyProps = {
+ handleClose: () => void;
+ };
+
/** React hook form */
const {
register,
@@ -116,6 +123,11 @@ const EventForm = ({
/** Handles form errors for time and date validation */
const [errorMessage, setErrorMessage] = useState
(null);
+ /** Handles for cancelling an event */
+ const [open, setOpen] = useState(false);
+ const handleOpen = () => setOpen(true);
+ const handleClose = () => setOpen(false);
+
/** Tanstack mutation for creating a new event */
const {
mutateAsync: handleCreateNewEvent,
@@ -210,6 +222,25 @@ const EventForm = ({
},
});
+ /** Tanstack mutation for canceling an event */
+ const { mutateAsync: handleCancelEventAsync, isPending: cancelEventPending } =
+ useMutation({
+ mutationFn: async () => {
+ const { response } = await api.patch(`/events/${eventId}/status`, {
+ status: "CANCELED",
+ });
+ return response;
+ },
+ retry: false,
+ onSuccess: () => {
+ queryClient.invalidateQueries({
+ queryKey: ["event", eventId],
+ });
+ localStorage.setItem("eventCanceled", "true");
+ router.push("/events/view");
+ },
+ });
+
/** Helper for handling creating events */
const handleCreateEvent: SubmitHandler = async (data) => {
try {
@@ -230,8 +261,49 @@ const EventForm = ({
}
};
+ /** Helper for handling canceling events */
+ const handleCancelEvent = async () => {
+ try {
+ await handleCancelEventAsync();
+ } catch (error) {
+ setErrorNotificationOpen(true);
+ setErrorMessage("We were unable to cancel this event. Please try again");
+ }
+ };
+
+ /** Confirmation modal for canceling an event */
+ const ModalBody = ({ handleClose }: modalBodyProps) => {
+ return (
+
+
+ Are you sure you want to cancel this event?
+
+
+
+
+
+
+
+
+
+
+ );
+ };
+
+ // Check if this event has been canceled
+ const thisEventHasBeenCanceled = eventDetails?.status === "CANCELED";
+
return (
<>
+ }
+ />
{/* Error component */}
Error: {errorMessage}
+ {thisEventHasBeenCanceled && (
+
+
This event has been canceled.
+
+ )}
diff --git a/frontend/src/components/organisms/ViewEvents.tsx b/frontend/src/components/organisms/ViewEvents.tsx
index 01a28440..fa9ea00b 100644
--- a/frontend/src/components/organisms/ViewEvents.tsx
+++ b/frontend/src/components/organisms/ViewEvents.tsx
@@ -63,6 +63,7 @@ const UpcomingEvents = () => {
endDate: event["endDate"],
role: "Supervisor",
hours: eventHours(event["startDate"], event["endDate"]),
+ status: event["status"],
imageURL: event["imageURL"],
};
}
@@ -79,6 +80,7 @@ const UpcomingEvents = () => {
role: "Volunteer",
hours: eventHours(event["startDate"], event["endDate"]),
imageURL: event["imageURL"],
+ status: event["status"],
};
}
) || [];
@@ -213,6 +215,7 @@ const PastEvents = () => {
endDate: event["endDate"],
role: "Supervisor",
hours: eventHours(event["endDate"], event["startDate"]),
+ status: event["status"],
});
});
@@ -225,6 +228,7 @@ const PastEvents = () => {
endDate: event["endDate"],
role: "Volunteer",
hours: eventHours(event["endDate"], event["startDate"]),
+ status: event["status"],
});
});
@@ -311,6 +315,19 @@ const PastEvents = () => {
renderHeader: (params) => (
{params.colDef.headerName}
),
+ renderCell: (params) => (
+
+ {params.row.name}
+ {params.row.status == "CANCELED" && (
+
+ )}
+
+ ),
},
{
field: "startDate",
@@ -373,6 +390,19 @@ const PastEvents = () => {
renderHeader: (params) => (
{params.colDef.headerName}
),
+ renderCell: (params) => (
+
+ {params.row.name}
+ {params.row.status == "CANCELED" && (
+
+ )}
+
+ ),
},
{
field: "startDate",
@@ -519,6 +549,7 @@ const ViewEvents = () => {
const [isEventCreated, setIsEventCreated] = useState(false);
const [isEventEdited, setIsEventEdited] = useState(false);
+ const [isEventCanceled, setIsEventCanceled] = useState(false);
useEffect(() => {
const isEventCreated = localStorage.getItem("eventCreated");
@@ -530,6 +561,10 @@ const ViewEvents = () => {
setIsEventEdited(true);
localStorage.removeItem("eventEdited");
}
+ if (localStorage.getItem("eventCanceled")) {
+ setIsEventCanceled(true);
+ localStorage.removeItem("eventCanceled");
+ }
}, []);
return (
@@ -551,6 +586,16 @@ const ViewEvents = () => {
>
Your event has been successfully updated!
+
+ {/* Event canceled success notification */}
+
setIsEventCanceled(false)}
+ >
+ Your event has been successfully canceled!
+
+
My Events }
diff --git a/frontend/src/pages/events/[eventid]/edit.tsx b/frontend/src/pages/events/[eventid]/edit.tsx
index 6b469c8c..901ddb17 100644
--- a/frontend/src/pages/events/[eventid]/edit.tsx
+++ b/frontend/src/pages/events/[eventid]/edit.tsx
@@ -20,6 +20,7 @@ type eventData = {
startTime: Date;
endTime: Date;
mode: string;
+ status: string;
};
/** An EditEvent page */
@@ -48,6 +49,7 @@ const EditEvent = () => {
startTime: data?.startDate,
endTime: data?.endDate,
mode: data?.mode,
+ status: data?.status,
};
/** Loading screen */
diff --git a/frontend/src/utils/types.ts b/frontend/src/utils/types.ts
index 49a33915..ce00952e 100644
--- a/frontend/src/utils/types.ts
+++ b/frontend/src/utils/types.ts
@@ -11,6 +11,7 @@ export type ViewEventsEvent = {
ownerId?: string;
description?: string;
capacity?: number;
+ status?: EventStatus;
imageURL?: string;
};