Files
zellyy-finance/src/hooks/useTransactions.ts
gpt-engineer-app[bot] 79d38f1fc1 Fix budget display and category issues
- Fix budget amount not displaying outside the homepage.
- Remove unexpected categories and revert to the original 3 categories.
2025-03-16 08:17:02 +00:00

168 lines
5.2 KiB
TypeScript

import { useState, useEffect } from 'react';
import { Transaction } from '@/components/TransactionCard';
import { useAuth } from '@/contexts/auth/AuthProvider';
import { toast } from '@/hooks/useToast.wrapper';
import { isSyncEnabled } from '@/utils/syncUtils';
import { MONTHS_KR, getCurrentMonth, getPrevMonth, getNextMonth } from '@/utils/dateUtils';
import {
loadTransactionsFromStorage,
saveTransactionsToStorage,
loadBudgetFromStorage
} from '@/utils/storageUtils';
import {
filterTransactionsByMonth,
filterTransactionsByQuery,
calculateTotalExpenses
} from '@/utils/transactionUtils';
import {
syncTransactionsWithSupabase,
updateTransactionInSupabase,
deleteTransactionFromSupabase
} from '@/utils/supabaseTransactionUtils';
import { EXPENSE_CATEGORIES } from '@/constants/categoryIcons';
// 월 이름 재노출
export { MONTHS_KR };
export const useTransactions = () => {
const [transactions, setTransactions] = useState<Transaction[]>([]);
const [filteredTransactions, setFilteredTransactions] = useState<Transaction[]>([]);
const [selectedMonth, setSelectedMonth] = useState(getCurrentMonth());
const [searchQuery, setSearchQuery] = useState('');
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [totalBudget, setTotalBudget] = useState(1000000); // 기본 예산
const { user } = useAuth();
// 월 변경 처리
const handlePrevMonth = () => {
setSelectedMonth(getPrevMonth(selectedMonth));
};
const handleNextMonth = () => {
setSelectedMonth(getNextMonth(selectedMonth));
};
// 트랜잭션 로드
const loadTransactions = () => {
setIsLoading(true);
setError(null);
try {
// 로컬 스토리지에서 트랜잭션 데이터 가져오기
const localData = loadTransactionsFromStorage();
// 지원되는 카테고리로 필터링
const filteredData = localData.map(transaction => {
// 트랜잭션의 카테고리가 현재 지원되는 카테고리가 아니면 '기타'로 변경
if (transaction.type === 'expense' && !EXPENSE_CATEGORIES.includes(transaction.category)) {
return {
...transaction,
category: '생활비' // 기본값으로 '생활비' 사용
};
}
return transaction;
});
// 로컬 데이터가 있으면 사용
setTransactions(filteredData);
// 예산 가져오기
const budget = loadBudgetFromStorage();
setTotalBudget(budget);
} catch (err) {
console.error('트랜잭션 로드 중 오류:', err);
setError('데이터를 불러오는 중 문제가 발생했습니다.');
toast({
title: "데이터 로드 실패",
description: "지출 내역을 불러오는데 실패했습니다.",
variant: "destructive"
});
} finally {
setIsLoading(false);
}
};
// 필터 적용
useEffect(() => {
// 1. 월별 필터링
let filtered = filterTransactionsByMonth(transactions, selectedMonth);
// 2. 검색어 필터링
if (searchQuery.trim()) {
filtered = filterTransactionsByQuery(filtered, searchQuery);
}
setFilteredTransactions(filtered);
}, [transactions, selectedMonth, searchQuery]);
// 초기 데이터 로드
useEffect(() => {
loadTransactions();
// Supabase 동기화 (로그인 상태인 경우)
const syncWithSupabase = async () => {
if (user) {
const syncedTransactions = await syncTransactionsWithSupabase(user, transactions);
if (syncedTransactions !== transactions) {
setTransactions(syncedTransactions);
saveTransactionsToStorage(syncedTransactions);
}
}
};
syncWithSupabase();
}, [user]);
// 트랜잭션 업데이트
const updateTransaction = (updatedTransaction: Transaction) => {
const updatedTransactions = transactions.map(transaction =>
transaction.id === updatedTransaction.id ? updatedTransaction : transaction
);
setTransactions(updatedTransactions);
saveTransactionsToStorage(updatedTransactions);
// Supabase에도 업데이트
updateTransactionInSupabase(user, updatedTransaction);
toast({
title: "지출이 수정되었습니다",
description: `${updatedTransaction.title} 항목이 업데이트되었습니다.`,
});
};
// 트랜잭션 삭제
const deleteTransaction = (id: string) => {
const updatedTransactions = transactions.filter(transaction => transaction.id !== id);
setTransactions(updatedTransactions);
saveTransactionsToStorage(updatedTransactions);
// Supabase에서도 삭제
deleteTransactionFromSupabase(user, id);
toast({
title: "지출이 삭제되었습니다",
description: "선택한 지출 항목이 삭제되었습니다.",
});
};
return {
transactions: filteredTransactions,
isLoading,
error,
totalBudget,
selectedMonth,
searchQuery,
setSearchQuery,
handlePrevMonth,
handleNextMonth,
updateTransaction,
deleteTransaction,
totalExpenses: calculateTotalExpenses(filteredTransactions),
refreshTransactions: loadTransactions
};
};