"use client"; import { useState, useEffect, useCallback } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import type { BankingData, Account } from "./types"; import { loadData } from "./store-db"; import type { TransactionsPaginatedParams, TransactionsPaginatedResult, } from "@/services/banking.service"; export function useBankingData() { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const fetchData = useCallback(async () => { try { setIsLoading(true); setError(null); const fetchedData = await loadData(); setData(fetchedData); } catch (err) { setError(err instanceof Error ? err : new Error("Failed to load data")); console.error("Error loading banking data:", err); } finally { setIsLoading(false); } }, []); useEffect(() => { fetchData(); }, [fetchData]); const refresh = useCallback(() => { fetchData(); }, [fetchData]); const refreshSilent = useCallback(async () => { try { const fetchedData = await loadData(); setData(fetchedData); } catch (err) { console.error("Error silently refreshing banking data:", err); } }, []); const update = useCallback((newData: BankingData) => { // Optimistic update - the actual save happens in individual operations setData(newData); }, []); return { data, isLoading, error, refresh, refreshSilent, update }; } export function useLocalStorage(key: string, initialValue: T) { const [storedValue, setStoredValue] = useState(initialValue); useEffect(() => { try { const item = window.localStorage.getItem(key); if (item) { setStoredValue(JSON.parse(item)); } } catch (error) { console.error(error); } }, [key]); const setValue = (value: T | ((val: T) => T)) => { try { const valueToStore = value instanceof Function ? value(storedValue) : value; setStoredValue(valueToStore); window.localStorage.setItem(key, JSON.stringify(valueToStore)); } catch (error) { console.error(error); } }; return [storedValue, setValue] as const; } export function useTransactions( params: TransactionsPaginatedParams = {}, enabled = true, ) { const queryClient = useQueryClient(); const query = useQuery({ queryKey: ["transactions", params], queryFn: async (): Promise => { const searchParams = new URLSearchParams(); if (params.limit) searchParams.set("limit", params.limit.toString()); if (params.offset) searchParams.set("offset", params.offset.toString()); if (params.startDate) searchParams.set("startDate", params.startDate); if (params.endDate) searchParams.set("endDate", params.endDate); if (params.accountIds && params.accountIds.length > 0) { searchParams.set("accountIds", params.accountIds.join(",")); } if (params.categoryIds && params.categoryIds.length > 0) { searchParams.set("categoryIds", params.categoryIds.join(",")); } if (params.includeUncategorized) { searchParams.set("includeUncategorized", "true"); } if (params.search) searchParams.set("search", params.search); if (params.isReconciled !== undefined && params.isReconciled !== "all") { searchParams.set( "isReconciled", params.isReconciled === true ? "true" : "false", ); } if (params.sortField) searchParams.set("sortField", params.sortField); if (params.sortOrder) searchParams.set("sortOrder", params.sortOrder); const response = await fetch(`/api/banking/transactions?${searchParams}`); if (!response.ok) { throw new Error("Failed to fetch transactions"); } return response.json(); }, enabled, staleTime: 30 * 1000, // 30 seconds }); const invalidate = useCallback(() => { queryClient.invalidateQueries({ queryKey: ["transactions"] }); }, [queryClient]); return { ...query, invalidate, }; } export function useCategoryStats() { return useQuery({ queryKey: ["category-stats"], queryFn: async (): Promise> => { const response = await fetch("/api/banking/categories?statsOnly=true"); if (!response.ok) { throw new Error("Failed to fetch category stats"); } return response.json(); }, staleTime: 60 * 1000, // 1 minute }); } export function useBankingMetadata() { return useQuery({ queryKey: ["banking-metadata"], queryFn: async () => { const response = await fetch("/api/banking?metadataOnly=true"); if (!response.ok) { throw new Error("Failed to fetch banking metadata"); } return response.json(); }, staleTime: 5 * 60 * 1000, // 5 minutes }); } export function useAccountsWithStats() { return useQuery({ queryKey: ["accounts-with-stats"], queryFn: async () => { const response = await fetch("/api/banking/accounts?withStats=true"); if (!response.ok) { throw new Error("Failed to fetch accounts with stats"); } return response.json() as Promise< Array >; }, staleTime: 60 * 1000, // 1 minute }); }