import type { QueryClient, QueryKey } from "@tanstack/react-query"; import { CustomerToListRowPatchAdapter } from "../adapters"; import type { Customer, CustomerList, CustomerListRow } from "../entities"; import { CUSTOMER_QUERY_KEY, LIST_CUSTOMERS_QUERY_KEY_PREFIX } from "./keys"; /** * Estrategias de caché para las consultas relacionadas con clientes. * Incluye funciones para cancelar, invalidar, actualizar y eliminar cachés de clientes, * así como para manejar actualizaciones optimistas al eliminar clientes. */ export interface CustomerListCacheSnapshot { key: QueryKey; page?: CustomerList; } export interface DeleteCustomerCacheContext { snapshots: CustomerListCacheSnapshot[]; } export function cancelCustomerListQueries(queryClient: QueryClient) { return queryClient.cancelQueries({ queryKey: LIST_CUSTOMERS_QUERY_KEY_PREFIX, }); } export function invalidateCustomerListQueries(queryClient: QueryClient) { return queryClient.invalidateQueries({ queryKey: LIST_CUSTOMERS_QUERY_KEY_PREFIX, }); } export function invalidateCustomerDetailQuery(queryClient: QueryClient, customerId: string) { return queryClient.invalidateQueries({ queryKey: CUSTOMER_QUERY_KEY(customerId), exact: true, }); } export function setCustomerDetailCache( queryClient: QueryClient, customerId: string, customer: Customer ) { queryClient.setQueryData(CUSTOMER_QUERY_KEY(customerId), customer); } export function removeCustomerDetailCache(queryClient: QueryClient, customerId: string) { queryClient.removeQueries({ queryKey: CUSTOMER_QUERY_KEY(customerId), exact: true, }); } export function getAllCustomerListQueryKeys(queryClient: QueryClient): QueryKey[] { const entries = queryClient.getQueriesData({ queryKey: LIST_CUSTOMERS_QUERY_KEY_PREFIX, }); return entries.map(([key]) => key); } export function upsertCustomerInListCaches( queryClient: QueryClient, customer: Pick & Partial ) { const keys = getAllCustomerListQueryKeys(queryClient); for (const key of keys) { const page = queryClient.getQueryData(key); if (!page) continue; const index = page.items.findIndex((row) => row.id === customer.id); if (index === -1) continue; const nextItems = page.items.slice(); nextItems[index] = { ...page.items[index], ...customer, }; queryClient.setQueryData(key, { ...page, items: nextItems, }); } } export function removeCustomerFromListCaches( queryClient: QueryClient, customerId: string ): CustomerListCacheSnapshot[] { const snapshots = getAllCustomerListQueryKeys(queryClient).map((key) => ({ key, page: queryClient.getQueryData(key), })); for (const { key, page } of snapshots) { if (!page) continue; queryClient.setQueryData(key, { ...page, items: page.items.filter((row) => row.id !== customerId), totalItems: Math.max(0, page.totalItems - 1), }); } return snapshots; } export function restoreCustomerListCaches( queryClient: QueryClient, snapshots: CustomerListCacheSnapshot[] ) { for (const snapshot of snapshots) { queryClient.setQueryData(snapshot.key, snapshot.page); } } export function syncCreatedCustomerCaches(queryClient: QueryClient, customer: Customer) { setCustomerDetailCache(queryClient, customer.id, customer); return invalidateCustomerListQueries(queryClient); } export function syncUpdatedCustomerCaches(queryClient: QueryClient, customer: Customer) { setCustomerDetailCache(queryClient, customer.id, customer); upsertCustomerInListCaches(queryClient, CustomerToListRowPatchAdapter.fromCustomer(customer)); return invalidateCustomerListQueries(queryClient); } export async function prepareDeleteCustomerOptimisticUpdate( queryClient: QueryClient, customerId: string ): Promise { await cancelCustomerListQueries(queryClient); const snapshots = removeCustomerFromListCaches(queryClient, customerId); return { snapshots }; } export function rollbackDeleteCustomerOptimisticUpdate( queryClient: QueryClient, context?: DeleteCustomerCacheContext ) { if (!context) return; restoreCustomerListCaches(queryClient, context.snapshots); } export function finalizeDeletedCustomerCaches(queryClient: QueryClient, customerId: string) { removeCustomerDetailCache(queryClient, customerId); return invalidateCustomerListQueries(queryClient); }