import { ClassController, type ClassesResponse, type ClassResponse } from "@/controllers/classes"; import type { StudentsResponse } from "@/controllers/students"; import type { ClassDTO } from "@dwengo-1/common/interfaces/class"; import { QueryClient, useMutation, useQuery, useQueryClient, type UseMutationReturnType, type UseQueryReturnType, } from "@tanstack/vue-query"; import { computed, toValue, type MaybeRefOrGetter } from "vue"; import { invalidateAllAssignmentKeys } from "./assignments"; import { invalidateAllGroupKeys } from "./groups"; import { invalidateAllSubmissionKeys } from "./submissions"; import type { TeachersResponse } from "@/controllers/teachers"; import type { TeacherInvitationsResponse } from "@/controllers/teacher-invitations"; const classController = new ClassController(); /* Query cache keys */ function classesQueryKey(full: boolean) { return ["classes", full]; } function classQueryKey(classid: string) { return ["class", classid]; } function classStudentsKey(classid: string, full: boolean) { return ["class-students", classid, full]; } function classTeachersKey(classid: string, full: boolean) { return ["class-teachers", classid, full]; } function classTeacherInvitationsKey(classid: string, full: boolean) { return ["class-teacher-invitations", classid, full]; } function classAssignmentsKey(classid: string, full: boolean) { return ["class-assignments", classid, full]; } export async function invalidateAllClassKeys(queryClient: QueryClient, classid?: string) { const keys = ["class", "class-students", "class-teachers", "class-teacher-invitations", "class-assignments"]; for (const key of keys) { const queryKey = [key, classid].filter((arg) => arg !== undefined); await queryClient.invalidateQueries({ queryKey: queryKey }); } await queryClient.invalidateQueries({ queryKey: ["classes"] }); } /* Queries */ export function useClassesQuery(full: MaybeRefOrGetter = true): UseQueryReturnType { return useQuery({ queryKey: computed(() => classesQueryKey(toValue(full))), queryFn: async () => classController.getAll(toValue(full)), }); } export function useClassQuery(id: MaybeRefOrGetter): UseQueryReturnType { return useQuery({ queryKey: computed(() => classQueryKey(toValue(id)!)), queryFn: async () => classController.getById(toValue(id)!), enabled: () => Boolean(toValue(id)), }); } export function useCreateClassMutation(): UseMutationReturnType { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (data) => classController.createClass(data), onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: ["classes"] }); }, }); } export function useDeleteClassMutation(): UseMutationReturnType { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (id) => classController.deleteClass(id), onSuccess: async (data) => { await invalidateAllClassKeys(queryClient, data.class.id); await invalidateAllAssignmentKeys(queryClient, data.class.id); await invalidateAllGroupKeys(queryClient, data.class.id); await invalidateAllSubmissionKeys(queryClient, data.class.id); }, }); } export function useUpdateClassMutation(): UseMutationReturnType< ClassResponse, Error, { cid: string; data: Partial }, unknown > { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ cid, data }) => classController.updateClass(cid, data), onSuccess: async (data) => { await invalidateAllClassKeys(queryClient, data.class.id); await invalidateAllAssignmentKeys(queryClient, data.class.id); await invalidateAllGroupKeys(queryClient, data.class.id); await invalidateAllSubmissionKeys(queryClient, data.class.id); }, }); } export function useClassStudentsQuery( id: MaybeRefOrGetter, full: MaybeRefOrGetter = true, ): UseQueryReturnType { return useQuery({ queryKey: computed(() => classStudentsKey(toValue(id)!, toValue(full))), queryFn: async () => classController.getStudents(toValue(id)!, toValue(full)), enabled: () => Boolean(toValue(id)), }); } export function useClassAddStudentMutation(): UseMutationReturnType< ClassResponse, Error, { id: string; username: string }, unknown > { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ id, username }) => classController.addStudent(id, username), onSuccess: async (data) => { await queryClient.invalidateQueries({ queryKey: classQueryKey(data.class.id) }); await queryClient.invalidateQueries({ queryKey: classStudentsKey(data.class.id, true) }); await queryClient.invalidateQueries({ queryKey: classStudentsKey(data.class.id, false) }); }, }); } export function useClassDeleteStudentMutation(): UseMutationReturnType< ClassResponse, Error, { id: string; username: string }, unknown > { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ id, username }) => classController.deleteStudent(id, username), onSuccess: async (data) => { await queryClient.invalidateQueries({ queryKey: classQueryKey(data.class.id) }); await queryClient.invalidateQueries({ queryKey: classStudentsKey(data.class.id, true) }); await queryClient.invalidateQueries({ queryKey: classStudentsKey(data.class.id, false) }); }, }); } export function useClassTeachersQuery( id: MaybeRefOrGetter, full: MaybeRefOrGetter = true, ): UseQueryReturnType { return useQuery({ queryKey: computed(() => classTeachersKey(toValue(id)!, toValue(full))), queryFn: async () => classController.getTeachers(toValue(id)!, toValue(full)), enabled: () => Boolean(toValue(id)), }); } export function useClassAddTeacherMutation(): UseMutationReturnType< ClassResponse, Error, { id: string; username: string }, unknown > { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ id, username }) => classController.addTeacher(id, username), onSuccess: async (data) => { await queryClient.invalidateQueries({ queryKey: classQueryKey(data.class.id) }); await queryClient.invalidateQueries({ queryKey: classTeachersKey(data.class.id, true) }); await queryClient.invalidateQueries({ queryKey: classTeachersKey(data.class.id, false) }); }, }); } export function useClassDeleteTeacherMutation(): UseMutationReturnType< ClassResponse, Error, { id: string; username: string }, unknown > { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ id, username }) => classController.deleteTeacher(id, username), onSuccess: async (data) => { await queryClient.invalidateQueries({ queryKey: classQueryKey(data.class.id) }); await queryClient.invalidateQueries({ queryKey: classTeachersKey(data.class.id, true) }); await queryClient.invalidateQueries({ queryKey: classTeachersKey(data.class.id, false) }); }, }); } export function useClassTeacherInvitationsQuery( id: MaybeRefOrGetter, full: MaybeRefOrGetter = true, ): UseQueryReturnType { return useQuery({ queryKey: computed(() => classTeacherInvitationsKey(toValue(id)!, toValue(full))), queryFn: async () => classController.getTeacherInvitations(toValue(id)!, toValue(full)), enabled: () => Boolean(toValue(id)), }); } export function useClassAssignmentsQuery( id: MaybeRefOrGetter, full: MaybeRefOrGetter = true, ): UseQueryReturnType { return useQuery({ queryKey: computed(() => classAssignmentsKey(toValue(id)!, toValue(full))), queryFn: async () => classController.getAssignments(toValue(id)!, toValue(full)), enabled: () => Boolean(toValue(id)), }); }