import { SubmissionController, type SubmissionResponse } from '@/controllers/submissions'; import type { SubmissionDTO } from '@dwengo-1/common/interfaces/submission'; import { QueryClient, useMutation, type UseMutationReturnType, useQuery, useQueryClient, type UseQueryReturnType, } from "@tanstack/vue-query"; import { computed, type MaybeRefOrGetter, toValue } from "vue"; import { LEARNING_PATH_KEY } from "@/queries/learning-paths.ts"; import { LEARNING_OBJECT_KEY } from "@/queries/learning-objects.ts"; import type { Language } from "@dwengo-1/common/util/language"; export const SUBMISSION_KEY = "submissions"; type SubmissionQueryKey = ["submission", string, Language | undefined, number, string, number, number, number]; function submissionQueryKey( hruid: string, language: Language, version: number, classid: string, assignmentNumber: number, groupNumber: number, submissionNumber: number, ): SubmissionQueryKey { return ["submission", hruid, language, version, classid, assignmentNumber, groupNumber, submissionNumber]; } export async function invalidateAllSubmissionKeys( queryClient: QueryClient, hruid?: string, language?: Language, version?: number, classid?: string, assignmentNumber?: number, groupNumber?: number, submissionNumber?: number, ): Promise { const keys = ["submission"]; await Promise.all( keys.map(async (key) => { const queryKey = [ key, hruid, language, version, classid, assignmentNumber, groupNumber, submissionNumber, ].filter((arg) => arg !== undefined); return queryClient.invalidateQueries({ queryKey: queryKey }); }) ) await queryClient.invalidateQueries({ queryKey: ["submissions", hruid, language, version, classid, assignmentNumber, groupNumber].filter( (arg) => arg !== undefined, ), }); await queryClient.invalidateQueries({ queryKey: ["group-submissions", hruid, language, version, classid, assignmentNumber, groupNumber].filter( (arg) => arg !== undefined, ), }); await queryClient.invalidateQueries({ queryKey: ["assignment-submissions", hruid, language, version, classid, assignmentNumber].filter( (arg) => arg !== undefined, ), }); } function checkEnabled(properties: MaybeRefOrGetter[]): boolean { return properties.every((prop) => Boolean(toValue(prop))); } export function useSubmissionsQuery( hruid: MaybeRefOrGetter, language: MaybeRefOrGetter, version: MaybeRefOrGetter, classid: MaybeRefOrGetter, assignmentNumber: MaybeRefOrGetter, groupNumber: MaybeRefOrGetter, full: MaybeRefOrGetter = true, ): UseQueryReturnType { return useQuery({ queryKey: ["submissions", hruid, language, version, classid, assignmentNumber, groupNumber, full], queryFn: async () => { const hruidVal = toValue(hruid); const languageVal = toValue(language); const versionVal = toValue(version); const classIdVal = toValue(classid); const assignmentNumberVal = toValue(assignmentNumber); const groupNumberVal = toValue(groupNumber); const fullVal = toValue(full); const response = await new SubmissionController(hruidVal!).getAll( languageVal, versionVal!, classIdVal!, assignmentNumberVal!, groupNumberVal, fullVal, ); return response ? (response.submissions as SubmissionDTO[]) : undefined; }, enabled: () => checkEnabled([hruid, language, version, classid, assignmentNumber]), }); } export function useSubmissionQuery( hruid: MaybeRefOrGetter, language: MaybeRefOrGetter, version: MaybeRefOrGetter, classid: MaybeRefOrGetter, assignmentNumber: MaybeRefOrGetter, groupNumber: MaybeRefOrGetter, submissionNumber: MaybeRefOrGetter, ): UseQueryReturnType { const hruidVal = toValue(hruid); const languageVal = toValue(language); const versionVal = toValue(version); const classIdVal = toValue(classid); const assignmentNumberVal = toValue(assignmentNumber); const groupNumberVal = toValue(groupNumber); const submissionNumberVal = toValue(submissionNumber); return useQuery({ queryKey: computed(() => submissionQueryKey( hruidVal!, languageVal, versionVal!, classIdVal!, assignmentNumberVal!, groupNumberVal!, submissionNumberVal!, ), ), queryFn: async () => new SubmissionController(hruidVal!).getByNumber( languageVal, versionVal!, classIdVal!, assignmentNumberVal!, groupNumberVal!, submissionNumberVal!, ), enabled: () => Boolean(hruidVal) && Boolean(languageVal) && Boolean(versionVal) && Boolean(classIdVal) && Boolean(assignmentNumberVal) && Boolean(submissionNumber), }); } export function useCreateSubmissionMutation(): UseMutationReturnType< SubmissionResponse, Error, { data: SubmissionDTO }, unknown > { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ data }) => new SubmissionController(data.learningObjectIdentifier.hruid).createSubmission(data), onSuccess: async (response) => { if (!response.submission.group) { await invalidateAllSubmissionKeys(queryClient); } else { const cls = response.submission.group.class; const assignment = response.submission.group.assignment; const cid = typeof cls === "string" ? cls : cls.id; const an = typeof assignment === "number" ? assignment : assignment.id; const gn = response.submission.group.groupNumber; const { hruid, language, version } = response.submission.learningObjectIdentifier; await invalidateAllSubmissionKeys(queryClient, hruid, language, version, cid, an, gn); await queryClient.invalidateQueries({ queryKey: [LEARNING_PATH_KEY, "get"] }); await queryClient.invalidateQueries({ queryKey: [LEARNING_OBJECT_KEY, "metadata", hruid, language, version], }); } }, }); } export function useDeleteSubmissionMutation(): UseMutationReturnType< SubmissionResponse, Error, { cid: string; an: number; gn: number; sn: number }, unknown > { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ cid, sn }) => new SubmissionController(cid).deleteSubmission(sn), onSuccess: async (response) => { if (!response.submission.group) { await invalidateAllSubmissionKeys(queryClient); } else { const cls = response.submission.group.class; const assignment = response.submission.group.assignment; const cid = typeof cls === "string" ? cls : cls.id; const an = typeof assignment === "number" ? assignment : assignment.id; const gn = response.submission.group.groupNumber; const { hruid, language, version } = response.submission.learningObjectIdentifier; await invalidateAllSubmissionKeys(queryClient, hruid, language, version, cid, an, gn); } }, }); }