Files
personal-admin-2026/apps/frontend/src/lib/queries.ts

220 lines
6.6 KiB
TypeScript

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 });
},
});
}