Fix: Handle undefined budget data

The `useBudgetTabContent` hook was throwing an error when `data` prop was undefined. This commit adds a check to ensure that `data` is defined before accessing its properties.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-23 10:09:50 +00:00
parent abf8c6ae0c
commit 8cf2e70050
4 changed files with 40 additions and 11 deletions

View File

@@ -13,7 +13,7 @@ interface BudgetData {
remainingAmount: number; remainingAmount: number;
} }
interface BudgetTabContentProps { export interface BudgetTabContentProps {
data: BudgetData; data: BudgetData;
formatCurrency: (amount: number) => string; formatCurrency: (amount: number) => string;
calculatePercentage: (spent: number, target: number) => number; calculatePercentage: (spent: number, target: number) => number;
@@ -26,6 +26,12 @@ const BudgetTabContent: React.FC<BudgetTabContentProps> = ({
calculatePercentage, calculatePercentage,
onSaveBudget onSaveBudget
}) => { }) => {
// 데이터 유효성 체크 - 데이터가 없으면 기본값 사용
if (!data) {
console.warn('BudgetTabContent: data prop이 제공되지 않았습니다. 기본값을 사용합니다.');
data = { targetAmount: 0, spentAmount: 0, remainingAmount: 0 };
}
const { const {
categoryBudgets, categoryBudgets,
showBudgetInput, showBudgetInput,

View File

@@ -1,3 +1,4 @@
import React from 'react'; import React from 'react';
import { Transaction } from '@/contexts/budget/types'; import { Transaction } from '@/contexts/budget/types';
import TransactionEditDialog from './TransactionEditDialog'; import TransactionEditDialog from './TransactionEditDialog';
@@ -8,7 +9,7 @@ import { useRecentTransactions } from '@/hooks/transactions/useRecentTransaction
import { useRecentTransactionsDialog } from '@/hooks/transactions/useRecentTransactionsDialog'; import { useRecentTransactionsDialog } from '@/hooks/transactions/useRecentTransactionsDialog';
import RecentTransactionItem from './recent-transactions/RecentTransactionItem'; import RecentTransactionItem from './recent-transactions/RecentTransactionItem';
interface RecentTransactionsSectionProps { export interface RecentTransactionsSectionProps {
transactions: Transaction[]; transactions: Transaction[];
onUpdateTransaction?: (transaction: Transaction) => void; onUpdateTransaction?: (transaction: Transaction) => void;
} }

View File

@@ -37,15 +37,18 @@ export const useBudgetTabContent = ({
calculatePercentage, calculatePercentage,
onSaveBudget onSaveBudget
}: UseBudgetTabContentProps): UseBudgetTabContentReturn => { }: UseBudgetTabContentProps): UseBudgetTabContentReturn => {
// 데이터가 undefined인 경우를 방지하기 위한 기본값 설정
const safeData = data || { targetAmount: 0, spentAmount: 0, remainingAmount: 0 };
const [categoryBudgets, setCategoryBudgets] = useState<Record<string, number>>({}); const [categoryBudgets, setCategoryBudgets] = useState<Record<string, number>>({});
const [showBudgetInput, setShowBudgetInput] = useState(false); const [showBudgetInput, setShowBudgetInput] = useState(false);
const spentAmount = data.spentAmount; const spentAmount = safeData.spentAmount;
const targetAmount = data.targetAmount; const targetAmount = safeData.targetAmount;
// 로그 추가 - 받은 데이터 확인 // 로그 추가 - 받은 데이터 확인
useEffect(() => { useEffect(() => {
console.log(`BudgetTabContent 수신 데이터:`, data); console.log(`BudgetTabContent 수신 데이터:`, safeData);
}, [data]); }, [safeData]);
// 전역 예산 데이터가 변경되었을 때 로컬 상태 갱신 // 전역 예산 데이터가 변경되었을 때 로컬 상태 갱신
useEffect(() => { useEffect(() => {

View File

@@ -7,17 +7,24 @@ import RecentTransactionsSection from '@/components/RecentTransactionsSection';
import Header from '@/components/Header'; import Header from '@/components/Header';
import { useBudget } from '@/contexts/budget'; import { useBudget } from '@/contexts/budget';
import SafeAreaContainer from '@/components/SafeAreaContainer'; import SafeAreaContainer from '@/components/SafeAreaContainer';
import { formatCurrency } from '@/utils/formatters';
const Index = () => { const Index = () => {
const { transactions, budgetData } = useBudget(); const { transactions, budgetData, handleBudgetGoalUpdate } = useBudget();
// 페이지 마운트 시 데이터 로깅 (디버깅 용도) // 데이터 구조 확인용 로깅
useEffect(() => { useEffect(() => {
console.info('Index 페이지 마운트, 현재 데이터 상태:'); console.info('Index 페이지 마운트, 현재 데이터 상태:');
console.info('트랜잭션:', transactions.length); console.info('트랜잭션:', transactions?.length);
console.info('예산 데이터:', budgetData); console.info('예산 데이터:', budgetData);
}, [transactions, budgetData]); }, [transactions, budgetData]);
// 예산 퍼센트 계산 함수
const calculatePercentage = (spent: number, target: number) => {
if (target <= 0) return 0;
return Math.min(100, Math.round((spent / target) * 100));
};
return ( return (
<SafeAreaContainer className="min-h-screen bg-neuro-background"> <SafeAreaContainer className="min-h-screen bg-neuro-background">
<div className="max-w-md mx-auto px-6"> <div className="max-w-md mx-auto px-6">
@@ -30,11 +37,23 @@ const Index = () => {
</TabsList> </TabsList>
<TabsContent value="budget" className="focus-visible:outline-none"> <TabsContent value="budget" className="focus-visible:outline-none">
<BudgetTabContent budgetData={budgetData.monthly} /> {budgetData && budgetData.monthly && (
<BudgetTabContent
data={budgetData.monthly}
formatCurrency={formatCurrency}
calculatePercentage={calculatePercentage}
onSaveBudget={(amount, categoryBudgets) =>
handleBudgetGoalUpdate('monthly', amount, categoryBudgets)
}
/>
)}
</TabsContent> </TabsContent>
<TabsContent value="recent" className="focus-visible:outline-none"> <TabsContent value="recent" className="focus-visible:outline-none">
<RecentTransactionsSection /> <RecentTransactionsSection
transactions={transactions || []}
onUpdateTransaction={transaction => console.log('트랜잭션 업데이트', transaction)}
/>
</TabsContent> </TabsContent>
</Tabs> </Tabs>
</div> </div>