import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query' import type { Ref } from 'vue' import { apiClient } from '@/lib/axios' import type { CreateSectionPayload, FestivalSection, UpdateSectionPayload } from '@/types/section' interface ApiResponse { success: boolean data: T message?: string } interface PaginatedResponse { data: T[] } export function useSectionCategories(orgId: Ref) { return useQuery({ queryKey: ['section-categories', orgId], queryFn: async () => { const { data } = await apiClient.get<{ data: string[] }>( `/organisations/${orgId.value}/section-categories`, ) return data.data }, enabled: () => !!orgId.value, }) } export function useSectionList(orgId: Ref, eventId: Ref) { return useQuery({ queryKey: ['sections', eventId], queryFn: async () => { const { data } = await apiClient.get>( `/organisations/${orgId.value}/events/${eventId.value}/sections`, ) return data.data }, enabled: () => !!orgId.value && !!eventId.value, }) } export interface CreateSectionResult { section: FestivalSection redirectedToParent: boolean parentEventName?: string } export function useCreateSection(orgId: Ref, eventId: Ref) { const queryClient = useQueryClient() return useMutation({ mutationFn: async (payload: CreateSectionPayload): Promise => { const { data } = await apiClient.post & { meta?: { redirected_to_parent?: boolean; parent_event_name?: string } }>( `/organisations/${orgId.value}/events/${eventId.value}/sections`, payload, ) return { section: data.data, redirectedToParent: data.meta?.redirected_to_parent ?? false, parentEventName: data.meta?.parent_event_name, } }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['sections', eventId.value] }) }, }) } export function useUpdateSection(orgId: Ref, eventId: Ref) { const queryClient = useQueryClient() return useMutation({ mutationFn: async ({ id, ...payload }: UpdateSectionPayload & { id: string }) => { const { data } = await apiClient.put>( `/organisations/${orgId.value}/events/${eventId.value}/sections/${id}`, payload, ) return data.data }, onSuccess: () => { // Invalidate all section lists — a cross_event section update affects multiple events queryClient.invalidateQueries({ queryKey: ['sections'] }) }, }) } export function useDeleteSection(orgId: Ref, eventId: Ref) { const queryClient = useQueryClient() return useMutation({ mutationFn: async (id: string) => { await apiClient.delete(`/organisations/${orgId.value}/events/${eventId.value}/sections/${id}`) }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['sections', eventId.value] }) }, }) } export function useReorderSections(orgId: Ref, eventId: Ref) { const queryClient = useQueryClient() let previousSections: FestivalSection[] | undefined return useMutation({ mutationFn: async (orderedIds: string[]) => { await apiClient.post(`/organisations/${orgId.value}/events/${eventId.value}/sections/reorder`, { sections: orderedIds, }) }, onMutate: async (orderedIds) => { await queryClient.cancelQueries({ queryKey: ['sections', eventId.value] }) previousSections = queryClient.getQueryData(['sections', eventId.value]) // Optimistically update query cache so watch doesn't snap back if (previousSections) { const byId = new Map(previousSections.map(s => [s.id, s])) const reordered = orderedIds .map(id => byId.get(id)) .filter((s): s is FestivalSection => !!s) queryClient.setQueryData(['sections', eventId.value], reordered) } }, onError: () => { if (previousSections) { queryClient.setQueryData(['sections', eventId.value], previousSections) } }, // No onSuccess invalidation — query cache and v-model are already in sync }) }