pmtool / src /utils /optimisticUpdates.ts
devarshia5's picture
Upload 487 files
d97b8f9 verified
Raw
History Blame Contribute Delete
5.2 kB
import { QueryClient } from '@tanstack/react-query';
import { AssetRequest } from '@/types/asset-request';
/**
* Utility functions for optimistic updates with rollback support
*/
interface OptimisticUpdateContext<T> {
previousData: T | undefined;
queryKey: unknown[];
}
/**
* Perform an optimistic update on a query
* @param queryClient - React Query client
* @param queryKey - Query key to update
* @param updater - Function to update the data
* @returns Context for rollback
*/
export const performOptimisticUpdate = <T>(
queryClient: QueryClient,
queryKey: unknown[],
updater: (oldData: T | undefined) => T
): OptimisticUpdateContext<T> => {
// Cancel any outgoing refetches
queryClient.cancelQueries({ queryKey });
// Snapshot the previous value
const previousData = queryClient.getQueryData<T>(queryKey);
// Optimistically update to the new value
queryClient.setQueryData<T>(queryKey, updater);
return { previousData, queryKey };
};
/**
* Rollback an optimistic update
* @param queryClient - React Query client
* @param context - Context from performOptimisticUpdate
*/
export const rollbackOptimisticUpdate = <T>(
queryClient: QueryClient,
context: OptimisticUpdateContext<T>
): void => {
queryClient.setQueryData(context.queryKey, context.previousData);
};
/**
* Optimistically update a request status
* @param queryClient - React Query client
* @param requestId - Request ID to update
* @param newStatus - New status
* @param additionalUpdates - Additional fields to update
* @returns Context for rollback
*/
export const optimisticallyUpdateRequestStatus = (
queryClient: QueryClient,
requestId: number,
newStatus: AssetRequest['status'],
additionalUpdates?: Partial<AssetRequest>
): OptimisticUpdateContext<AssetRequest[]>[] => {
const contexts: OptimisticUpdateContext<AssetRequest[]>[] = [];
// Update all relevant query keys
const queryKeys = [
['assetRequests', 'pending'],
['assetRequests', 'all'],
];
queryKeys.forEach((queryKey) => {
const context = performOptimisticUpdate<AssetRequest[]>(
queryClient,
queryKey,
(oldData) => {
if (!oldData) return [];
return oldData.map((request) =>
request.requestID === requestId
? {
...request,
status: newStatus,
...additionalUpdates,
}
: request
);
}
);
contexts.push(context);
});
return contexts;
};
/**
* Optimistically add a new request
* @param queryClient - React Query client
* @param newRequest - New request to add
* @param employeeId - Employee ID for employee-specific queries
* @returns Context for rollback
*/
export const optimisticallyAddRequest = (
queryClient: QueryClient,
newRequest: AssetRequest,
employeeId: number
): OptimisticUpdateContext<AssetRequest[]>[] => {
const contexts: OptimisticUpdateContext<AssetRequest[]>[] = [];
// Update employee-specific query
const employeeContext = performOptimisticUpdate<AssetRequest[]>(
queryClient,
['assetRequests', 'employee', employeeId],
(oldData) => {
if (!oldData) return [newRequest];
return [newRequest, ...oldData];
}
);
contexts.push(employeeContext);
// Update all requests query
const allContext = performOptimisticUpdate<AssetRequest[]>(
queryClient,
['assetRequests', 'all'],
(oldData) => {
if (!oldData) return [newRequest];
return [newRequest, ...oldData];
}
);
contexts.push(allContext);
// Update pending requests query
if (newRequest.status === 'pending') {
const pendingContext = performOptimisticUpdate<AssetRequest[]>(
queryClient,
['assetRequests', 'pending'],
(oldData) => {
if (!oldData) return [newRequest];
return [newRequest, ...oldData];
}
);
contexts.push(pendingContext);
}
return contexts;
};
/**
* Optimistically remove a request from a specific status list
* @param queryClient - React Query client
* @param requestId - Request ID to remove
* @param fromStatus - Status list to remove from
* @returns Context for rollback
*/
export const optimisticallyRemoveFromStatus = (
queryClient: QueryClient,
requestId: number,
fromStatus: 'pending' | 'approved'
): OptimisticUpdateContext<AssetRequest[]> => {
const queryKey = ['assetRequests', fromStatus];
return performOptimisticUpdate<AssetRequest[]>(
queryClient,
queryKey,
(oldData) => {
if (!oldData) return [];
return oldData.filter((request) => request.requestID !== requestId);
}
);
};
/**
* Rollback multiple optimistic updates
* @param queryClient - React Query client
* @param contexts - Array of contexts to rollback
*/
export const rollbackMultipleUpdates = <T>(
queryClient: QueryClient,
contexts: OptimisticUpdateContext<T>[]
): void => {
contexts.forEach((context) => {
rollbackOptimisticUpdate(queryClient, context);
});
};