/** * Service Management Hooks */ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import apiClient from '../api/client'; import { Service } from '../types'; /** * Hook to fetch all services for current business */ export const useServices = () => { return useQuery({ queryKey: ['services'], queryFn: async () => { const { data } = await apiClient.get('/services/'); // Transform backend format to frontend format return data.map((s: any) => ({ id: String(s.id), name: s.name, durationMinutes: s.duration || s.duration_minutes, price: parseFloat(s.price), description: s.description || '', displayOrder: s.display_order ?? 0, photos: s.photos || [], // Pricing fields variable_pricing: s.variable_pricing ?? false, deposit_amount: s.deposit_amount ? parseFloat(s.deposit_amount) : null, deposit_percent: s.deposit_percent ? parseFloat(s.deposit_percent) : null, requires_deposit: s.requires_deposit ?? false, requires_saved_payment_method: s.requires_saved_payment_method ?? false, deposit_display: s.deposit_display || null, })); }, retry: false, // Don't retry on 404 - endpoint may not exist yet }); }; /** * Hook to get a single service */ export const useService = (id: string) => { return useQuery({ queryKey: ['services', id], queryFn: async () => { const { data } = await apiClient.get(`/services/${id}/`); return { id: String(data.id), name: data.name, durationMinutes: data.duration || data.duration_minutes, price: parseFloat(data.price), description: data.description || '', displayOrder: data.display_order ?? 0, photos: data.photos || [], }; }, enabled: !!id, retry: false, }); }; // Input type for creating/updating services (not all Service fields required) interface ServiceInput { name: string; durationMinutes: number; price: number; description?: string; photos?: string[]; variable_pricing?: boolean; deposit_amount?: number | null; deposit_percent?: number | null; } /** * Hook to create a service */ export const useCreateService = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (serviceData: ServiceInput) => { const backendData: Record = { name: serviceData.name, duration: serviceData.durationMinutes, price: serviceData.price.toString(), description: serviceData.description || '', photos: serviceData.photos || [], }; // Add pricing fields if (serviceData.variable_pricing !== undefined) { backendData.variable_pricing = serviceData.variable_pricing; } if (serviceData.deposit_amount !== undefined) { backendData.deposit_amount = serviceData.deposit_amount; } if (serviceData.deposit_percent !== undefined) { backendData.deposit_percent = serviceData.deposit_percent; } const { data } = await apiClient.post('/services/', backendData); return data; }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['services'] }); }, }); }; /** * Hook to update a service */ export const useUpdateService = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ id, updates }: { id: string; updates: Partial }) => { const backendData: Record = {}; if (updates.name) backendData.name = updates.name; if (updates.durationMinutes) backendData.duration = updates.durationMinutes; if (updates.price !== undefined) backendData.price = updates.price.toString(); if (updates.description !== undefined) backendData.description = updates.description; if (updates.photos !== undefined) backendData.photos = updates.photos; // Pricing fields if (updates.variable_pricing !== undefined) backendData.variable_pricing = updates.variable_pricing; if (updates.deposit_amount !== undefined) backendData.deposit_amount = updates.deposit_amount; if (updates.deposit_percent !== undefined) backendData.deposit_percent = updates.deposit_percent; const { data } = await apiClient.patch(`/services/${id}/`, backendData); return data; }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['services'] }); }, }); }; /** * Hook to delete a service */ export const useDeleteService = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (id: string) => { await apiClient.delete(`/services/${id}/`); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['services'] }); }, }); }; /** * Hook to reorder services (drag and drop) */ export const useReorderServices = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (orderedIds: string[]) => { // Convert string IDs to numbers for the backend const order = orderedIds.map(id => parseInt(id, 10)); const { data } = await apiClient.post('/services/reorder/', { order }); return data; }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['services'] }); }, }); };