Initial public release

Aurum — a self-hosted personal finance operating system: cash flow,
net worth tracking, budgets, goals, recurring payments, reports,
proactive alerts, and a compound-interest returns calculator, all
bilingual (RU/EN) and mobile-first. Ships as a three-container Docker
Compose stack (Postgres + FastAPI + nginx-served React frontend).

See README.md for setup and CONTRIBUTING.md for development.
This commit is contained in:
ZProger
2026-08-16 18:39:52 +03:00
commit fe9b079c12
199 changed files with 14410 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
createTransaction,
deleteTransaction,
fetchTransactions,
updateTransaction,
type TransactionFilters,
} from "@/api/transactions";
import type { TransactionInput } from "@/types";
function useInvalidateAfterTransactionChange() {
const queryClient = useQueryClient();
return () => {
queryClient.invalidateQueries({ queryKey: ["transactions"] });
queryClient.invalidateQueries({ queryKey: ["dashboard-summary"] });
queryClient.invalidateQueries({ queryKey: ["net-worth-summary"] });
queryClient.invalidateQueries({ queryKey: ["category-spending-report"] });
queryClient.invalidateQueries({ queryKey: ["category-ranking"] });
queryClient.invalidateQueries({ queryKey: ["budget-status"] });
queryClient.invalidateQueries({ queryKey: ["financial-alerts"] });
queryClient.invalidateQueries({ queryKey: ["advice"] });
queryClient.invalidateQueries({ queryKey: ["cash-flow"] });
};
}
export function useTransactions(filters: TransactionFilters) {
return useQuery({
queryKey: ["transactions", filters],
queryFn: () => fetchTransactions(filters),
});
}
export function useCreateTransaction() {
const invalidate = useInvalidateAfterTransactionChange();
return useMutation({
mutationFn: (input: TransactionInput) => createTransaction(input),
onSuccess: invalidate,
});
}
export function useUpdateTransaction() {
const invalidate = useInvalidateAfterTransactionChange();
return useMutation({
mutationFn: ({ id, input }: { id: number; input: Partial<TransactionInput> }) =>
updateTransaction(id, input),
onSuccess: invalidate,
});
}
export function useDeleteTransaction() {
const invalidate = useInvalidateAfterTransactionChange();
return useMutation({
mutationFn: (id: number) => deleteTransaction(id),
onSuccess: invalidate,
});
}