Add cards, operations, refunds, categories and monthly summaries with Mantine date controls. Derive banking types from runtime OpenAPI. Cover recovery and session isolation.
112 lines
2.8 KiB
TypeScript
112 lines
2.8 KiB
TypeScript
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
import { apiClient, apiErrorCode } from "@/shared/api";
|
|
import type {
|
|
CreateBankCard,
|
|
CreateBankOperation,
|
|
CreateExpenseCategory,
|
|
UpdateBankCard,
|
|
UpdateBankOperation,
|
|
UpdateExpenseCategory,
|
|
} from "./queries";
|
|
|
|
async function mutationData<T>(
|
|
request: Promise<{ data?: T; error?: unknown }>,
|
|
) {
|
|
const { data, error } = await request;
|
|
if (error) throw error;
|
|
return data;
|
|
}
|
|
|
|
function useBankMutations() {
|
|
const queryClient = useQueryClient();
|
|
const invalidate = () =>
|
|
queryClient.invalidateQueries({
|
|
predicate: ({ queryKey: [method, path] }) =>
|
|
method === "get" &&
|
|
typeof path === "string" &&
|
|
(path === "/api/v1/bank-cards" ||
|
|
path.startsWith("/api/v1/bank-cards/")),
|
|
});
|
|
const options = {
|
|
retry: false,
|
|
onSuccess: invalidate,
|
|
onError: (error: unknown) => {
|
|
if (
|
|
[
|
|
"BANK_VERSION_CONFLICT",
|
|
"BANK_WRITE_CONFLICT",
|
|
"BANK_INTENT_CONFLICT",
|
|
"BANK_REFUND_LIMIT",
|
|
"BANK_DEPENDENT_REFUNDS",
|
|
].includes(apiErrorCode(error) ?? "")
|
|
)
|
|
return invalidate();
|
|
},
|
|
} as const;
|
|
const createCard = useMutation({
|
|
...options,
|
|
mutationFn: (body: CreateBankCard) =>
|
|
mutationData(apiClient.POST("/api/v1/bank-cards", { body })),
|
|
});
|
|
const updateCard = useMutation({
|
|
...options,
|
|
mutationFn: ({ id, body }: { id: string; body: UpdateBankCard }) =>
|
|
mutationData(
|
|
apiClient.PATCH("/api/v1/bank-cards/{id}", {
|
|
params: { path: { id } },
|
|
body,
|
|
}),
|
|
),
|
|
});
|
|
const createOperation = useMutation({
|
|
...options,
|
|
mutationFn: (body: CreateBankOperation) =>
|
|
mutationData(apiClient.POST("/api/v1/bank-cards/operations", { body })),
|
|
});
|
|
const updateOperation = useMutation({
|
|
...options,
|
|
mutationFn: ({ id, body }: { id: string; body: UpdateBankOperation }) =>
|
|
mutationData(
|
|
apiClient.PATCH("/api/v1/bank-cards/operations/{id}", {
|
|
params: { path: { id } },
|
|
body,
|
|
}),
|
|
),
|
|
});
|
|
const deleteOperation = useMutation({
|
|
...options,
|
|
mutationFn: ({ id, version }: { id: string; version: number }) =>
|
|
mutationData(
|
|
apiClient.DELETE("/api/v1/bank-cards/operations/{id}", {
|
|
params: { path: { id }, query: { version } },
|
|
}),
|
|
),
|
|
});
|
|
const createCategory = useMutation({
|
|
...options,
|
|
mutationFn: (body: CreateExpenseCategory) =>
|
|
mutationData(apiClient.POST("/api/v1/bank-cards/categories", { body })),
|
|
});
|
|
const updateCategory = useMutation({
|
|
...options,
|
|
mutationFn: ({ id, body }: { id: string; body: UpdateExpenseCategory }) =>
|
|
mutationData(
|
|
apiClient.PATCH("/api/v1/bank-cards/categories/{id}", {
|
|
params: { path: { id } },
|
|
body,
|
|
}),
|
|
),
|
|
});
|
|
return {
|
|
createCard,
|
|
updateCard,
|
|
createOperation,
|
|
updateOperation,
|
|
deleteOperation,
|
|
createCategory,
|
|
updateCategory,
|
|
};
|
|
}
|
|
|
|
export { useBankMutations };
|