merge: Phase 5 (Rules Engine) + Phase 6 (Budget & Analytics)
Resolve additive conflicts in schema.prisma and hooks.ts — both models and all hooks retained.
This commit is contained in:
@@ -431,3 +431,72 @@ export function useApplyRules() {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// --- Budgets & Analytics ---
|
||||
|
||||
export interface BudgetRow {
|
||||
id: number;
|
||||
category: string;
|
||||
month: string;
|
||||
amount_limit: number;
|
||||
}
|
||||
|
||||
export interface MonthlyAnalyticsRow {
|
||||
category: string;
|
||||
spent: Record<string, number>;
|
||||
budget: Record<string, number>;
|
||||
txCount: Record<string, number>;
|
||||
}
|
||||
|
||||
export interface MonthlyAnalytics {
|
||||
months: string[];
|
||||
rows: MonthlyAnalyticsRow[];
|
||||
totals: Record<string, { spent: number; budget: number }>;
|
||||
}
|
||||
|
||||
export function useBudgets(month: string) {
|
||||
return useQuery<BudgetRow[]>({
|
||||
queryKey: ["budgets", month],
|
||||
queryFn: async () => {
|
||||
const res = await fetch(`/api/budgets?month=${month}`);
|
||||
return res.json();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpsertBudget() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async (data: { category: string; month: string; amount_limit: number }) => {
|
||||
const res = await fetch("/api/budgets", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
if (!res.ok) throw new Error("Failed to save budget");
|
||||
return res.json();
|
||||
},
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: ["budgets"] }),
|
||||
});
|
||||
}
|
||||
|
||||
export function useDeleteBudget() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async (id: number) => {
|
||||
await fetch(`/api/budgets/${id}`, { method: "DELETE" });
|
||||
},
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: ["budgets"] }),
|
||||
});
|
||||
}
|
||||
|
||||
export function useMonthlyAnalytics(months?: number) {
|
||||
const m = months || 6;
|
||||
return useQuery<MonthlyAnalytics>({
|
||||
queryKey: ["analytics", "monthly", m],
|
||||
queryFn: async () => {
|
||||
const res = await fetch(`/api/analytics/monthly?months=${m}`);
|
||||
return res.json();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user