diff --git a/src/components/BudgetInputCard.tsx b/src/components/BudgetInputCard.tsx index 110489e..bc9d558 100644 --- a/src/components/BudgetInputCard.tsx +++ b/src/components/BudgetInputCard.tsx @@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; -import { Check, ChevronDown, ChevronUp } from 'lucide-react'; +import { Check, ChevronDown, ChevronUp, Wallet } from 'lucide-react'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; interface BudgetGoalProps { @@ -13,11 +13,13 @@ interface BudgetGoalProps { monthly: number; }; onSave: (type: 'daily' | 'weekly' | 'monthly', amount: number) => void; + highlight?: boolean; } const BudgetInputCard: React.FC = ({ initialBudgets, - onSave + onSave, + highlight = false }) => { const [selectedTab, setSelectedTab] = useState<'daily' | 'weekly' | 'monthly'>('daily'); const [budgetInputs, setBudgetInputs] = useState({ @@ -25,7 +27,7 @@ const BudgetInputCard: React.FC = ({ weekly: initialBudgets.weekly > 0 ? initialBudgets.weekly.toString() : '', monthly: initialBudgets.monthly > 0 ? initialBudgets.monthly.toString() : '' }); - const [isOpen, setIsOpen] = useState(false); + const [isOpen, setIsOpen] = useState(highlight); // Format with commas for display const formatWithCommas = (amount: string) => { @@ -87,10 +89,13 @@ const BudgetInputCard: React.FC = ({ - 예산 목표 설정하기 + + {highlight && } + 예산 목표 설정하기 + {isOpen ? ( ) : ( @@ -114,7 +119,7 @@ const BudgetInputCard: React.FC = ({ placeholder="목표 금액 입력" className="neuro-pressed" /> - @@ -131,7 +136,7 @@ const BudgetInputCard: React.FC = ({ placeholder="목표 금액 입력" className="neuro-pressed" /> - @@ -148,7 +153,7 @@ const BudgetInputCard: React.FC = ({ placeholder="목표 금액 입력" className="neuro-pressed" /> - diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 6f79d69..0c8bfca 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -1,12 +1,8 @@ import React, { useState } from 'react'; +import { Plus, Wallet } from 'lucide-react'; +import BudgetInputCard from './BudgetInputCard'; import { Button } from '@/components/ui/button'; -import { Check, ChevronDown, ChevronUp, Calculator } from 'lucide-react'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; -import BudgetProgress from './BudgetProgress'; -import CategoryBudgetInputs from './CategoryBudgetInputs'; -import { toast } from '@/hooks/useToast.wrapper'; // 래퍼 함수 사용 -import { EXPENSE_CATEGORIES } from '@/constants/categoryIcons'; interface BudgetData { targetAmount: number; @@ -27,109 +23,77 @@ const BudgetTabContent: React.FC = ({ calculatePercentage, onSaveBudget }) => { - const percentage = calculatePercentage(data.spentAmount, data.targetAmount); - const [isOpen, setIsOpen] = useState(false); - const [budgetInput, setBudgetInput] = useState(data.targetAmount > 0 ? data.targetAmount.toString() : ''); - - // 저장된 카테고리 예산을 불러옵니다 - const savedCategoryBudgets = localStorage.getItem('categoryBudgets'); - const defaultCategoryAmount = data.targetAmount > 0 ? Math.round(data.targetAmount / EXPENSE_CATEGORIES.length) : 0; - const initialCategoryBudgets = savedCategoryBudgets ? JSON.parse(savedCategoryBudgets) : EXPENSE_CATEGORIES.reduce((acc, category) => { - acc[category] = defaultCategoryAmount; - return acc; - }, {} as Record); + const [showBudgetInput, setShowBudgetInput] = useState(false); - const [categoryBudgets, setCategoryBudgets] = useState>(initialCategoryBudgets); - - const handleInputChange = (value: string) => { - // Remove all non-numeric characters - const numericValue = value.replace(/[^0-9]/g, ''); - setBudgetInput(numericValue); - }; - - const handleCategoryInputChange = (value: string, category: string) => { - // Remove all non-numeric characters - const numericValue = value.replace(/[^0-9]/g, ''); - setCategoryBudgets(prev => ({ - ...prev, - [category]: parseInt(numericValue) || 0 - })); - }; - - const handleSave = () => { - // Calculate total from all categories - const totalAmount = Object.values(categoryBudgets).reduce((sum, value) => sum + value, 0); - - // 버튼 중복 클릭 방지를 위해 비활성화 처리 (setTimeout 사용) - const button = document.querySelector('button[type="button"]') as HTMLButtonElement; - if (button) { - button.disabled = true; - setTimeout(() => { - button.disabled = false; - }, 1000); - } - - // 카테고리 예산도 함께 전달합니다 - onSaveBudget(totalAmount, categoryBudgets); - - // 단일 토스트만 표시하고 즉시 패널 닫음 - setIsOpen(false); - - // 토스트는 이벤트 발생 후 처리되므로 여기서는 호출하지 않음 - // 이 함수에서 직접 toast 호출하지 않고 budgetStorage에서 처리되도록 함 - }; - - // Format with commas for display - const formatWithCommas = (amount: string) => { - return amount.replace(/\B(?=(\d{3})+(?!\d))/g, ','); - }; + const spentAmount = data.spentAmount; + const targetAmount = data.targetAmount; + const percentage = calculatePercentage(spentAmount, targetAmount); + const isFirstBudget = targetAmount === 0; return ( -
- - -
- 남은 예산 - {formatCurrency(data.remainingAmount)} -
- -
- - - 예산 설정하기 - {isOpen ? : } - +
+ {targetAmount > 0 ? ( + <> +
+
{formatCurrency(spentAmount)}
+
/ {formatCurrency(targetAmount)}
+
- - +
- -
-
- - 총 예산: -
- {formatCurrency(Object.values(categoryBudgets).reduce((sum, value) => sum + value, 0))} +
+ +
+
+ 남은 예산: {formatCurrency(Math.max(0, targetAmount - spentAmount))}
- -
- +
+ {percentage}%
- -

카테고리 예산을 설정하면 일일, 주간, 월간 예산이 자동으로 합산됩니다.

- - -
+
+ +
+ +
+ + ) : ( +
+
아직 예산이 설정되지 않았습니다
+ +
+ )} + + {showBudgetInput && ( +
+ { + onSaveBudget(amount); + setShowBudgetInput(false); + }} + highlight={isFirstBudget} + /> +
+ )}
); };