mercury-web/src/api/hooks/mutations.ts

205 lines
6.7 KiB
TypeScript

import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiSend } from "../client";
import { keys } from "../keys";
import {
BudgetSchema,
SettingsSchema,
LendingSchema,
RevalueResultSchema,
SubscriptionSchema,
} from "../schemas";
// --- transactions ---
export const useCategorize = () => {
const qc = useQueryClient();
return useMutation({
mutationFn: (b: { matchKey: string; category: string; kind?: "income" | "expense" }) =>
apiSend("POST", "/transactions/categorize", b),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ["transactions"] });
qc.invalidateQueries({ queryKey: ["analyze"] });
qc.invalidateQueries({ queryKey: keys.budget });
},
});
};
export const useRenameTxn = () => {
const qc = useQueryClient();
return useMutation({
mutationFn: (b: { matchKey: string; name: string }) => apiSend("POST", "/transactions/rename", b),
onSuccess: () => qc.invalidateQueries({ queryKey: ["transactions"] }),
});
};
export const useSetNote = () => {
const qc = useQueryClient();
return useMutation({
mutationFn: (b: { id: number; note: string }) => apiSend("PUT", `/transactions/${b.id}/note`, { note: b.note }),
onSuccess: () => qc.invalidateQueries({ queryKey: ["transactions"] }),
});
};
// --- budget ---
export const usePutBudget = () => {
const qc = useQueryClient();
return useMutation({
mutationFn: (b: {
dayLimit: string;
weekLimit: string;
monthLimit: string;
plannedIncomeManual: string;
categories: { name: string; day: string; week: string; month: string }[];
}) => apiSend("PUT", "/budget", b, BudgetSchema),
onSuccess: () => qc.invalidateQueries({ queryKey: keys.budget }),
});
};
// --- settings ---
export const useSaveSettings = () => {
const qc = useQueryClient();
return useMutation({
mutationFn: (b: {
holderName: string;
employer: string;
salaryKeywords: string[];
payDays: number[];
ownAccounts: string[];
peerAccounts: string[];
hideAmounts?: boolean;
}) => apiSend("PUT", "/settings", b, SettingsSchema),
onSuccess: () => qc.invalidateQueries({ queryKey: keys.settings }),
});
};
// --- categories ---
export const useCategoryMutations = () => {
const qc = useQueryClient();
const invalidate = () => {
qc.invalidateQueries({ queryKey: keys.categories });
qc.invalidateQueries({ queryKey: keys.budget });
qc.invalidateQueries({ queryKey: ["transactions"] });
};
const add = useMutation({
mutationFn: (b: { name: string; kind?: "income" | "expense"; parent?: string; icon?: string }) =>
apiSend("POST", "/categories", b),
onSuccess: invalidate,
});
const update = useMutation({
mutationFn: (b: { oldName: string; newName?: string; parent?: string | null; icon?: string | null }) =>
apiSend("PUT", "/categories", b),
onSuccess: invalidate,
});
const remove = useMutation({
mutationFn: (name: string) => apiSend("DELETE", `/categories?name=${encodeURIComponent(name)}`),
onSuccess: invalidate,
});
return { add, update, delete: remove };
};
// --- manual assets ---
export const useManualAssetMutations = () => {
const qc = useQueryClient();
const invalidate = () => {
qc.invalidateQueries({ queryKey: keys.manualAssets });
qc.invalidateQueries({ queryKey: keys.networth });
};
const add = useMutation({
mutationFn: (b: {
name: string;
category?: string;
value: string;
acquiredValue?: string;
currency?: string;
condition?: string;
isLiability?: boolean;
}) => apiSend("POST", "/manual-assets", b),
onSuccess: invalidate,
});
const remove = useMutation({
mutationFn: (name: string) => apiSend("DELETE", `/manual-assets/${encodeURIComponent(name)}`),
onSuccess: invalidate,
});
const revalue = useMutation({
mutationFn: (name: string) => apiSend("POST", `/manual-assets/${encodeURIComponent(name)}/revalue`, undefined, RevalueResultSchema),
onSuccess: invalidate,
});
return { add, delete: remove, revalue };
};
// --- lending ---
export const useLendingMutations = () => {
const qc = useQueryClient();
const invalidate = () => qc.invalidateQueries({ queryKey: keys.lending });
const create = useMutation({
mutationFn: (b: { person: string; amount: string; lentOn: string; dueOn?: string; note?: string; txnId?: number }) =>
apiSend("POST", "/lending", b, LendingSchema),
onSuccess: invalidate,
});
const remove = useMutation({
mutationFn: (id: number) => apiSend("DELETE", `/lending/${id}`),
onSuccess: invalidate,
});
const addRepayment = useMutation({
mutationFn: (b: { id: number; amount: string; paidOn: string; note?: string; txnId?: number }) =>
apiSend("POST", `/lending/${b.id}/repayments`, { amount: b.amount, paidOn: b.paidOn, note: b.note, txnId: b.txnId }, LendingSchema),
onSuccess: invalidate,
});
const deleteRepayment = useMutation({
mutationFn: (b: { id: number; repaymentId: number }) => apiSend("DELETE", `/lending/${b.id}/repayments/${b.repaymentId}`),
onSuccess: invalidate,
});
return { create, delete: remove, addRepayment, deleteRepayment };
};
// --- subscriptions ---
export const useSubscriptionMutations = () => {
const qc = useQueryClient();
const invalidate = () => {
qc.invalidateQueries({ queryKey: keys.subscriptions });
qc.invalidateQueries({ queryKey: keys.budget });
};
const setSubscription = useMutation({
mutationFn: (b: { matchKey: string; name?: string; active: boolean }) => apiSend("POST", "/subscriptions", b),
onSuccess: invalidate,
});
const createManualSub = useMutation({
mutationFn: (b: { name: string; amount: string; category?: string; nextDue?: string }) =>
apiSend("POST", "/manual-subscriptions", b, SubscriptionSchema),
onSuccess: invalidate,
});
const deleteManualSub = useMutation({
mutationFn: (id: number) => apiSend("DELETE", `/manual-subscriptions/${id}`),
onSuccess: invalidate,
});
return { setSubscription, createManualSub, deleteManualSub };
};
// --- savings goals ---
export const useSavingsGoalMutations = () => {
const qc = useQueryClient();
const invalidate = () => qc.invalidateQueries({ queryKey: keys.budget });
const post = useMutation({
mutationFn: (b: {
originalName?: string;
name: string;
target: string;
monthlyContribution?: string;
accountId?: number;
targetDate?: string;
}) => apiSend("POST", "/savings-goals", b, BudgetSchema),
onSuccess: invalidate,
});
const remove = useMutation({
mutationFn: (name: string) => apiSend("DELETE", `/savings-goals/${encodeURIComponent(name)}`, undefined, BudgetSchema),
onSuccess: invalidate,
});
return { post, delete: remove };
};