diff --git a/src/components/BudgetProgressCard.tsx b/src/components/BudgetProgressCard.tsx index 99794e0..bee5023 100644 --- a/src/components/BudgetProgressCard.tsx +++ b/src/components/BudgetProgressCard.tsx @@ -1,9 +1,7 @@ -import React, { useState } from 'react'; + +import React 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, Calculator } from 'lucide-react'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; +import BudgetTabContent from './BudgetTabContent'; interface BudgetData { targetAmount: number; @@ -11,12 +9,6 @@ interface BudgetData { remainingAmount: number; } -interface CategoryBudget { - 식비: number; - 생활비: number; - 교통비: number; -} - interface BudgetProgressCardProps { budgetData: { daily: BudgetData; @@ -38,7 +30,8 @@ const BudgetProgressCard: React.FC = ({ calculatePercentage, onSaveBudget }) => { - return
+ return ( +
@@ -55,153 +48,34 @@ const BudgetProgressCard: React.FC = ({
지출 / 예산
- onSaveBudget('daily', amount)} /> + onSaveBudget('daily', amount)} + /> - onSaveBudget('weekly', amount)} /> + onSaveBudget('weekly', amount)} + /> - onSaveBudget('monthly', amount)} /> + onSaveBudget('monthly', amount)} + />
-
; -}; - -interface BudgetTabContentProps { - data: BudgetData; - formatCurrency: (amount: number) => string; - calculatePercentage: (spent: number, target: number) => number; - onSaveBudget: (amount: number) => void; -} - -const BudgetTabContent: React.FC = ({ - data, - formatCurrency, - calculatePercentage, - onSaveBudget -}) => { - const percentage = calculatePercentage(data.spentAmount, data.targetAmount); - const [isOpen, setIsOpen] = useState(false); - const [budgetInput, setBudgetInput] = useState(data.targetAmount.toString()); - - const [categoryBudgets, setCategoryBudgets] = useState({ - 식비: Math.round(data.targetAmount * 0.4), - 생활비: Math.round(data.targetAmount * 0.4), - 교통비: Math.round(data.targetAmount * 0.2) - }); - - const handleInputChange = (value: string) => { - // Remove all non-numeric characters - const numericValue = value.replace(/[^0-9]/g, ''); - setBudgetInput(numericValue); - }; - - const handleCategoryInputChange = (value: string, category: keyof CategoryBudget) => { - // 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); - onSaveBudget(totalAmount); - setIsOpen(false); - }; - - // Format with commas for display - const formatWithCommas = (amount: string) => { - return amount.replace(/\B(?=(\d{3})+(?!\d))/g, ','); - }; - - return
-
-
-

{formatCurrency(data.spentAmount)}

-

/ {formatCurrency(data.targetAmount)}

-
- -
-
= 90 ? "bg-yellow-400" : "bg-neuro-income"}`} /> -
- -
- - {percentage}% - -
-
- -
- 남은 예산 - {formatCurrency(data.remainingAmount)} -
- -
- - - 카테고리별 예산 설정하기 - {isOpen ? : } - - - -
-
- - handleCategoryInputChange(e.target.value, '식비')} - className="neuro-pressed max-w-[150px]" - /> -
- -
- - handleCategoryInputChange(e.target.value, '생활비')} - className="neuro-pressed max-w-[150px]" - /> -
- -
- - handleCategoryInputChange(e.target.value, '교통비')} - className="neuro-pressed max-w-[150px]" - /> -
-
- -
-
- - 총 예산: -
- {formatCurrency(Object.values(categoryBudgets).reduce((sum, value) => sum + value, 0))} -
- -
- -
- -

총 예산을 설정하면 일일, 주간 예산이 자동으로 계산됩니다.

-
-
-
-
; +
+ ); }; export default BudgetProgressCard; diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx new file mode 100644 index 0000000..0626251 --- /dev/null +++ b/src/components/BudgetTabContent.tsx @@ -0,0 +1,198 @@ + +import React, { useState } from 'react'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { Check, ChevronDown, ChevronUp, Calculator } from 'lucide-react'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; + +interface BudgetData { + targetAmount: number; + spentAmount: number; + remainingAmount: number; +} + +interface CategoryBudget { + 식비: number; + 생활비: number; + 교통비: number; +} + +interface BudgetTabContentProps { + data: BudgetData; + formatCurrency: (amount: number) => string; + calculatePercentage: (spent: number, target: number) => number; + onSaveBudget: (amount: number) => void; +} + +const BudgetTabContent: React.FC = ({ + data, + formatCurrency, + calculatePercentage, + onSaveBudget +}) => { + const percentage = calculatePercentage(data.spentAmount, data.targetAmount); + const [isOpen, setIsOpen] = useState(false); + const [budgetInput, setBudgetInput] = useState(data.targetAmount.toString()); + + const [categoryBudgets, setCategoryBudgets] = useState({ + 식비: Math.round(data.targetAmount * 0.4), + 생활비: Math.round(data.targetAmount * 0.4), + 교통비: Math.round(data.targetAmount * 0.2) + }); + + const handleInputChange = (value: string) => { + // Remove all non-numeric characters + const numericValue = value.replace(/[^0-9]/g, ''); + setBudgetInput(numericValue); + }; + + const handleCategoryInputChange = (value: string, category: keyof CategoryBudget) => { + // 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); + onSaveBudget(totalAmount); + setIsOpen(false); + }; + + // Format with commas for display + const formatWithCommas = (amount: string) => { + return amount.replace(/\B(?=(\d{3})+(?!\d))/g, ','); + }; + + return ( +
+ + +
+ 남은 예산 + {formatCurrency(data.remainingAmount)} +
+ +
+ + + 카테고리별 예산 설정하기 + {isOpen ? : } + + + + + +
+
+ + 총 예산: +
+ {formatCurrency(Object.values(categoryBudgets).reduce((sum, value) => sum + value, 0))} +
+ +
+ +
+ +

총 예산을 설정하면 일일, 주간 예산이 자동으로 계산됩니다.

+
+
+
+
+ ); +}; + +interface BudgetProgressProps { + spentAmount: number; + targetAmount: number; + percentage: number; + formatCurrency: (amount: number) => string; +} + +const BudgetProgress: React.FC = ({ + spentAmount, + targetAmount, + percentage, + formatCurrency +}) => { + return ( +
+
+

{formatCurrency(spentAmount)}

+

/ {formatCurrency(targetAmount)}

+
+ +
+
= 90 ? "bg-yellow-400" : "bg-neuro-income"}`} + /> +
+ +
+ + {percentage}% + +
+
+ ); +}; + +interface CategoryBudgetInputsProps { + categoryBudgets: CategoryBudget; + handleCategoryInputChange: (value: string, category: keyof CategoryBudget) => void; +} + +const CategoryBudgetInputs: React.FC = ({ + categoryBudgets, + handleCategoryInputChange +}) => { + return ( +
+
+ + handleCategoryInputChange(e.target.value, '식비')} + className="neuro-pressed max-w-[150px]" + /> +
+ +
+ + handleCategoryInputChange(e.target.value, '생활비')} + className="neuro-pressed max-w-[150px]" + /> +
+ +
+ + handleCategoryInputChange(e.target.value, '교통비')} + className="neuro-pressed max-w-[150px]" + /> +
+
+ ); +}; + +export default BudgetTabContent;