import { useState, useEffect } from 'react'; import { Transaction, Category, TransactionSummary } from '../types'; import { apiClient } from '../utils/api'; import { API_ENDPOINTS } from '../config/api'; export const useTransactions = () => { const [transactions, setTransactions] = useState([]); const [categories, setCategories] = useState([]); const [loading, setLoading] = useState(false); const [summary, setSummary] = useState({ totalIncome: 0, totalExpenses: 0, balance: 0, categoryBreakdown: [], }); const fetchTransactions = async () => { setLoading(true); try { const data = await apiClient.get(API_ENDPOINTS.transactions.list); setTransactions(data); calculateSummary(data); } catch (error) { console.error('Failed to fetch transactions:', error); } finally { setLoading(false); } }; const fetchCategories = async () => { try { const data = await apiClient.get(API_ENDPOINTS.categories.list); setCategories(data); } catch (error) { console.error('Failed to fetch categories:', error); } }; const createTransaction = async (transaction: Omit) => { try { const newTransaction = await apiClient.post( API_ENDPOINTS.transactions.create, transaction ); setTransactions(prev => [newTransaction, ...prev]); calculateSummary([newTransaction, ...transactions]); return newTransaction; } catch (error) { throw new Error('Failed to create transaction'); } }; const updateTransaction = async (id: string, updates: Partial) => { try { const updatedTransaction = await apiClient.put( API_ENDPOINTS.transactions.update(id), updates ); setTransactions(prev => prev.map(t => (t.id === id ? updatedTransaction : t)) ); const newTransactions = transactions.map(t => (t.id === id ? updatedTransaction : t)); calculateSummary(newTransactions); return updatedTransaction; } catch (error) { throw new Error('Failed to update transaction'); } }; const deleteTransaction = async (id: string) => { try { await apiClient.delete(API_ENDPOINTS.transactions.delete(id)); setTransactions(prev => prev.filter(t => t.id !== id)); const newTransactions = transactions.filter(t => t.id !== id); calculateSummary(newTransactions); } catch (error) { throw new Error('Failed to delete transaction'); } }; const calculateSummary = (transactionList: Transaction[]) => { const totalIncome = transactionList .filter(t => t.type === 'income') .reduce((sum, t) => sum + t.amount, 0); const totalExpenses = transactionList .filter(t => t.type === 'expense') .reduce((sum, t) => sum + t.amount, 0); const balance = totalIncome - totalExpenses; const categoryTotals = transactionList.reduce((acc, transaction) => { const categoryName = transaction.category?.name || 'Uncategorized'; acc[categoryName] = (acc[categoryName] || 0) + Math.abs(transaction.amount); return acc; }, {} as Record); const totalAmount = Object.values(categoryTotals).reduce((sum, amount) => sum + amount, 0); const categoryBreakdown = Object.entries(categoryTotals) .map(([category, amount]) => ({ category, amount, percentage: totalAmount > 0 ? (amount / totalAmount) * 100 : 0, })) .sort((a, b) => b.amount - a.amount); setSummary({ totalIncome, totalExpenses, balance, categoryBreakdown, }); }; useEffect(() => { fetchTransactions(); fetchCategories(); }, []); return { transactions, categories, loading, summary, createTransaction, updateTransaction, deleteTransaction, refreshTransactions: fetchTransactions, refreshCategories: fetchCategories, }; };