pmtool / src /hooks /asset-management /useAssignments.ts
devarshia5's picture
Upload 487 files
d97b8f9 verified
Raw
History Blame Contribute Delete
14.3 kB
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { assetAssignmentApi } from '@/services/assetAssignmentApi';
import { AssetAssignment, AssetAssignmentCreateRequest, AssetAssignmentUpdateRequest } from '@/types/asset-management';
import { toast } from '@/lib/custom-toast';
import { assetQueryKeys } from './useAssets';
// Query keys for asset assignment-related queries
export const assignmentQueryKeys = {
all: ['assignments'] as const,
lists: () => [...assignmentQueryKeys.all, 'list'] as const,
list: (filters?: any) => [...assignmentQueryKeys.lists(), { filters }] as const,
details: () => [...assignmentQueryKeys.all, 'detail'] as const,
detail: (id: number) => [...assignmentQueryKeys.details(), id] as const,
byAsset: (assetId: number) => [...assignmentQueryKeys.all, 'byAsset', assetId] as const,
byEmployee: (employeeId: number) => [...assignmentQueryKeys.all, 'byEmployee', employeeId] as const,
history: (assetId: number) => [...assignmentQueryKeys.all, 'history', assetId] as const,
active: () => [...assignmentQueryKeys.all, 'active'] as const,
};
/**
* Hook for fetching all asset assignments
*/
export const useAssignments = () => {
return useQuery({
queryKey: assignmentQueryKeys.lists(),
queryFn: () => assetAssignmentApi.getAll(),
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 10 * 60 * 1000, // 10 minutes
});
};
/**
* Hook for fetching a single asset assignment by ID
*/
export const useAssignment = (id: number) => {
return useQuery({
queryKey: assignmentQueryKeys.detail(id),
queryFn: () => assetAssignmentApi.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 asset assignments by asset ID
*/
export const useAssignmentsByAsset = (assetId: number) => {
return useQuery({
queryKey: assignmentQueryKeys.byAsset(assetId),
queryFn: () => assetAssignmentApi.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 fetching asset assignments by employee ID
*/
export const useAssignmentsByEmployee = (employeeId: number) => {
return useQuery({
queryKey: assignmentQueryKeys.byEmployee(employeeId),
queryFn: () => assetAssignmentApi.getByEmployeeId(employeeId),
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 10 * 60 * 1000, // 10 minutes
enabled: !!employeeId && employeeId > 0, // Only run query if employee ID is valid
});
};
/**
* Hook for creating a new asset assignment
*/
export const useCreateAssignment = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (assignment: AssetAssignmentCreateRequest) => {
// Ensure dates are properly formatted before sending to API
const formattedAssignment = {
...assignment,
assignedDate: assignment.assignedDate || new Date().toISOString(),
returnedDate: assignment.returnedDate || null,
};
return assetAssignmentApi.create(formattedAssignment);
},
onSuccess: (newAssignment) => {
// Invalidate and refetch assignment lists
queryClient.invalidateQueries({ queryKey: assignmentQueryKeys.lists() });
// Invalidate assignments for the specific asset
queryClient.invalidateQueries({
queryKey: assignmentQueryKeys.byAsset(newAssignment.assetID)
});
// Invalidate assignments for the specific employee
queryClient.invalidateQueries({
queryKey: assignmentQueryKeys.byEmployee(newAssignment.employeeID)
});
// Optionally add the new assignment to the cache
queryClient.setQueryData(
assignmentQueryKeys.detail(newAssignment.assignmentID),
newAssignment
);
// Invalidate the asset details to refresh related data
queryClient.invalidateQueries({
queryKey: assetQueryKeys.detail(newAssignment.assetID)
});
toast.success('Asset assignment created successfully');
},
onError: (error) => {
console.error('Create assignment error:', error);
toast.error('Failed to create asset assignment');
},
});
};
/**
* Hook for updating an existing asset assignment
*/
export const useUpdateAssignment = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, assignment }: { id: number; assignment: AssetAssignmentUpdateRequest }) => {
// Ensure dates are properly formatted before sending to API
const formattedAssignment = {
...assignment,
assignedDate: assignment.assignedDate || new Date().toISOString(),
returnedDate: assignment.returnedDate || null,
};
return assetAssignmentApi.update(id, formattedAssignment);
},
onMutate: async ({ id, assignment }) => {
// Cancel any outgoing refetches
await queryClient.cancelQueries({ queryKey: assignmentQueryKeys.detail(id) });
// Snapshot the previous value
const previousAssignment = queryClient.getQueryData(assignmentQueryKeys.detail(id));
// Optimistically update to the new value
queryClient.setQueryData(assignmentQueryKeys.detail(id), assignment);
// Return a context object with the snapshotted value
return {
previousAssignment,
id,
assetId: assignment.assetID,
employeeId: assignment.employeeID
};
},
onError: (error, variables, context) => {
// If the mutation fails, use the context returned from onMutate to roll back
if (context?.previousAssignment) {
queryClient.setQueryData(
assignmentQueryKeys.detail(context.id),
context.previousAssignment
);
}
console.error('Update assignment error:', error);
toast.error('Failed to update asset assignment');
},
onSuccess: (updatedAssignment, { id }) => {
// Update the assignment in the cache
queryClient.setQueryData(assignmentQueryKeys.detail(id), updatedAssignment);
// Invalidate assignment lists to ensure consistency
queryClient.invalidateQueries({ queryKey: assignmentQueryKeys.lists() });
// Invalidate assignments for the specific asset
queryClient.invalidateQueries({
queryKey: assignmentQueryKeys.byAsset(updatedAssignment.assetID)
});
// Invalidate assignments for the specific employee
queryClient.invalidateQueries({
queryKey: assignmentQueryKeys.byEmployee(updatedAssignment.employeeID)
});
// Invalidate the asset details to refresh related data
queryClient.invalidateQueries({
queryKey: assetQueryKeys.detail(updatedAssignment.assetID)
});
toast.success('Asset assignment updated successfully');
},
});
};
/**
* Hook for deleting an asset assignment
*/
export const useDeleteAssignment = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: number) => assetAssignmentApi.delete(id),
onMutate: async (id) => {
// Cancel any outgoing refetches
await queryClient.cancelQueries({ queryKey: assignmentQueryKeys.detail(id) });
await queryClient.cancelQueries({ queryKey: assignmentQueryKeys.lists() });
// Snapshot the previous values
const previousAssignment = queryClient.getQueryData(assignmentQueryKeys.detail(id));
const previousAssignmentsList = queryClient.getQueryData(assignmentQueryKeys.lists());
// Get the asset and employee IDs from the assignment to invalidate related queries
const assignment = previousAssignment as AssetAssignment;
const assetId = assignment?.assetID;
const employeeId = assignment?.employeeID;
// Optimistically remove the assignment from the list
if (previousAssignmentsList) {
queryClient.setQueryData(
assignmentQueryKeys.lists(),
(previousAssignmentsList as AssetAssignment[]).filter(
assignment => assignment.assignmentID !== id
)
);
}
// Optimistically remove from asset-specific list if we have the asset ID
if (assetId) {
const previousAssetAssignments = queryClient.getQueryData(
assignmentQueryKeys.byAsset(assetId)
);
if (previousAssetAssignments) {
queryClient.setQueryData(
assignmentQueryKeys.byAsset(assetId),
(previousAssetAssignments as AssetAssignment[]).filter(
assignment => assignment.assignmentID !== id
)
);
}
}
// Optimistically remove from employee-specific list if we have the employee ID
if (employeeId) {
const previousEmployeeAssignments = queryClient.getQueryData(
assignmentQueryKeys.byEmployee(employeeId)
);
if (previousEmployeeAssignments) {
queryClient.setQueryData(
assignmentQueryKeys.byEmployee(employeeId),
(previousEmployeeAssignments as AssetAssignment[]).filter(
assignment => assignment.assignmentID !== id
)
);
}
}
// Return a context object with the snapshotted values
return {
previousAssignment,
previousAssignmentsList,
id,
assetId,
employeeId
};
},
onError: (error, id, context) => {
// If the mutation fails, use the context to roll back
if (context?.previousAssignmentsList) {
queryClient.setQueryData(assignmentQueryKeys.lists(), context.previousAssignmentsList);
}
if (context?.previousAssignment) {
queryClient.setQueryData(assignmentQueryKeys.detail(id), context.previousAssignment);
}
if (context?.assetId) {
// Invalidate asset-specific assignments to refresh from server
queryClient.invalidateQueries({
queryKey: assignmentQueryKeys.byAsset(context.assetId)
});
}
if (context?.employeeId) {
// Invalidate employee-specific assignments to refresh from server
queryClient.invalidateQueries({
queryKey: assignmentQueryKeys.byEmployee(context.employeeId)
});
}
console.error('Delete assignment error:', error);
toast.error('Failed to delete asset assignment');
},
onSuccess: (_, id, context) => {
// Remove the assignment from the cache
queryClient.removeQueries({ queryKey: assignmentQueryKeys.detail(id) });
// Invalidate assignment lists to ensure consistency
queryClient.invalidateQueries({ queryKey: assignmentQueryKeys.lists() });
// Invalidate assignments for the specific asset if we have the asset ID
if (context?.assetId) {
queryClient.invalidateQueries({
queryKey: assignmentQueryKeys.byAsset(context.assetId)
});
// Invalidate the asset details to refresh related data
queryClient.invalidateQueries({
queryKey: assetQueryKeys.detail(context.assetId)
});
}
// Invalidate assignments for the specific employee if we have the employee ID
if (context?.employeeId) {
queryClient.invalidateQueries({
queryKey: assignmentQueryKeys.byEmployee(context.employeeId)
});
}
toast.success('Asset assignment deleted successfully');
},
});
};
/**
* Hook for fetching assignment history by asset ID
*/
export const useAssignmentHistory = (assetId: number) => {
return useQuery({
queryKey: assignmentQueryKeys.history(assetId),
queryFn: () => assetAssignmentApi.getAssignmentHistory(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 fetching all active assignments
*/
export const useActiveAssignments = () => {
return useQuery({
queryKey: assignmentQueryKeys.active(),
queryFn: () => assetAssignmentApi.getActiveAssignments(),
staleTime: 2 * 60 * 1000, // 2 minutes (shorter for active data)
gcTime: 5 * 60 * 1000, // 5 minutes
});
};
/**
* Hook for bulk returning multiple assignments
*/
export const useBulkReturnAssignments = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (request: {
assignmentIds: number[];
returnedDate: string;
returnReason?: string;
remarks?: string;
performedBy?: {
employeeID: number;
name: string;
};
}) => assetAssignmentApi.bulkReturn(request),
onSuccess: (result) => {
// Invalidate all assignment-related queries to refresh data
queryClient.invalidateQueries({ queryKey: assignmentQueryKeys.all });
// Invalidate active assignments specifically
queryClient.invalidateQueries({ queryKey: assignmentQueryKeys.active() });
// Invalidate asset queries to refresh asset status
queryClient.invalidateQueries({ queryKey: assetQueryKeys.all });
// Show success/failure summary
const { successful, failed } = result.summary;
if (successful > 0 && failed === 0) {
toast.success(`Successfully returned ${successful} assignment${successful > 1 ? 's' : ''}`);
} else if (successful > 0 && failed > 0) {
toast.warning(`Returned ${successful} assignment${successful > 1 ? 's' : ''}, ${failed} failed`);
} else {
toast.error(`Failed to return assignments: ${result.message}`);
}
},
onError: (error) => {
console.error('Bulk return assignments error:', error);
toast.error('Failed to return assignments');
},
});
};