- Fix budget amount not displaying outside the homepage. - Remove unexpected categories and revert to the original 3 categories.
168 lines
5.2 KiB
TypeScript
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
|
|
};
|
|
};
|