From edeb9f8ffb9f8709c387efb97f17aa847442651a Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 12:10:59 +0000 Subject: [PATCH] Update budget display and input - Allow budget progress bar to exceed 100% when over budget. - Streamline budget input by directly displaying category budgets. --- src/components/BudgetCategoriesSection.tsx | 14 +++-- src/components/BudgetTabContent.tsx | 69 +++++++++++++++++----- src/components/CategoryBudgetInputs.tsx | 38 +----------- 3 files changed, 64 insertions(+), 57 deletions(-) diff --git a/src/components/BudgetCategoriesSection.tsx b/src/components/BudgetCategoriesSection.tsx index 83c0e5f..a0063c3 100644 --- a/src/components/BudgetCategoriesSection.tsx +++ b/src/components/BudgetCategoriesSection.tsx @@ -20,9 +20,15 @@ const BudgetCategoriesSection: React.FC = ({ {categories.map((category, index) => { // 예산 초과 여부 확인 const isOverBudget = category.current > category.total && category.total > 0; + // 실제 백분율 계산 (초과해도 실제 퍼센트로 표시) + const actualPercentage = category.total > 0 + ? Math.round((category.current / category.total) * 100) + : 0; + // 프로그레스 바용 퍼센트 (100%로 제한하지 않음) + const displayPercentage = actualPercentage; + // 예산이 얼마 남지 않은 경우 (10% 미만) - const percentage = Math.min(Math.round((category.current / (category.total || 1)) * 100), 100); - const isLowBudget = category.total > 0 && percentage >= 90 && percentage < 100; + const isLowBudget = category.total > 0 && actualPercentage >= 90 && actualPercentage < 100; // 프로그레스 바 색상 결정 const progressBarColor = isOverBudget @@ -57,7 +63,7 @@ const BudgetCategoriesSection: React.FC = ({
@@ -66,7 +72,7 @@ const BudgetCategoriesSection: React.FC = ({ {budgetStatusText}{formatCurrency(budgetAmount)} - {percentage}% + {displayPercentage}%
diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index b5f86e2..3a4981f 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -1,8 +1,9 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { Plus, Wallet } from 'lucide-react'; import BudgetInputCard from './BudgetInputCard'; import { Button } from '@/components/ui/button'; +import CategoryBudgetInputs from './CategoryBudgetInputs'; interface BudgetData { targetAmount: number; @@ -23,11 +24,16 @@ const BudgetTabContent: React.FC = ({ calculatePercentage, onSaveBudget }) => { + const [categoryBudgets, setCategoryBudgets] = useState>({}); const [showBudgetInput, setShowBudgetInput] = useState(false); const spentAmount = data.spentAmount; const targetAmount = data.targetAmount; - const percentage = calculatePercentage(spentAmount, targetAmount); + // 실제 백분율 계산 (초과해도 실제 퍼센트로 표시) + const actualPercentage = targetAmount > 0 + ? Math.round((spentAmount / targetAmount) * 100) + : 0; + const percentage = actualPercentage; const isFirstBudget = targetAmount === 0; // 예산 초과 여부 계산 @@ -51,6 +57,14 @@ const BudgetTabContent: React.FC = ({ ? formatCurrency(Math.abs(targetAmount - spentAmount)) : formatCurrency(Math.max(0, targetAmount - spentAmount)); + const handleCategoryInputChange = (value: string, category: string) => { + const numValue = parseInt(value, 10) || 0; + setCategoryBudgets(prev => ({ + ...prev, + [category]: numValue + })); + }; + return (
{targetAmount > 0 ? ( @@ -63,7 +77,7 @@ const BudgetTabContent: React.FC = ({
@@ -78,7 +92,7 @@ const BudgetTabContent: React.FC = ({
+
+
+ +
+

카테고리별 예산 설정

+ +
+
)} diff --git a/src/components/CategoryBudgetInputs.tsx b/src/components/CategoryBudgetInputs.tsx index f2c4215..e77386d 100644 --- a/src/components/CategoryBudgetInputs.tsx +++ b/src/components/CategoryBudgetInputs.tsx @@ -1,9 +1,8 @@ -import React, { useEffect, useRef } from 'react'; +import React from 'react'; import { Input } from '@/components/ui/input'; import { EXPENSE_CATEGORIES } from '@/constants/categoryIcons'; import { useIsMobile } from '@/hooks/use-mobile'; -import { toast } from '@/components/ui/use-toast'; interface CategoryBudgetInputsProps { categoryBudgets: Record; @@ -15,7 +14,6 @@ const CategoryBudgetInputs: React.FC = ({ handleCategoryInputChange }) => { const isMobile = useIsMobile(); - const previousBudgetsRef = useRef>({}); // Format number with commas for display const formatWithCommas = (value: number): string => { @@ -36,40 +34,6 @@ const CategoryBudgetInputs: React.FC = ({ }, 300); }; - // 컴포넌트가 마운트될 때 categoryBudgets가 로컬 스토리지에서 다시 로드되도록 이벤트 리스너 설정 - useEffect(() => { - const handleStorageChange = () => { - // 부모 컴포넌트에서 데이터가 업데이트되므로 별도 처리 필요 없음 - console.log('카테고리 예산 데이터 변경 감지됨'); - }; - - window.addEventListener('categoryBudgetsUpdated', handleStorageChange); - window.addEventListener('storage', handleStorageChange); - - return () => { - window.removeEventListener('categoryBudgetsUpdated', handleStorageChange); - window.removeEventListener('storage', handleStorageChange); - }; - }, []); - - // 값이 변경될 때마다 토스트 메시지 표시 - useEffect(() => { - const hasChanges = Object.keys(categoryBudgets).some( - category => categoryBudgets[category] !== previousBudgetsRef.current[category] - ); - - const totalBudget = Object.values(categoryBudgets).reduce((sum, val) => sum + val, 0); - const previousTotal = Object.values(previousBudgetsRef.current).reduce((sum, val) => sum + val, 0); - - // 이전 값과 다르고, 총 예산이 있는 경우 토스트 표시 - if (hasChanges && totalBudget > 0 && totalBudget !== previousTotal) { - // 토스트 메시지는 storage에서 처리 - } - - // 현재 값을 이전 값으로 업데이트 - previousBudgetsRef.current = { ...categoryBudgets }; - }, [categoryBudgets]); - return (
{EXPENSE_CATEGORIES.map(category => (