import { computed, toValue } from "vue"; import type { MaybeRefOrGetter } from "vue"; import { useMutation, useQuery, useQueryClient, type UseMutationReturnType, type UseQueryReturnType, } from "@tanstack/vue-query"; import { TeacherController, type TeacherResponse, type TeachersResponse } from "@/controllers/teachers.ts"; import type { ClassesResponse } from "@/controllers/classes.ts"; import type { JoinRequestResponse, JoinRequestsResponse, StudentsResponse } from "@/controllers/students.ts"; import type { TeacherDTO } from "@dwengo-1/common/interfaces/teacher"; import { studentJoinRequestQueryKey, studentJoinRequestsQueryKey } from "@/queries/students.ts"; const teacherController = new TeacherController(); /** 🔑 Query keys */ function teachersQueryKey(full: boolean): [string, boolean] { return ["teachers", full]; } function teacherQueryKey(username: string): [string, string] { return ["teacher", username]; } function teacherClassesQueryKey(username: string, full: boolean): [string, string, boolean] { return ["teacher-classes", username, full]; } function teacherStudentsQueryKey(username: string, full: boolean): [string, string, boolean] { return ["teacher-students", username, full]; } export function teacherClassJoinRequests(classId: string): [string, string] { return ["teacher-class-join-requests", classId]; } export function useTeachersQuery(full: MaybeRefOrGetter = false): UseQueryReturnType { return useQuery({ queryKey: computed(() => teachersQueryKey(toValue(full))), queryFn: async () => teacherController.getAll(toValue(full)), }); } export function useTeacherQuery( username: MaybeRefOrGetter, ): UseQueryReturnType { return useQuery({ queryKey: computed(() => teacherQueryKey(toValue(username)!)), queryFn: async () => teacherController.getByUsername(toValue(username)!), enabled: () => Boolean(toValue(username)), }); } export function useTeacherClassesQuery( username: MaybeRefOrGetter, full: MaybeRefOrGetter = false, ): UseQueryReturnType { return useQuery({ queryKey: computed(() => teacherClassesQueryKey(toValue(username)!, toValue(full))), queryFn: async () => teacherController.getClasses(toValue(username)!, toValue(full)), enabled: () => Boolean(toValue(username)), }); } export function useTeacherStudentsQuery( username: MaybeRefOrGetter, full: MaybeRefOrGetter = false, ): UseQueryReturnType { return useQuery({ queryKey: computed(() => teacherStudentsQueryKey(toValue(username)!, toValue(full))), queryFn: async () => teacherController.getStudents(toValue(username)!, toValue(full)), enabled: () => Boolean(toValue(username)), }); } export function useTeacherJoinRequestsQuery( username: MaybeRefOrGetter, classId: MaybeRefOrGetter, ): UseQueryReturnType { return useQuery({ queryKey: computed(() => teacherClassJoinRequests(toValue(classId)!)), queryFn: async () => teacherController.getStudentJoinRequests(toValue(username)!, toValue(classId)!), enabled: () => Boolean(toValue(username)) && Boolean(toValue(classId)), }); } export function useCreateTeacherMutation(): UseMutationReturnType { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (data: TeacherDTO) => teacherController.createTeacher(data), onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: ["teachers"] }); }, }); } export function useDeleteTeacherMutation(): UseMutationReturnType { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (username: string) => teacherController.deleteTeacher(username), onSuccess: async (deletedTeacher) => { await queryClient.invalidateQueries({ queryKey: ["teachers"] }); await queryClient.invalidateQueries({ queryKey: teacherQueryKey(deletedTeacher.teacher.username) }); }, }); } export function useUpdateJoinRequestMutation(): UseMutationReturnType< JoinRequestResponse, Error, { teacherUsername: string; classId: string; studentUsername: string; accepted: boolean }, unknown > { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ teacherUsername, classId, studentUsername, accepted }) => teacherController.updateStudentJoinRequest(teacherUsername, classId, studentUsername, accepted), onSuccess: async (deletedJoinRequest) => { const username = deletedJoinRequest.request.requester.username; const classId = deletedJoinRequest.request.class; await queryClient.invalidateQueries({ queryKey: studentJoinRequestsQueryKey(username) }); await queryClient.invalidateQueries({ queryKey: studentJoinRequestQueryKey(username, classId) }); await queryClient.invalidateQueries({ queryKey: teacherClassJoinRequests(classId) }); }, }); }