141 lines
4.3 KiB
TypeScript
141 lines
4.3 KiB
TypeScript
import { createContext, useContext, useState, useCallback, type ReactNode } from "react";
|
|
import {
|
|
usePeriodicExpenses,
|
|
useCreatePeriodicExpense,
|
|
useUpdatePeriodicExpense,
|
|
useDeletePeriodicExpense,
|
|
useGenerateMonthlyExpense,
|
|
useExpenses,
|
|
useCreateNonPeriodicExpense,
|
|
usePayExpense,
|
|
useMonthlyTotals,
|
|
} from "@/lib/queries";
|
|
import type {
|
|
PeriodicExpense,
|
|
Expense,
|
|
CreatePeriodicExpenseInput,
|
|
CreateNonPeriodicExpenseInput,
|
|
PayExpenseInput,
|
|
PaginatedResponse,
|
|
MonthlyTotals,
|
|
} from "@/lib/api";
|
|
|
|
interface ExpensesContextValue {
|
|
periodicExpenses: PeriodicExpense[];
|
|
isLoadingPeriodic: boolean;
|
|
|
|
expenses: PaginatedResponse<Expense>;
|
|
isLoadingExpenses: boolean;
|
|
statusFilter: string;
|
|
setStatusFilter: (status: string) => void;
|
|
page: number;
|
|
setPage: (page: number) => void;
|
|
pageSize: number;
|
|
|
|
monthlyTotals: MonthlyTotals | undefined;
|
|
isLoadingTotals: boolean;
|
|
|
|
createPeriodicExpense: (data: CreatePeriodicExpenseInput) => Promise<PeriodicExpense>;
|
|
updatePeriodicExpense: (id: number, data: CreatePeriodicExpenseInput) => Promise<void>;
|
|
deletePeriodicExpense: (id: number) => Promise<void>;
|
|
generateMonthlyExpense: (id: number) => Promise<Expense>;
|
|
createNonPeriodicExpense: (data: CreateNonPeriodicExpenseInput) => Promise<void>;
|
|
payExpense: (id: number, data: PayExpenseInput) => Promise<void>;
|
|
}
|
|
|
|
const ExpensesContext = createContext<ExpensesContextValue | null>(null);
|
|
|
|
export function ExpensesProvider({ children }: { children: ReactNode }) {
|
|
const [statusFilter, setStatusFilter] = useState("PENDING");
|
|
const [page, setPage] = useState(1);
|
|
const pageSize = 10;
|
|
|
|
const { data: periodicExpenses = [], isLoading: isLoadingPeriodic } = usePeriodicExpenses();
|
|
const { data: expenses = { data: [], total: 0, page: 1, pageSize: 10 }, isLoading: isLoadingExpenses } =
|
|
useExpenses(statusFilter, page, pageSize);
|
|
|
|
const now = new Date();
|
|
const { data: monthlyTotals, isLoading: isLoadingTotals } = useMonthlyTotals(now.getFullYear(), now.getMonth() + 1);
|
|
|
|
const createPeriodicMutation = useCreatePeriodicExpense();
|
|
const updatePeriodicMutation = useUpdatePeriodicExpense();
|
|
const deletePeriodicMutation = useDeletePeriodicExpense();
|
|
const generateMonthlyMutation = useGenerateMonthlyExpense();
|
|
const createExpenseMutation = useCreateNonPeriodicExpense();
|
|
const payExpenseMutation = usePayExpense();
|
|
|
|
const createPeriodicExpense = useCallback(
|
|
async (data: CreatePeriodicExpenseInput): Promise<PeriodicExpense> => {
|
|
return createPeriodicMutation.mutateAsync(data);
|
|
},
|
|
[createPeriodicMutation],
|
|
);
|
|
|
|
const updatePeriodicExpenseFn = useCallback(
|
|
async (id: number, data: CreatePeriodicExpenseInput) => {
|
|
await updatePeriodicMutation.mutateAsync({ id, data });
|
|
},
|
|
[updatePeriodicMutation],
|
|
);
|
|
|
|
const deletePeriodicExpenseFn = useCallback(
|
|
async (id: number) => {
|
|
await deletePeriodicMutation.mutateAsync(id);
|
|
},
|
|
[deletePeriodicMutation],
|
|
);
|
|
|
|
const generateMonthlyExpenseFn = useCallback(
|
|
async (id: number): Promise<Expense> => {
|
|
return generateMonthlyMutation.mutateAsync(id);
|
|
},
|
|
[generateMonthlyMutation],
|
|
);
|
|
|
|
const createNonPeriodicExpenseFn = useCallback(
|
|
async (data: CreateNonPeriodicExpenseInput) => {
|
|
await createExpenseMutation.mutateAsync(data);
|
|
},
|
|
[createExpenseMutation],
|
|
);
|
|
|
|
const payExpenseFn = useCallback(
|
|
async (id: number, data: PayExpenseInput) => {
|
|
await payExpenseMutation.mutateAsync({ id, data });
|
|
},
|
|
[payExpenseMutation],
|
|
);
|
|
|
|
return (
|
|
<ExpensesContext
|
|
value={{
|
|
periodicExpenses,
|
|
isLoadingPeriodic,
|
|
expenses,
|
|
isLoadingExpenses,
|
|
statusFilter,
|
|
setStatusFilter,
|
|
page,
|
|
setPage,
|
|
pageSize,
|
|
monthlyTotals,
|
|
isLoadingTotals,
|
|
createPeriodicExpense,
|
|
updatePeriodicExpense: updatePeriodicExpenseFn,
|
|
deletePeriodicExpense: deletePeriodicExpenseFn,
|
|
generateMonthlyExpense: generateMonthlyExpenseFn,
|
|
createNonPeriodicExpense: createNonPeriodicExpenseFn,
|
|
payExpense: payExpenseFn,
|
|
}}
|
|
>
|
|
{children}
|
|
</ExpensesContext>
|
|
);
|
|
}
|
|
|
|
export function useExpensesContext() {
|
|
const ctx = useContext(ExpensesContext);
|
|
if (!ctx) throw new Error("useExpensesContext must be used within ExpensesProvider");
|
|
return ctx;
|
|
}
|