import { keepPreviousData, useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { getQuotes, fetchQuotes, getQuoteHistory, getDailyMinMax, getDailyQuotes, getHistoricalMinMax, getPeriodicExpenses, createPeriodicExpense as createPeriodicExpenseApi, updatePeriodicExpense as updatePeriodicExpenseApi, deletePeriodicExpense as deletePeriodicExpenseApi, generateMonthlyExpense as generateMonthlyExpenseApi, getExpenses, createNonPeriodicExpense as createNonPeriodicExpenseApi, payExpense as payExpenseApi, getMonthlyPayedTotal, getMonthlyTotals, getTotalPending, importPeriodicExpenses, importExpenses, type CreatePeriodicExpenseInput, type CreateNonPeriodicExpenseInput, type PayExpenseInput, } from "./api"; export const quoteKeys = { all: ["quotes"] as const, history: (type: string, startDate: string, endDate: string) => ["quotes", type, "history", startDate, endDate] as const, minMax: (type: string, startDate: string, endDate: string) => ["quotes", type, "minMax", startDate, endDate] as const, daily: (type: string, startDate: string, endDate: string) => ["quotes", type, "daily", startDate, endDate] as const, historicalMinMax: (type: string) => ["quotes", type, "historicalMinMax"] as const, }; export function useQuotes() { return useQuery({ queryKey: quoteKeys.all, queryFn: getQuotes, staleTime: 30_000, refetchInterval: 60_000, }); } export function useFetchQuotes() { const queryClient = useQueryClient(); return useMutation({ mutationFn: fetchQuotes, onSuccess: () => { queryClient.invalidateQueries({ queryKey: quoteKeys.all }); }, }); } export function useQuoteHistory(type: string, startDate: string, endDate: string) { return useQuery({ queryKey: quoteKeys.history(type, startDate, endDate), queryFn: () => getQuoteHistory(type, startDate, endDate), staleTime: 30_000, refetchInterval: 60_000, }); } export function useDailyMinMax(type: string, startDate: string, endDate: string) { return useQuery({ queryKey: quoteKeys.minMax(type, startDate, endDate), queryFn: () => getDailyMinMax(type, startDate, endDate), staleTime: 30_000, refetchInterval: 60_000, }); } export function useDailyQuotes(type: string, startDate: string, endDate: string) { return useQuery({ queryKey: quoteKeys.daily(type, startDate, endDate), queryFn: () => getDailyQuotes(type, startDate, endDate), staleTime: 30_000, refetchInterval: 60_000, }); } export function useHistoricalMinMax(type: string) { return useQuery({ queryKey: quoteKeys.historicalMinMax(type), queryFn: () => getHistoricalMinMax(type), staleTime: 30_000, }); } // Expenses export const expenseKeys = { periodic: ["periodic-expenses"] as const, all: ["expenses"] as const, byFilters: (status: string, page: number, pageSize: number, periodicExpenseId?: number, search?: string) => ["expenses", status, page, pageSize, periodicExpenseId, search] as const, monthlyTotal: (year: number, month: number) => ["expenses", "monthly-total", year, month] as const, monthlyTotals: (year: number, month: number) => ["expenses", "totals", year, month] as const, totalPending: ["expenses", "pending-total"] as const, }; export function usePeriodicExpenses() { return useQuery({ queryKey: expenseKeys.periodic, queryFn: getPeriodicExpenses, }); } export function useCreatePeriodicExpense() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (data: CreatePeriodicExpenseInput) => createPeriodicExpenseApi(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: expenseKeys.periodic }); }, }); } export function useUpdatePeriodicExpense() { const queryClient = useQueryClient(); return useMutation({ mutationFn: ({ id, data }: { id: number; data: CreatePeriodicExpenseInput }) => updatePeriodicExpenseApi(id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: expenseKeys.periodic }); }, }); } export function useDeletePeriodicExpense() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (id: number) => deletePeriodicExpenseApi(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: expenseKeys.periodic }); }, }); } export function useGenerateMonthlyExpense() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (id: number) => generateMonthlyExpenseApi(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: expenseKeys.all }); }, }); } export function useExpenses(status: string, page: number = 1, pageSize: number = 10, periodicExpenseId?: number, search?: string) { return useQuery({ queryKey: expenseKeys.byFilters(status, page, pageSize, periodicExpenseId, search), placeholderData: keepPreviousData, queryFn: () => getExpenses( status === "all" ? undefined : status, page, pageSize, periodicExpenseId, search, ), }); } export function useMonthlyTotals(year: number, month: number) { return useQuery({ queryKey: expenseKeys.monthlyTotals(year, month), queryFn: () => getMonthlyTotals(year, month), }); } export function useTotalPending() { return useQuery({ queryKey: expenseKeys.totalPending, queryFn: getTotalPending, }); } export function useMonthlyPayedTotal(year: number, month: number) { return useQuery({ queryKey: expenseKeys.monthlyTotal(year, month), queryFn: () => getMonthlyPayedTotal(year, month), }); } export function useCreateNonPeriodicExpense() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (data: CreateNonPeriodicExpenseInput) => createNonPeriodicExpenseApi(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: expenseKeys.all }); }, }); } export function useImportExpenses() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (file: File) => importExpenses(file), onSuccess: () => { queryClient.invalidateQueries({ queryKey: expenseKeys.all }); }, }); } export function useImportPeriodicExpenses() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (file: File) => importPeriodicExpenses(file), onSuccess: () => { queryClient.invalidateQueries({ queryKey: expenseKeys.periodic }); }, }); } export function usePayExpense() { const queryClient = useQueryClient(); return useMutation({ mutationFn: ({ id, data }: { id: number; data: PayExpenseInput }) => payExpenseApi(id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: expenseKeys.all }); }, }); }