import { useMutation, useQuery, useQueryClient, type UseQueryOptions, } from '@tanstack/react-query'; import { EDITION_ID, api } from './index'; import type { AssignmentCreate, AssignmentUpdate, AssignmentValidateResult, EditionUpdate, PlanningNotificationRequest, PositionCreate, PositionUpdate, ShiftCreate, ShiftUpdate, VolunteerCreate, VolunteerUpdate, } from './schema'; const edition = EDITION_ID; export const queryKeys = { edition: ['edition', edition] as const, volunteers: ['volunteers', edition] as const, positions: ['positions', edition] as const, shifts: (positionId?: string) => ['shifts', edition, positionId ?? null] as const, assignments: (params?: { volunteerId?: string; shiftId?: string }) => ['assignments', edition, params?.volunteerId ?? null, params?.shiftId ?? null] as const, matrix: ['matrix', edition] as const, validate: (volunteerId: string, shiftId: string) => ['validate', edition, volunteerId, shiftId] as const, }; // --------------------------------------------------------------------------- // // Lectures // // --------------------------------------------------------------------------- // export function useEdition() { return useQuery({ queryKey: queryKeys.edition, queryFn: () => api.editions.get(edition) }); } export function useVolunteers(options?: { enabled?: boolean }) { return useQuery({ queryKey: queryKeys.volunteers, queryFn: () => api.volunteers.list(edition), enabled: options?.enabled ?? true, }); } export function usePositions() { return useQuery({ queryKey: queryKeys.positions, queryFn: () => api.positions.list(edition) }); } /** Fiche d'un bénévole (un bénévole connecté peut lire la sienne). */ export function useVolunteer(id: string | null | undefined) { return useQuery({ queryKey: ['volunteer', edition, id ?? null], queryFn: () => api.volunteers.get(edition, id as string), enabled: Boolean(id), }); } export function useShifts(positionId?: string) { return useQuery({ queryKey: queryKeys.shifts(positionId), queryFn: () => api.shifts.list(edition, positionId ? { positionId } : undefined), }); } export function useAssignments( params?: { volunteerId?: string; shiftId?: string }, options?: { enabled?: boolean }, ) { return useQuery({ queryKey: queryKeys.assignments(params), queryFn: () => api.assignments.list(edition, params), enabled: options?.enabled ?? true, }); } export function useMatrix() { return useQuery({ queryKey: queryKeys.matrix, queryFn: () => api.matrix.get(edition) }); } export function useValidateAssignment( volunteerId: string, shiftId: string, options?: Partial>, ) { return useQuery({ queryKey: queryKeys.validate(volunteerId, shiftId), queryFn: () => api.assignments.validate(edition, { volunteer_id: volunteerId, shift_id: shiftId }), staleTime: 60_000, ...options, }); } // --------------------------------------------------------------------------- // // Écritures // // --------------------------------------------------------------------------- // function useInvalidate() { const client = useQueryClient(); return { volunteers: () => client.invalidateQueries({ queryKey: ['volunteers', edition] }), positions: () => client.invalidateQueries({ queryKey: ['positions', edition] }), shifts: () => client.invalidateQueries({ queryKey: ['shifts', edition] }), planning: () => { client.invalidateQueries({ queryKey: ['assignments', edition] }); client.invalidateQueries({ queryKey: ['matrix', edition] }); client.invalidateQueries({ queryKey: ['validate', edition] }); }, }; } export function useUpdateEdition() { const client = useQueryClient(); return useMutation({ mutationFn: (body: EditionUpdate) => api.editions.update(edition, body), onSuccess: () => client.invalidateQueries({ queryKey: ['edition', edition] }), }); } export function useCreateVolunteer() { const invalidate = useInvalidate(); return useMutation({ mutationFn: (body: VolunteerCreate) => api.volunteers.create(edition, body), onSuccess: invalidate.volunteers, }); } export function useUpdateVolunteer() { const invalidate = useInvalidate(); return useMutation({ mutationFn: ({ id, body }: { id: string; body: VolunteerUpdate }) => api.volunteers.update(edition, id, body), onSuccess: invalidate.volunteers, }); } export function useDeleteVolunteer() { const invalidate = useInvalidate(); return useMutation({ mutationFn: (id: string) => api.volunteers.remove(edition, id), onSuccess: () => { invalidate.volunteers(); invalidate.planning(); }, }); } export function useCreatePosition() { const invalidate = useInvalidate(); return useMutation({ mutationFn: (body: PositionCreate) => api.positions.create(edition, body), onSuccess: () => { invalidate.positions(); invalidate.planning(); }, }); } export function useUpdatePosition() { const invalidate = useInvalidate(); return useMutation({ mutationFn: ({ id, body }: { id: string; body: PositionUpdate }) => api.positions.update(edition, id, body), onSuccess: () => { invalidate.positions(); invalidate.planning(); }, }); } export function useDeletePosition() { const invalidate = useInvalidate(); return useMutation({ mutationFn: (id: string) => api.positions.remove(edition, id), onSuccess: () => { invalidate.positions(); invalidate.shifts(); invalidate.planning(); }, }); } export function useCreateShift() { const invalidate = useInvalidate(); return useMutation({ mutationFn: (body: ShiftCreate) => api.shifts.create(edition, body), onSuccess: () => { invalidate.shifts(); invalidate.planning(); }, }); } export function useUpdateShift() { const invalidate = useInvalidate(); return useMutation({ mutationFn: ({ id, body }: { id: string; body: ShiftUpdate }) => api.shifts.update(edition, id, body), onSuccess: () => { invalidate.shifts(); invalidate.planning(); }, }); } export function useDeleteShift() { const invalidate = useInvalidate(); return useMutation({ mutationFn: (id: string) => api.shifts.remove(edition, id), onSuccess: () => { invalidate.shifts(); invalidate.planning(); }, }); } export function useCreateAssignment() { const invalidate = useInvalidate(); return useMutation({ mutationFn: (body: AssignmentCreate) => api.assignments.create(edition, body), onSuccess: invalidate.planning, }); } export function useUpdateAssignment() { const invalidate = useInvalidate(); return useMutation({ mutationFn: ({ id, body }: { id: string; body: AssignmentUpdate }) => api.assignments.update(edition, id, body), onSuccess: invalidate.planning, }); } export function useDeleteAssignment() { const invalidate = useInvalidate(); return useMutation({ mutationFn: (id: string) => api.assignments.remove(edition, id), onSuccess: invalidate.planning, }); } export function useSendPlanningNotification() { return useMutation({ mutationFn: (body: PlanningNotificationRequest) => api.notifications.sendPlanning(edition, body), }); }