From 78da23abe6834c35a03bec0f9d5a30ad7304744f Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 22 Mar 2025 13:22:33 +0000 Subject: [PATCH] Refactor RecentTransactionsSection Further refactors RecentTransactionsSection to separate remaining logic. Creates additional hooks and utility files as needed. --- src/components/RecentTransactionsSection.tsx | 18 ++++++----- .../RecentTransactionItem.tsx | 5 +-- .../transactions/useRecentTransactions.ts | 20 ++++++++++-- .../useRecentTransactionsDialog.ts | 32 +++++++++++++++++++ src/utils/currencyFormatter.ts | 29 +++++++++++++++++ 5 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 src/hooks/transactions/useRecentTransactionsDialog.ts create mode 100644 src/utils/currencyFormatter.ts diff --git a/src/components/RecentTransactionsSection.tsx b/src/components/RecentTransactionsSection.tsx index dd104ff..ae0e7e8 100644 --- a/src/components/RecentTransactionsSection.tsx +++ b/src/components/RecentTransactionsSection.tsx @@ -1,11 +1,12 @@ -import React, { useState } from 'react'; +import React from 'react'; import { Transaction } from '@/contexts/budget/types'; import TransactionEditDialog from './TransactionEditDialog'; import { ChevronRight } from 'lucide-react'; import { useBudget } from '@/contexts/budget/BudgetContext'; import { Link } from 'react-router-dom'; import { useRecentTransactions } from '@/hooks/transactions/useRecentTransactions'; +import { useRecentTransactionsDialog } from '@/hooks/transactions/useRecentTransactionsDialog'; import RecentTransactionItem from './recent-transactions/RecentTransactionItem'; interface RecentTransactionsSectionProps { @@ -17,17 +18,18 @@ const RecentTransactionsSection: React.FC = ({ transactions, onUpdateTransaction }) => { - const [selectedTransaction, setSelectedTransaction] = useState(null); - const [isDialogOpen, setIsDialogOpen] = useState(false); const { updateTransaction, deleteTransaction } = useBudget(); // 트랜잭션 삭제 관련 로직은 커스텀 훅으로 분리 const { handleDeleteTransaction, isDeleting } = useRecentTransactions(deleteTransaction); - - const handleTransactionClick = (transaction: Transaction) => { - setSelectedTransaction(transaction); - setIsDialogOpen(true); - }; + + // 다이얼로그 관련 로직 분리 + const { + selectedTransaction, + isDialogOpen, + handleTransactionClick, + setIsDialogOpen + } = useRecentTransactionsDialog(); const handleUpdateTransaction = (updatedTransaction: Transaction) => { if (onUpdateTransaction) { diff --git a/src/components/recent-transactions/RecentTransactionItem.tsx b/src/components/recent-transactions/RecentTransactionItem.tsx index 3691f93..5ebf157 100644 --- a/src/components/recent-transactions/RecentTransactionItem.tsx +++ b/src/components/recent-transactions/RecentTransactionItem.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { Transaction } from '@/contexts/budget/types'; import TransactionIcon from '../transaction/TransactionIcon'; +import { formatCurrency } from '@/utils/currencyFormatter'; interface RecentTransactionItemProps { transaction: Transaction; @@ -12,10 +13,6 @@ const RecentTransactionItem: React.FC = ({ transaction, onClick }) => { - const formatCurrency = (amount: number) => { - return amount.toLocaleString('ko-KR') + '원'; - }; - return (
void @@ -58,8 +58,9 @@ export const useRecentTransactions = ( }, 900); // 비동기 작업을 동기적으로 처리하여 UI 블로킹 방지 - setTimeout(async () => { + setTimeout(() => { try { + // BudgetContext의 deleteTransaction 함수 호출 deleteTransaction(id); // 안전장치 타임아웃 제거 @@ -73,8 +74,23 @@ export const useRecentTransactions = ( setIsDeleting(false); deletingIdRef.current = null; }, 100); + + // 성공 메시지 표시 + toast({ + title: "항목이 삭제되었습니다", + description: "지출 내역이 성공적으로 삭제되었습니다.", + duration: 1500 + }); } catch (err) { console.error('삭제 처리 오류:', err); + + // 에러 메시지 표시 + toast({ + title: "삭제 실패", + description: "항목을 삭제하는 중 오류가 발생했습니다.", + variant: "destructive", + duration: 1500 + }); } }, 0); diff --git a/src/hooks/transactions/useRecentTransactionsDialog.ts b/src/hooks/transactions/useRecentTransactionsDialog.ts new file mode 100644 index 0000000..e1518d6 --- /dev/null +++ b/src/hooks/transactions/useRecentTransactionsDialog.ts @@ -0,0 +1,32 @@ + +import { useState } from 'react'; +import { Transaction } from '@/contexts/budget/types'; + +/** + * 최근 거래내역의 다이얼로그 상태를 관리하는 커스텀 훅 + */ +export const useRecentTransactionsDialog = () => { + const [selectedTransaction, setSelectedTransaction] = useState(null); + const [isDialogOpen, setIsDialogOpen] = useState(false); + + const handleTransactionClick = (transaction: Transaction) => { + setSelectedTransaction(transaction); + setIsDialogOpen(true); + }; + + const handleCloseDialog = () => { + setIsDialogOpen(false); + // 약간의 딜레이 후 선택된 트랜잭션 초기화 (애니메이션 완료 후) + setTimeout(() => { + setSelectedTransaction(null); + }, 300); + }; + + return { + selectedTransaction, + isDialogOpen, + handleTransactionClick, + handleCloseDialog, + setIsDialogOpen + }; +}; diff --git a/src/utils/currencyFormatter.ts b/src/utils/currencyFormatter.ts new file mode 100644 index 0000000..87bf5aa --- /dev/null +++ b/src/utils/currencyFormatter.ts @@ -0,0 +1,29 @@ + +/** + * 숫자를 한국 통화 형식으로 변환합니다. + * 1000 -> 1,000원 + */ +export const formatCurrency = (amount: number): string => { + return amount.toLocaleString('ko-KR') + '원'; +}; + +/** + * 문자열에서 숫자만 추출합니다. + * "1,000원" -> 1000 + */ +export const extractNumber = (value: string): number => { + const numericValue = value.replace(/[^\d]/g, ''); + return numericValue ? parseInt(numericValue, 10) : 0; +}; + +/** + * 입력값을 통화 형식으로 변환합니다. (입력 필드용) + * 1000 -> "1,000" + */ +export const formatInputCurrency = (value: string): string => { + const numericValue = value.replace(/[^\d]/g, ''); + if (!numericValue) return ''; + + const number = parseInt(numericValue, 10); + return number.toLocaleString('ko-KR'); +};