diff --git a/src/components/TransactionCard.tsx b/src/components/TransactionCard.tsx index dc0b174..a1ffc4a 100644 --- a/src/components/TransactionCard.tsx +++ b/src/components/TransactionCard.tsx @@ -23,16 +23,9 @@ interface TransactionCardProps { const TransactionCard: React.FC = ({ transaction, - onUpdate }) => { const [isEditDialogOpen, setIsEditDialogOpen] = useState(false); - const { title, amount, date, category, type } = transaction; - - const handleSaveTransaction = (updatedTransaction: Transaction) => { - if (onUpdate) { - onUpdate(updatedTransaction); - } - }; + const { title, amount, date, category } = transaction; return ( <> @@ -54,7 +47,6 @@ const TransactionCard: React.FC = ({ transaction={transaction} open={isEditDialogOpen} onOpenChange={setIsEditDialogOpen} - onSave={handleSaveTransaction} /> ); diff --git a/src/components/TransactionEditDialog.tsx b/src/components/TransactionEditDialog.tsx index f9999c4..d1651a6 100644 --- a/src/components/TransactionEditDialog.tsx +++ b/src/components/TransactionEditDialog.tsx @@ -10,7 +10,8 @@ import { DialogHeader, DialogTitle, DialogFooter, - DialogClose + DialogClose, + DialogDescription } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Form } from '@/components/ui/form'; @@ -78,20 +79,19 @@ const TransactionEditDialog: React.FC = ({ }; const handleDelete = () => { - // 컨텍스트를 통해 트랜잭션 삭제 - deleteTransaction(transaction.id); - - // 부모 컴포넌트의 onDelete 콜백이 있다면 호출 - if (onDelete) { - onDelete(transaction.id); - } - + // 다이얼로그 닫기를 먼저 수행 (UI 블로킹 방지) onOpenChange(false); - toast({ - title: "지출이 삭제되었습니다", - description: `${transaction.title} 항목이 삭제되었습니다.`, - }); + // 약간의 지연 후 삭제 작업 수행 (안정성 향상) + setTimeout(() => { + // 컨텍스트를 통해 트랜잭션 삭제 + deleteTransaction(transaction.id); + + // 부모 컴포넌트의 onDelete 콜백이 있다면 호출 + if (onDelete) { + onDelete(transaction.id); + } + }, 100); }; return ( @@ -99,6 +99,9 @@ const TransactionEditDialog: React.FC = ({ 지출 수정 + + 지출 내역을 수정하거나 삭제할 수 있습니다. +
diff --git a/src/contexts/budget/hooks/useTransactionState.ts b/src/contexts/budget/hooks/useTransactionState.ts index 31d9c14..c116382 100644 --- a/src/contexts/budget/hooks/useTransactionState.ts +++ b/src/contexts/budget/hooks/useTransactionState.ts @@ -1,3 +1,4 @@ + import { useState, useEffect, useCallback } from 'react'; import { Transaction } from '../types'; import { @@ -11,6 +12,7 @@ import { toast } from '@/hooks/useToast.wrapper'; // 래퍼 사용 export const useTransactionState = () => { const [transactions, setTransactions] = useState([]); const [lastDeletedId, setLastDeletedId] = useState(null); + const [isDeleting, setIsDeleting] = useState(false); // 초기 트랜잭션 로드 및 이벤트 리스너 설정 useEffect(() => { @@ -72,9 +74,15 @@ export const useTransactionState = () => { }); }, []); - // 트랜잭션 삭제 함수 + // 트랜잭션 삭제 함수 - 안정성 개선 const deleteTransaction = useCallback((transactionId: string) => { - console.log('트랜잭션 삭제:', transactionId); + // 이미 삭제 중이면 중복 삭제 방지 + if (isDeleting) { + console.log('이미 삭제 작업이 진행 중입니다.'); + return; + } + + console.log('트랜잭션 삭제 시작:', transactionId); // 중복 삭제 방지 if (lastDeletedId === transactionId) { @@ -82,24 +90,50 @@ export const useTransactionState = () => { return; } + setIsDeleting(true); setLastDeletedId(transactionId); - setTransactions(prev => { - const updated = prev.filter(transaction => transaction.id !== transactionId); - saveTransactionsToStorage(updated); - - // 토스트는 한 번만 호출 - toast({ - title: "지출이 삭제되었습니다", - description: "지출 항목이 성공적으로 삭제되었습니다.", + try { + setTransactions(prev => { + // 기존 트랜잭션 목록 백업 (문제 발생 시 복원용) + const originalTransactions = [...prev]; + + // 삭제할 항목 필터링 + const updated = prev.filter(transaction => transaction.id !== transactionId); + + // 항목이 실제로 삭제되었는지 확인 + if (updated.length === originalTransactions.length) { + console.log('삭제할 트랜잭션을 찾을 수 없음:', transactionId); + setIsDeleting(false); + return originalTransactions; + } + + // 저장소에 업데이트된 목록 저장 + saveTransactionsToStorage(updated); + + // 토스트 메시지 표시 + toast({ + title: "지출이 삭제되었습니다", + description: "지출 항목이 성공적으로 삭제되었습니다.", + }); + + return updated; }); - - return updated; - }); - - // 5초 후 lastDeletedId 초기화 - setTimeout(() => setLastDeletedId(null), 5000); - }, [lastDeletedId]); + } catch (error) { + console.error('트랜잭션 삭제 중 오류 발생:', error); + toast({ + title: "삭제 실패", + description: "지출 항목 삭제 중 오류가 발생했습니다.", + variant: "destructive" + }); + } finally { + // 삭제 상태 초기화 (1초 후) + setTimeout(() => { + setIsDeleting(false); + setLastDeletedId(null); + }, 1000); + } + }, [lastDeletedId, isDeleting]); // 트랜잭션 초기화 함수 const resetTransactions = useCallback(() => { diff --git a/src/hooks/transactions/useTransactionsCore.ts b/src/hooks/transactions/useTransactionsCore.ts index c1624dd..406d38e 100644 --- a/src/hooks/transactions/useTransactionsCore.ts +++ b/src/hooks/transactions/useTransactionsCore.ts @@ -66,6 +66,7 @@ export const useTransactionsCore = () => { // 데이터 강제 새로고침 const refreshTransactions = useCallback(() => { + console.log('트랜잭션 강제 새로고침'); setRefreshKey(prev => prev + 1); loadTransactions(); }, [loadTransactions, setRefreshKey]); diff --git a/src/pages/Transactions.tsx b/src/pages/Transactions.tsx index 9887053..49a5a55 100644 --- a/src/pages/Transactions.tsx +++ b/src/pages/Transactions.tsx @@ -17,8 +17,7 @@ const Transactions = () => { setSearchQuery, handlePrevMonth, handleNextMonth, - updateTransaction, - deleteTransaction, + refreshTransactions, totalExpenses, } = useTransactions(); @@ -48,15 +47,13 @@ const Transactions = () => { const handleVisibilityChange = () => { if (document.visibilityState === 'visible') { console.log('거래내역 페이지 보임 - 데이터 새로고침'); - // 상태 업데이트 트리거 - setIsDataLoaded(prev => !prev); + refreshTransactions(); } }; const handleFocus = () => { console.log('거래내역 페이지 포커스 - 데이터 새로고침'); - // 상태 업데이트 트리거 - setIsDataLoaded(prev => !prev); + refreshTransactions(); }; document.addEventListener('visibilitychange', handleVisibilityChange); @@ -66,7 +63,7 @@ const Transactions = () => { document.removeEventListener('visibilitychange', handleVisibilityChange); window.removeEventListener('focus', handleFocus); }; - }, []); + }, [refreshTransactions]); return (
@@ -168,8 +165,7 @@ const Transactions = () => { {transactions.map(transaction => ( ))}