import { useMutation, useQueryClient } from "@tanstack/react-query"; import { apiClient, ApiErrorCode, apiErrorCode, isApiErrorCode, } from "@/shared/api"; import type { CreateBankCard, CreateBankOperation, CreateExpenseCategory, UpdateBankCard, UpdateBankOperation, UpdateExpenseCategory, } from "./queries"; async function mutationData( request: Promise<{ data?: T; error?: unknown }>, ) { const { data, error } = await request; // eslint-disable-next-line @typescript-eslint/only-throw-error -- Preserve generated ProblemDetails for apiErrorCode and field-error consumers. if (error) throw error; return data; } function useBankMutations() { const queryClient = useQueryClient(); const invalidate = () => queryClient.invalidateQueries({ predicate: ({ queryKey }) => { const [method, path] = queryKey; return ( method === "get" && typeof path === "string" && (path === "/api/v1/bank-cards" || path.startsWith("/api/v1/bank-cards/")) ); }, }); const options = { onError: (error: unknown) => { const errorCode = apiErrorCode(error); if ( [ ApiErrorCode.BankDependentRefunds, ApiErrorCode.BankIntentConflict, ApiErrorCode.BankRefundLimit, ApiErrorCode.BankVersionConflict, ApiErrorCode.BankWriteConflict, ].some(code => isApiErrorCode(errorCode, code)) ) return invalidate(); }, onSuccess: invalidate, retry: false, } as const; const cardCreation = useMutation({ ...options, mutationFn: (body: CreateBankCard) => mutationData(apiClient.POST("/api/v1/bank-cards", { body })), }); const updateCard = useMutation({ ...options, mutationFn: ({ body, id }: { body: UpdateBankCard; id: string }) => mutationData( apiClient.PATCH("/api/v1/bank-cards/{id}", { body, params: { path: { id } }, }), ), }); const operationCreation = useMutation({ ...options, mutationFn: (body: CreateBankOperation) => mutationData(apiClient.POST("/api/v1/bank-cards/operations", { body })), }); const updateOperation = useMutation({ ...options, mutationFn: ({ body, id }: { body: UpdateBankOperation; id: string }) => mutationData( apiClient.PATCH("/api/v1/bank-cards/operations/{id}", { body, params: { path: { id } }, }), ), }); const operationDeletion = useMutation({ ...options, mutationFn: ({ id, version }: { id: string; version: number }) => mutationData( apiClient.DELETE("/api/v1/bank-cards/operations/{id}", { params: { path: { id }, query: { version } }, }), ), }); const categoryCreation = useMutation({ ...options, mutationFn: (body: CreateExpenseCategory) => mutationData(apiClient.POST("/api/v1/bank-cards/categories", { body })), }); const updateCategory = useMutation({ ...options, mutationFn: ({ body, id }: { body: UpdateExpenseCategory; id: string }) => mutationData( apiClient.PATCH("/api/v1/bank-cards/categories/{id}", { body, params: { path: { id } }, }), ), }); return { createCard: cardCreation, createCategory: categoryCreation, createOperation: operationCreation, deleteOperation: operationDeletion, updateCard, updateCategory, updateOperation, }; } export { useBankMutations };