diff --git a/src/components/gameClass/GameClassByClassGroupDisplay.tsx b/src/components/gameClass/GameClassByClassGroupDisplay.tsx
new file mode 100644
index 0000000..5f299b3
--- /dev/null
+++ b/src/components/gameClass/GameClassByClassGroupDisplay.tsx
@@ -0,0 +1,45 @@
+import { useGetGameClassesByClassGroup } from "@/hooks/GameClassHooks";
+import DangerMessage from "../message/DangerMessage";
+
+
+export default function GameClassByClassGroupDisplay({
+ classGroupId
+}:{
+ classGroupId: string;
+}){
+ const gameClassesQuery = useGetGameClassesByClassGroup(classGroupId);
+ const displayId = crypto.randomUUID().replaceAll("-", "");
+
+
+ if(gameClassesQuery.status === "pending"){
+ return (
Loading...
);
+ }
+ else if(gameClassesQuery.status === "error"){
+ return (Error: {gameClassesQuery.error.message});
+ }
+ else{
+ return (
+
+ {
+ gameClassesQuery.data.map((gameClass) => (
+
+ {
+ gameClass.gameClassIcon &&
+

+ }
+ {gameClass.gameClassName}
+
+ ))
+ }
+
+ );
+ }
+}
diff --git a/src/components/gameClass/GameClassesSelector.tsx b/src/components/gameClass/GameClassesSelector.tsx
new file mode 100644
index 0000000..37e4a46
--- /dev/null
+++ b/src/components/gameClass/GameClassesSelector.tsx
@@ -0,0 +1,82 @@
+import { useGetGameClasses } from "@/hooks/GameClassHooks";
+import { useEffect, useState } from "react";
+import DangerMessage from "../message/DangerMessage";
+
+export function GameClassesSelector({
+ gameId,
+ gameClassIds,
+ onChange
+}:{
+ gameId: string;
+ gameClassIds?: string[];
+ onChange?: (gameClassIds: string[]) => void;
+}){
+ const [ selectedGameClassIds, setSelectedGameClassIds ] = useState(gameClassIds ?? []);
+ const selectorId = crypto.randomUUID().replaceAll("-", "");
+
+
+ const gameClassesQuery = useGetGameClasses(gameId, 0, 100, undefined);
+
+
+ const updateSelectedGameClassIds = (selectedGameClassId: string) => {
+ if(selectedGameClassIds.includes(selectedGameClassId)){
+ setSelectedGameClassIds(selectedGameClassIds.filter((id) => id !== selectedGameClassId));
+ }
+ else{
+ setSelectedGameClassIds([...selectedGameClassIds, selectedGameClassId]);
+ }
+ }
+
+
+ useEffect(() => {
+ onChange?.(selectedGameClassIds);
+ }, [ selectedGameClassIds, onChange ]);
+
+
+ if(gameClassesQuery.status === "pending"){
+ return Loading...
+ }
+ else if(gameClassesQuery.status === "error"){
+ return Error loading Game Classes: {gameClassesQuery.error.message}
+ }
+ else{
+ return (
+
+ {
+ gameClassesQuery.data.map((gameClass) => (
+
+
updateSelectedGameClassIds(e.target.value)}
+ />
+
+
+ ))
+ }
+
+ );
+ }
+}
diff --git a/src/hooks/ClassGroupHooks.ts b/src/hooks/ClassGroupHooks.ts
new file mode 100644
index 0000000..1ac8389
--- /dev/null
+++ b/src/hooks/ClassGroupHooks.ts
@@ -0,0 +1,135 @@
+import { ClassGroup } from "@/interface/ClassGroup";
+import { api } from "@/util/AxiosUtil";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+
+
+export function useGetClassGroups(raidGroupId: string, page: number, pageSize: number, searchTerm?: string){
+ return useQuery({
+ queryKey: ["classGroups", raidGroupId, { page, pageSize, searchTerm }],
+ queryFn: async () => {
+ const params = new URLSearchParams();
+ params.append("page", page.toString());
+ params.append("pageSize", pageSize.toString());
+ if(searchTerm){
+ params.append("searchTerm", searchTerm);
+ }
+
+ const response = await api.get(`/raidGroup/${raidGroupId}/classGroup?${params}`);
+
+ if(response.status !== 200){
+ throw new Error("Failed to get class groups");
+ }
+ else if(response.data.errors){
+ throw new Error(response.data.errors.join(", "));
+ }
+
+ return response.data as ClassGroup[];
+ }
+ });
+}
+
+export function useGetClassGroupsCount(raidGroupId: string, searchTerm?: string){
+ const searchParams = new URLSearchParams();
+ if(searchTerm){
+ searchParams.append("searchTerm", searchTerm);
+ }
+
+
+ return useQuery({
+ queryKey: ["classGroups", "count", searchTerm],
+ queryFn: async () => {
+ const response = await api.get(`/raidGroup/${raidGroupId}/classGroup/count?${searchParams}`);
+
+ if(response.status !== 200){
+ throw new Error("Failed to get class groups count");
+ }
+ else if(response.data.errors){
+ throw new Error(response.data.errors.join(", "));
+ }
+
+ return response.data.count as number;
+ }
+ });
+}
+
+
+export function useCreateClassGroup(raidGroupId: string){
+ const queryClient = useQueryClient();
+
+
+ return useMutation({
+ mutationKey: ["createClassGroup"],
+ mutationFn: async ({classGroupName, gameClassIds}:{classGroupName: string; gameClassIds: string[];}) => {
+ const response = await api.post(`/raidGroup/${raidGroupId}/classGroup`,
+ {
+ classGroup: {
+ classGroupName: classGroupName,
+ raidGroupId: raidGroupId
+ },
+ gameClassIds
+ }
+ );
+
+ if(response.status !== 200){
+ throw new Error("Failed to create class group");
+ }
+ else if(response.data.errors){
+ throw new Error(response.data.errors.join(", "));
+ }
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({queryKey: ["classGroups"]});
+ }
+ });
+}
+
+export function useUpdateClassGroup(raidGroupId: string){
+ const queryClient = useQueryClient();
+
+
+ return useMutation({
+ mutationKey: ["updateClassGroup"],
+ mutationFn: async ({classGroup, gameClassIds}:{classGroup: ClassGroup; gameClassIds: string[];}) => {
+ console.log("Hit");
+ const response = await api.put(`/raidGroup/${raidGroupId}/classGroup/${classGroup.classGroupId}`,
+ {
+ classGroup,
+ gameClassIds
+ }
+ );
+
+ if(response.status !== 200){
+ throw new Error("Failed to update class group");
+ }
+ else if(response.data.errors){
+ throw new Error(response.data.errors.join(", "));
+ }
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({queryKey: ["gameClasses", "classGroups"]});
+ queryClient.invalidateQueries({queryKey: ["classGroups"]});
+ }
+ });
+}
+
+export function useDeleteClassGroup(raidGroupId: string, classGroupId: string){
+ const queryClient = useQueryClient();
+
+
+ return useMutation({
+ mutationKey: ["deleteClassGroup", classGroupId, raidGroupId],
+ mutationFn: async () => {
+ const response = await api.delete(`/raidGroup/${raidGroupId}/classGroup/${classGroupId}`);
+
+ if(response.status !== 200){
+ throw new Error("Failed to delete class group");
+ }
+ else if(response.data.errors){
+ throw new Error(response.data.errors.join(", "));
+ }
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({queryKey: ["classGroups"]});
+ }
+ });
+}
diff --git a/src/hooks/GameClassHooks.ts b/src/hooks/GameClassHooks.ts
index 705b846..464d2bf 100644
--- a/src/hooks/GameClassHooks.ts
+++ b/src/hooks/GameClassHooks.ts
@@ -28,6 +28,26 @@ export function useGetGameClasses(gameId: string, page: number, pageSize: number
});
}
+export function useGetGameClassesByClassGroup(classGroupId: string){
+ return useQuery({
+ queryKey: ["gameClasses", "classGroups", classGroupId],
+ queryFn: async () => {
+ const response = await api.get(`/gameClass/classGroup/${classGroupId}`);
+
+ if(response.status !== 200){
+ throw new Error("Failed to get game classes");
+ }
+ else if(response.data.errors){
+ throw new Error(response.data.errors.join(", "));
+ }
+
+ return response.data as GameClass[];
+ },
+ enabled: !!classGroupId
+ });
+
+}
+
export function useGetGameClassesCount(gameId: string, searchTerm?: string){
const searchParams = new URLSearchParams();
if(searchTerm){
diff --git a/src/interface/ClassGroup.ts b/src/interface/ClassGroup.ts
new file mode 100644
index 0000000..21c66aa
--- /dev/null
+++ b/src/interface/ClassGroup.ts
@@ -0,0 +1,5 @@
+export interface ClassGroup {
+ classGroupId?: string;
+ raidGroupId: string;
+ classGroupName: string;
+}
diff --git a/src/pages/protected/RaidGroupPage.tsx b/src/pages/protected/RaidGroupPage.tsx
index 390370a..2899093 100644
--- a/src/pages/protected/RaidGroupPage.tsx
+++ b/src/pages/protected/RaidGroupPage.tsx
@@ -3,6 +3,7 @@ import { useGetRaidGroup } from "@/hooks/RaidGroupHooks";
import { RaidGroup } from "@/interface/RaidGroup";
import RaidGroupCalendarDisplay from "@/ui/calendar/RaidGroupCalendarDisplay";
import RaidGroupHeader from "@/ui/calendar/RaidGroupHeader";
+import ClassGroupsTab from "@/ui/classGroup/ClassGroupsTab";
import PersonTab from "@/ui/person/PersonTab";
import { useEffect, useState } from "react";
import { Navigate, useParams } from "react-router";
@@ -45,6 +46,10 @@ export default function RaidGroupPage(){
{
tabHeader: "People",
tabContent:
+ },
+ {
+ tabHeader: "Class Groups",
+ tabContent:
}
];
diff --git a/src/ui/classGroup/ClassGroupButtons.tsx b/src/ui/classGroup/ClassGroupButtons.tsx
new file mode 100644
index 0000000..a21ff15
--- /dev/null
+++ b/src/ui/classGroup/ClassGroupButtons.tsx
@@ -0,0 +1,38 @@
+import { ButtonProps } from "@/components/button/Button";
+import DangerButton from "@/components/button/DangerButton";
+import PrimaryButton from "@/components/button/PrimaryButton";
+import { BsPencilFill, BsTrash3 } from "react-icons/bs";
+
+
+export default function ClassGroupButtons({
+ buttonProps,
+ showClassGroupModal,
+ showDeleteClassGroupModal
+}:{
+ buttonProps: ButtonProps;
+ showClassGroupModal: () => void;
+ showDeleteClassGroupModal: () => void;
+}){
+ return (
+
+ );
+}
diff --git a/src/ui/classGroup/ClassGroupList.tsx b/src/ui/classGroup/ClassGroupList.tsx
new file mode 100644
index 0000000..13d9535
--- /dev/null
+++ b/src/ui/classGroup/ClassGroupList.tsx
@@ -0,0 +1,102 @@
+import { ButtonProps } from "@/components/button/Button";
+import GameClassByClassGroupDisplay from "@/components/gameClass/GameClassByClassGroupDisplay";
+import Table from "@/components/table/Table";
+import { useGetGameClassesByClassGroup } from "@/hooks/GameClassHooks";
+import { ClassGroup } from "@/interface/ClassGroup";
+import { RaidGroup } from "@/interface/RaidGroup";
+import { useState } from "react";
+import ClassGroupButtons from "./ClassGroupButtons";
+import ClassGroupModal from "./modal/ClassGroupModal";
+import DeleteClassGroupModal from "./modal/DeleteClassGroupModal";
+
+
+export default function ClassGroupList({
+ classGroups,
+ raidGroup
+}:{
+ classGroups: ClassGroup[];
+ raidGroup: RaidGroup;
+}){
+ const [ selectedClassGroup, setSelectedClassGroup ] = useState();
+ const [ displayClassGroupModal, setDisplayClassGroupModal ] = useState(false);
+ const [ displayDeleteClassGroupModal, setDisplayDeleteClassGroupModal ] = useState(false);
+ const gameClassesQuery = useGetGameClassesByClassGroup(selectedClassGroup?.classGroupId ?? "");
+
+
+ const buttonProps: ButtonProps = {
+ variant: "ghost",
+ size: "md",
+ shape: "square"
+ };
+
+
+ const headElements: React.ReactNode[] = [
+
+ Name
+
,
+
+ Classes
+
,
+
+ Actions
+
+ ];
+
+ const bodyElements: React.ReactNode[][] = classGroups.map((classGroup) => [
+
+ {classGroup.classGroupName}
+
,
+
+
+
,
+
+
+
+
+
{
+ setSelectedClassGroup(classGroup);
+ setDisplayClassGroupModal(true);
+ }}
+ showDeleteClassGroupModal={() => {
+ setSelectedClassGroup(classGroup);
+ setDisplayDeleteClassGroupModal(true);
+ }}
+ />
+
+ ]);
+
+
+ return (
+ <>
+
+ { setDisplayClassGroupModal(false); setSelectedClassGroup(undefined); }}
+ classGroup={selectedClassGroup}
+ raidGroup={raidGroup}
+ selectedGameClasses={gameClassesQuery.data ?? []}
+ />
+ { setDisplayDeleteClassGroupModal(false); setSelectedClassGroup(undefined); }}
+ raidGroupId={selectedClassGroup?.raidGroupId ?? ""}
+ classGroup={selectedClassGroup}
+ />
+ >
+ );
+}
diff --git a/src/ui/classGroup/ClassGroupListSkeleton.tsx b/src/ui/classGroup/ClassGroupListSkeleton.tsx
new file mode 100644
index 0000000..624ecf4
--- /dev/null
+++ b/src/ui/classGroup/ClassGroupListSkeleton.tsx
@@ -0,0 +1,72 @@
+import { ButtonShape, ButtonSizeType, ButtonVariant } from "@/components/button/Button";
+import Table from "@/components/table/Table";
+import { elementBg } from "@/util/SkeletonUtil";
+import ClassGroupButtons from "./ClassGroupButtons";
+
+export default function ClassGroupListSkeleton(){
+ const headerElements: React.ReactElement[] = [
+
+ Name
+
,
+
+ Classes
+
,
+
+ Actions
+
+ ];
+
+ const bodyElements: React.ReactNode[][] = [
+ ClassGroupSkeleton(),
+ ClassGroupSkeleton(),
+ ClassGroupSkeleton(),
+ ClassGroupSkeleton(),
+ ClassGroupSkeleton(),
+ ClassGroupSkeleton(),
+ ClassGroupSkeleton(),
+ ClassGroupSkeleton(),
+ ClassGroupSkeleton(),
+ ClassGroupSkeleton()
+ ];
+
+
+ return (
+
+ );
+}
+
+
+function ClassGroupSkeleton(): React.ReactNode[]{
+ const buttonsProps = {
+ buttonProps: {
+ variant: "ghost" as ButtonVariant,
+ size: "md" as ButtonSizeType,
+ shape: "square" as ButtonShape,
+ disabled: true
+ },
+ showClassGroupModal: () => {},
+ showDeleteClassGroupModal: () => {}
+ }
+
+ const elements: React.ReactNode[] = [
+ ,
+ ,
+
+ ];
+
+ return elements;
+}
diff --git a/src/ui/classGroup/ClassGroupsLoader.tsx b/src/ui/classGroup/ClassGroupsLoader.tsx
new file mode 100644
index 0000000..420bee4
--- /dev/null
+++ b/src/ui/classGroup/ClassGroupsLoader.tsx
@@ -0,0 +1,42 @@
+import DangerMessage from "@/components/message/DangerMessage";
+import { useGetClassGroups } from "@/hooks/ClassGroupHooks";
+import { useGetGameClasses } from "@/hooks/GameClassHooks";
+import { RaidGroup } from "@/interface/RaidGroup";
+import ClassGroupList from "./ClassGroupList";
+
+
+export default function ClassGroupsLoader({
+ page,
+ pageSize,
+ searchTerm,
+ raidGroup,
+ gameId
+}:{
+ page: number;
+ pageSize: number;
+ searchTerm?: string;
+ raidGroup: RaidGroup;
+ gameId: string;
+}){
+ const classGroupsQuery = useGetClassGroups(raidGroup?.raidGroupId ?? "", page - 1, pageSize, searchTerm);
+ const gameClassesQuery = useGetGameClasses(gameId, 0, 100);
+
+
+ if((classGroupsQuery.status === "pending") || (gameClassesQuery.status === "pending")){
+ return Loading...
+ }
+ else if(classGroupsQuery.status === "error"){
+ return Error: {classGroupsQuery.error.message}
+ }
+ else if(gameClassesQuery.status === "error"){
+ return Error: {gameClassesQuery.error.message}
+ }
+ else{
+ return (
+
+ );
+ }
+}
diff --git a/src/ui/classGroup/ClassGroupsTab.tsx b/src/ui/classGroup/ClassGroupsTab.tsx
new file mode 100644
index 0000000..3c84d33
--- /dev/null
+++ b/src/ui/classGroup/ClassGroupsTab.tsx
@@ -0,0 +1,108 @@
+import PrimaryButton from "@/components/button/PrimaryButton";
+import TextInput from "@/components/input/TextInput";
+import Pagination from "@/components/pagination/Pagination";
+import { useGetClassGroupsCount } from "@/hooks/ClassGroupHooks";
+import { RaidGroup } from "@/interface/RaidGroup";
+import { useEffect, useState } from "react";
+import { useDebouncedCallback } from "use-debounce";
+import ClassGroupsLoader from "./ClassGroupsLoader";
+import ClassGroupModal from "./modal/ClassGroupModal";
+
+
+export default function ClassGroupsTab({
+ raidGroup
+}:{
+ raidGroup: RaidGroup;
+}){
+ const [ displayCreateClassGroupModal, setDisplayCreateClassGroupModal ] = useState(false);
+ const [ page, setPage ] = useState(1);
+ const [ totalPages, setTotalPages ] = useState(1);
+ const [ searchTerm, setSearchTerm ] = useState("");
+ const [ sentSearchTerm, setSentSearchTerm ] = useState("");
+ const pageSize = 10;
+ const modalId = crypto.randomUUID().replaceAll("-", "");
+
+
+ const classGroupsCountQuery = useGetClassGroupsCount(raidGroup.raidGroupId!, sentSearchTerm);
+
+
+ const updateSearchTerm = useDebouncedCallback((newSearchTerm: string) => {
+ setSentSearchTerm(newSearchTerm);
+ }, 1000);
+
+
+ useEffect(() => {
+ updateSearchTerm(searchTerm ?? "");
+ }, [ searchTerm, updateSearchTerm ]);
+
+
+ useEffect(() => {
+ if(classGroupsCountQuery.status === "success"){
+ setTotalPages(Math.ceil(classGroupsCountQuery.data / pageSize));
+ }
+ }, [ classGroupsCountQuery ]);
+
+
+ return (
+ <>
+
+
+
+
+ {/* Add Class Group Button */}
+
+
setDisplayCreateClassGroupModal(true)}
+ >
+ Create Class Group
+
+
setDisplayCreateClassGroupModal(false)}
+ classGroup={undefined}
+ selectedGameClasses={[]}
+ raidGroup={raidGroup}
+ />
+
+ {/* Class Group Search Box */}
+
+
+ setSearchTerm(e.target.value)}
+ placeholder="Search"
+ />
+
+
+
+ {/* Class Group List */}
+
+ {/* Pagination */}
+
+ >
+ );
+}
diff --git a/src/ui/classGroup/modal/ClassGroupModal.tsx b/src/ui/classGroup/modal/ClassGroupModal.tsx
new file mode 100644
index 0000000..977378a
--- /dev/null
+++ b/src/ui/classGroup/modal/ClassGroupModal.tsx
@@ -0,0 +1,121 @@
+import PrimaryButton from "@/components/button/PrimaryButton";
+import SecondaryButton from "@/components/button/SecondaryButton";
+import { GameClassesSelector } from "@/components/gameClass/GameClassesSelector";
+import TextInput from "@/components/input/TextInput";
+import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
+import { useCreateClassGroup, useUpdateClassGroup } from "@/hooks/ClassGroupHooks";
+import { ClassGroup } from "@/interface/ClassGroup";
+import { GameClass } from "@/interface/GameClass";
+import { RaidGroup } from "@/interface/RaidGroup";
+import { useTimedModal } from "@/providers/TimedModalProvider";
+import { useEffect, useState } from "react";
+
+
+export default function ClassGroupModal({
+ display,
+ close,
+ classGroup,
+ raidGroup,
+ selectedGameClasses
+}:{
+ display: boolean;
+ close: () => void;
+ classGroup: ClassGroup | undefined;
+ raidGroup: RaidGroup;
+ selectedGameClasses: GameClass[];
+}){
+ const [ classGroupName, setClassGroupName ] = useState(classGroup?.classGroupName ?? "");
+ const [ selectedGameClassIds, setSelectedGameClassIds ] = useState(selectedGameClasses.map(gc => gc.gameClassId ?? ""));
+ const modalId = crypto.randomUUID().replace("-", "");
+
+
+ useEffect(() => {
+ setClassGroupName(classGroup?.classGroupName ?? "");
+ setSelectedGameClassIds(selectedGameClasses.map(gc => gc.gameClassId ?? ""));
+ }, [classGroup, selectedGameClasses]);
+
+
+ const createClassGroupMutate = useCreateClassGroup(raidGroup.raidGroupId ?? "");
+ const updateClassGroupMutate = useUpdateClassGroup(raidGroup.raidGroupId ?? "");
+ const { addSuccessMessage, addErrorMessage } = useTimedModal();
+
+
+ useEffect(() => {
+ if(createClassGroupMutate.status === "success"){
+ createClassGroupMutate.reset();
+ addSuccessMessage("Class Group Created");
+ close();
+ }
+ else if(createClassGroupMutate.status === "error"){
+ createClassGroupMutate.reset();
+ addErrorMessage(`Error creating class group ${classGroupName}: ${createClassGroupMutate.error.message}`);
+ console.log(createClassGroupMutate.error);
+ }
+ else if(updateClassGroupMutate.status === "success"){
+ updateClassGroupMutate.reset();
+ addSuccessMessage("Class Group Updated");
+ close();
+ }
+ else if(updateClassGroupMutate.status === "error"){
+ updateClassGroupMutate.reset();
+ addErrorMessage(`Error updating class group ${classGroupName}: ${updateClassGroupMutate.error.message}`);
+ console.log(updateClassGroupMutate.error);
+ }
+ });
+
+
+ const createClassGroup = () => {
+ createClassGroupMutate.mutate({ classGroupName, gameClassIds: selectedGameClassIds });
+ }
+
+ const updateClassGroup = () => {
+ updateClassGroupMutate.mutate({
+ classGroup: {
+ classGroupId: classGroup?.classGroupId,
+ raidGroupId: raidGroup.raidGroupId ?? "",
+ classGroupName
+ },
+ gameClassIds: selectedGameClassIds
+ });
+ }
+
+
+ return (
+
+ setClassGroupName(e.target.value)}
+ />
+ gc.gameClassId ?? "")}
+ onChange={(gameClassIds) => setSelectedGameClassIds(gameClassIds)}
+ />
+
+ }
+ modalFooter={
+ <>
+
+ {classGroup ? "Update" : "Create"}
+
+
+ Cancel
+
+ >
+ }
+ />
+ );
+}
diff --git a/src/ui/classGroup/modal/DeleteClassGroupModal.tsx b/src/ui/classGroup/modal/DeleteClassGroupModal.tsx
new file mode 100644
index 0000000..39c03e9
--- /dev/null
+++ b/src/ui/classGroup/modal/DeleteClassGroupModal.tsx
@@ -0,0 +1,66 @@
+import DangerButton from "@/components/button/DangerButton";
+import SecondaryButton from "@/components/button/SecondaryButton";
+import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
+import { useDeleteClassGroup } from "@/hooks/ClassGroupHooks";
+import { ClassGroup } from "@/interface/ClassGroup";
+import { useTimedModal } from "@/providers/TimedModalProvider";
+import { useEffect } from "react";
+
+
+export default function DeleteClassGroupModal({
+ display,
+ close,
+ classGroup,
+ raidGroupId
+}:{
+ display: boolean;
+ close: () => void;
+ classGroup?: ClassGroup;
+ raidGroupId: string;
+}){
+ const deleteClassGroupMutate = useDeleteClassGroup(raidGroupId, classGroup?.classGroupId ?? "");
+ const { addSuccessMessage, addErrorMessage } = useTimedModal();
+
+
+ const deleteAccount = () => {
+ deleteClassGroupMutate.mutate();
+ }
+
+
+ useEffect(() => {
+ if(deleteClassGroupMutate.status === "success"){
+ deleteClassGroupMutate.reset();
+ addSuccessMessage("Class Group Deleted");
+ close();
+ }
+ else if(deleteClassGroupMutate.status === "error"){
+ deleteClassGroupMutate.reset();
+ addErrorMessage(`Error deleting class group: ${deleteClassGroupMutate.error.message}`);
+ console.log(deleteClassGroupMutate.error);
+ }
+ });
+
+
+ return (
+
+
+ Delete
+
+
+ Cancel
+
+ >
+ }
+ />
+ );
+}