import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { systemDetailsApi } from '@/services/systemDetailsApi'; import { SystemDetails, SystemDetailsCreateRequest, SystemDetailsUpdateRequest } from '@/types/asset-management'; import { toast } from '@/lib/custom-toast'; import { assetQueryKeys } from './useAssets'; // Query keys for system details-related queries export const systemDetailsQueryKeys = { all: ['systemDetails'] as const, lists: () => [...systemDetailsQueryKeys.all, 'list'] as const, list: (filters?: any) => [...systemDetailsQueryKeys.lists(), { filters }] as const, details: () => [...systemDetailsQueryKeys.all, 'detail'] as const, detail: (id: number) => [...systemDetailsQueryKeys.details(), id] as const, byAsset: (assetId: number) => [...systemDetailsQueryKeys.all, 'byAsset', assetId] as const, }; /** * Hook for fetching all system details */ export const useSystemDetails = () => { return useQuery({ queryKey: systemDetailsQueryKeys.lists(), queryFn: () => systemDetailsApi.getAll(), staleTime: 5 * 60 * 1000, // 5 minutes gcTime: 10 * 60 * 1000, // 10 minutes }); }; /** * Hook for fetching a single system details record by ID */ export const useSystemDetail = (id: number) => { return useQuery({ queryKey: systemDetailsQueryKeys.detail(id), queryFn: () => systemDetailsApi.getById(id), staleTime: 5 * 60 * 1000, // 5 minutes gcTime: 10 * 60 * 1000, // 10 minutes enabled: !!id && id > 0, // Only run query if ID is valid }); }; /** * Hook for fetching system details by asset ID */ export const useSystemDetailsByAsset = (assetId: number) => { return useQuery({ queryKey: systemDetailsQueryKeys.byAsset(assetId), queryFn: () => systemDetailsApi.getByAssetId(assetId), staleTime: 5 * 60 * 1000, // 5 minutes gcTime: 10 * 60 * 1000, // 10 minutes enabled: !!assetId && assetId > 0, // Only run query if asset ID is valid }); }; /** * Hook for creating new system details */ export const useCreateSystemDetails = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (systemDetails: SystemDetailsCreateRequest) => systemDetailsApi.create(systemDetails), onSuccess: (newSystemDetails) => { // Invalidate and refetch system details lists queryClient.invalidateQueries({ queryKey: systemDetailsQueryKeys.lists() }); // Invalidate system details for the specific asset queryClient.invalidateQueries({ queryKey: systemDetailsQueryKeys.byAsset(newSystemDetails.assetID) }); // Optionally add the new system details to the cache queryClient.setQueryData( systemDetailsQueryKeys.detail(newSystemDetails.systemDetailsID), newSystemDetails ); // Invalidate the asset details to refresh related data queryClient.invalidateQueries({ queryKey: assetQueryKeys.detail(newSystemDetails.assetID) }); toast.success('System details created successfully'); }, onError: (error) => { console.error('Create system details error:', error); toast.error('Failed to create system details'); }, }); }; /** * Hook for updating existing system details */ export const useUpdateSystemDetails = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: ({ id, systemDetails }: { id: number; systemDetails: SystemDetailsUpdateRequest }) => systemDetailsApi.update(id, systemDetails), onMutate: async ({ id, systemDetails }) => { // Cancel any outgoing refetches await queryClient.cancelQueries({ queryKey: systemDetailsQueryKeys.detail(id) }); // Snapshot the previous value const previousSystemDetails = queryClient.getQueryData(systemDetailsQueryKeys.detail(id)); // Optimistically update to the new value queryClient.setQueryData(systemDetailsQueryKeys.detail(id), systemDetails); // Return a context object with the snapshotted value return { previousSystemDetails, id, assetId: systemDetails.assetID }; }, onError: (error, variables, context) => { // If the mutation fails, use the context returned from onMutate to roll back if (context?.previousSystemDetails) { queryClient.setQueryData( systemDetailsQueryKeys.detail(context.id), context.previousSystemDetails ); } console.error('Update system details error:', error); toast.error('Failed to update system details'); }, onSuccess: (updatedSystemDetails, { id }) => { // Update the system details in the cache queryClient.setQueryData(systemDetailsQueryKeys.detail(id), updatedSystemDetails); // Invalidate system details lists to ensure consistency queryClient.invalidateQueries({ queryKey: systemDetailsQueryKeys.lists() }); // Invalidate system details for the specific asset queryClient.invalidateQueries({ queryKey: systemDetailsQueryKeys.byAsset(updatedSystemDetails.assetID) }); // Invalidate the asset details to refresh related data queryClient.invalidateQueries({ queryKey: assetQueryKeys.detail(updatedSystemDetails.assetID) }); toast.success('System details updated successfully'); }, }); }; /** * Hook for deleting system details */ export const useDeleteSystemDetails = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (id: number) => systemDetailsApi.delete(id), onMutate: async (id) => { // Cancel any outgoing refetches await queryClient.cancelQueries({ queryKey: systemDetailsQueryKeys.detail(id) }); await queryClient.cancelQueries({ queryKey: systemDetailsQueryKeys.lists() }); // Snapshot the previous values const previousSystemDetails = queryClient.getQueryData(systemDetailsQueryKeys.detail(id)); const previousSystemDetailsList = queryClient.getQueryData(systemDetailsQueryKeys.lists()); // Get the asset ID from the system details to invalidate related queries const systemDetails = previousSystemDetails as SystemDetails; const assetId = systemDetails?.assetID; // Optimistically remove the system details from the list if (previousSystemDetailsList) { queryClient.setQueryData( systemDetailsQueryKeys.lists(), (previousSystemDetailsList as SystemDetails[]).filter( details => details.systemDetailsID !== id ) ); } // Optimistically remove from asset-specific list if we have the asset ID if (assetId) { const previousAssetSystemDetails = queryClient.getQueryData( systemDetailsQueryKeys.byAsset(assetId) ); if (previousAssetSystemDetails) { queryClient.setQueryData( systemDetailsQueryKeys.byAsset(assetId), (previousAssetSystemDetails as SystemDetails[]).filter( details => details.systemDetailsID !== id ) ); } } // Return a context object with the snapshotted values return { previousSystemDetails, previousSystemDetailsList, id, assetId }; }, onError: (error, id, context) => { // If the mutation fails, use the context to roll back if (context?.previousSystemDetailsList) { queryClient.setQueryData(systemDetailsQueryKeys.lists(), context.previousSystemDetailsList); } if (context?.previousSystemDetails) { queryClient.setQueryData(systemDetailsQueryKeys.detail(id), context.previousSystemDetails); } if (context?.assetId) { // Invalidate asset-specific system details to refresh from server queryClient.invalidateQueries({ queryKey: systemDetailsQueryKeys.byAsset(context.assetId) }); } console.error('Delete system details error:', error); toast.error('Failed to delete system details'); }, onSuccess: (_, id, context) => { // Remove the system details from the cache queryClient.removeQueries({ queryKey: systemDetailsQueryKeys.detail(id) }); // Invalidate system details lists to ensure consistency queryClient.invalidateQueries({ queryKey: systemDetailsQueryKeys.lists() }); // Invalidate system details for the specific asset if we have the asset ID if (context?.assetId) { queryClient.invalidateQueries({ queryKey: systemDetailsQueryKeys.byAsset(context.assetId) }); // Invalidate the asset details to refresh related data queryClient.invalidateQueries({ queryKey: assetQueryKeys.detail(context.assetId) }); } toast.success('System details deleted successfully'); }, }); };