import { useDataSource } from "@erp/core/hooks"; import { UniqueID, ValidationErrorCollection } from "@repo/rdx-ddd"; import { DefaultError, useMutation, useQueryClient } from "@tanstack/react-query"; import { ZodError } from "zod/v4"; import { CreateCustomerRequestSchema } from "../../common"; import { Customer, CustomerFormData } from "../schemas"; import { CUSTOMERS_LIST_KEY, invalidateCustomerListCache } from "./use-customer-list-query"; import { setCustomerDetailCache } from "./use-customer-query"; export const CUSTOMER_CREATE_KEY = ["customers", "create"] as const; type CreateCustomerPayload = { data: CustomerFormData; }; // Helpers de validación a errores de dominio export function toValidationErrors(error: ZodError) { return error.issues.map((err) => ({ field: err.path.join("."), message: err.message, })); } export function useCreateCustomer() { const queryClient = useQueryClient(); const dataSource = useDataSource(); const schema = CreateCustomerRequestSchema; return useMutation({ mutationKey: CUSTOMER_CREATE_KEY, mutationFn: async ({ data }, context) => { const id = UniqueID.generateNewID().toString(); const payload = { ...data, id }; const result = schema.safeParse(payload); if (!result.success) { throw new ValidationErrorCollection("Validation failed", toValidationErrors(result.error)); } const created = await dataSource.createOne("customers", payload); return created as Customer; }, onSuccess: (created: Customer, variables) => { const { id: customerId } = created; // Invalida el listado para refrescar desde servidor invalidateCustomerListCache(queryClient); // Sincroniza detalle setCustomerDetailCache(queryClient, customerId, created); }, onSettled: () => { // Refresca todos los listados invalidateCustomerListCache(queryClient); }, onMutate: async ({ data }, context) => { // Cancelar queries del listado para evitar overwrite await queryClient.cancelQueries({ queryKey: [CUSTOMERS_LIST_KEY] }); const optimisticId = UniqueID.generateNewID().toString(); const optimisticCustomer: Customer = { ...data, id: optimisticId } as Customer; // Snapshot previo const previous = queryClient.getQueryData([CUSTOMERS_LIST_KEY]); // Optimista: prepend queryClient.setQueryData([CUSTOMERS_LIST_KEY], (old) => [ optimisticCustomer, ...(old ?? []), ]); return { previous, optimisticId }; }, }); }