From 20969dfb07cecd435fe4ff133360f75c3de411ac 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 11:51:11 +0000 Subject: [PATCH 01/30] Visual edit in Lovable Edited UI in Lovable --- src/components/BudgetCategoriesSection.tsx | 28 +++++++--------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/components/BudgetCategoriesSection.tsx b/src/components/BudgetCategoriesSection.tsx index d66eea6..c6147e0 100644 --- a/src/components/BudgetCategoriesSection.tsx +++ b/src/components/BudgetCategoriesSection.tsx @@ -1,7 +1,5 @@ - import React from 'react'; import BudgetCard from '@/components/BudgetCard'; - interface BudgetCategoriesSectionProps { categories: { title: string; @@ -9,24 +7,14 @@ interface BudgetCategoriesSectionProps { total: number; }[]; } - -const BudgetCategoriesSection: React.FC = ({ categories }) => { - return ( - <> -

지출 카테고리

+const BudgetCategoriesSection: React.FC = ({ + categories +}) => { + return <> +

지출 그래프

- {categories.map((category, index) => ( - - ))} + {categories.map((category, index) => )}
- - ); + ; }; - -export default BudgetCategoriesSection; +export default BudgetCategoriesSection; \ No newline at end of file From 64da436552d41cfbdcc70f37fa7e3f8596c81e16 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 11:52:10 +0000 Subject: [PATCH 02/30] Refactor budget categories section Consolidated the budget categories section into a single card. --- src/components/BudgetCategoriesSection.tsx | 46 ++++++++++++++++++---- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/components/BudgetCategoriesSection.tsx b/src/components/BudgetCategoriesSection.tsx index c6147e0..bf9e872 100644 --- a/src/components/BudgetCategoriesSection.tsx +++ b/src/components/BudgetCategoriesSection.tsx @@ -1,5 +1,8 @@ + import React from 'react'; -import BudgetCard from '@/components/BudgetCard'; +import { categoryIcons } from '@/constants/categoryIcons'; +import { formatCurrency } from '@/utils/formatters'; + interface BudgetCategoriesSectionProps { categories: { title: string; @@ -7,14 +10,43 @@ interface BudgetCategoriesSectionProps { total: number; }[]; } + const BudgetCategoriesSection: React.FC = ({ categories }) => { return <> -

지출 그래프

-
- {categories.map((category, index) => )} -
- ; +

지출 그래프

+
+ {categories.map((category, index) => ( +
+
+
+ {categoryIcons[category.title]} +
+

{category.title}

+
+ +
+

{formatCurrency(category.current)}

+

/ {formatCurrency(category.total)}

+
+ +
+
+
+ +
+ + {Math.min(Math.round((category.current / category.total) * 100), 100)}% + +
+
+ ))} +
+ ; }; -export default BudgetCategoriesSection; \ No newline at end of file + +export default BudgetCategoriesSection; From bbcea786be9a2b0801af659597b24013e84d7ad5 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 11:53:43 +0000 Subject: [PATCH 03/30] Display remaining budget in graph Display the remaining budget amount in the expense graph section. --- src/components/BudgetCategoriesSection.tsx | 61 +++++++++++++--------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/src/components/BudgetCategoriesSection.tsx b/src/components/BudgetCategoriesSection.tsx index bf9e872..834380b 100644 --- a/src/components/BudgetCategoriesSection.tsx +++ b/src/components/BudgetCategoriesSection.tsx @@ -17,34 +17,43 @@ const BudgetCategoriesSection: React.FC = ({ return <>

지출 그래프

- {categories.map((category, index) => ( -
-
-
- {categoryIcons[category.title]} + {categories.map((category, index) => { + // 남은 예산 계산 (음수가 되지 않도록) + const remaining = Math.max(0, category.total - category.current); + const percentage = Math.min(Math.round((category.current / category.total) * 100), 100); + + return ( +
+
+
+ {categoryIcons[category.title]} +
+

{category.title}

+
+ +
+

{formatCurrency(category.current)}

+

/ {formatCurrency(category.total)}

+
+ +
+
+
+ +
+ + 남은 예산: {formatCurrency(remaining)} + + + {percentage}% +
-

{category.title}

- -
-

{formatCurrency(category.current)}

-

/ {formatCurrency(category.total)}

-
- -
-
-
- -
- - {Math.min(Math.round((category.current / category.total) * 100), 100)}% - -
-
- ))} + ); + })}
; }; From cfe035ff3fb65a814f23cb51f588527ddd2af384 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 11:55:38 +0000 Subject: [PATCH 04/30] Use consistent category icons Use the same icons in the recent transactions card as in the expense chart. --- src/components/RecentTransactionsSection.tsx | 34 +++++++------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/components/RecentTransactionsSection.tsx b/src/components/RecentTransactionsSection.tsx index bb7300b..d54f99f 100644 --- a/src/components/RecentTransactionsSection.tsx +++ b/src/components/RecentTransactionsSection.tsx @@ -4,10 +4,14 @@ import TransactionEditDialog from './TransactionEditDialog'; import { ChevronRight } from 'lucide-react'; import { useBudget } from '@/contexts/BudgetContext'; import { Link } from 'react-router-dom'; +import { categoryIcons } from '@/constants/categoryIcons'; +import TransactionIcon from './transaction/TransactionIcon'; + interface RecentTransactionsSectionProps { transactions: Transaction[]; onUpdateTransaction?: (transaction: Transaction) => void; } + const RecentTransactionsSection: React.FC = ({ transactions, onUpdateTransaction @@ -18,10 +22,12 @@ const RecentTransactionsSection: React.FC = ({ updateTransaction, deleteTransaction } = useBudget(); + const handleTransactionClick = (transaction: Transaction) => { setSelectedTransaction(transaction); setIsDialogOpen(true); }; + const handleUpdateTransaction = (updatedTransaction: Transaction) => { if (onUpdateTransaction) { onUpdateTransaction(updatedTransaction); @@ -29,33 +35,16 @@ const RecentTransactionsSection: React.FC = ({ // 직접 컨텍스트를 통해 업데이트 updateTransaction(updatedTransaction); }; + const handleDeleteTransaction = (id: string) => { // 직접 컨텍스트를 통해 삭제 deleteTransaction(id); }; + const formatCurrency = (amount: number) => { return amount.toLocaleString('ko-KR') + '원'; }; - const getCategoryIcon = (category: string) => { - switch (category) { - case '식비': - return '🍽️'; - case '교통비': - return '🚗'; - case '생활비': - return '🏠'; - case '쇼핑': - return '🛍️'; - case '의료': - return '💊'; - case '여가': - return '🎮'; - case '교육': - return '📚'; - default: - return '💰'; - } - }; + return

최근 지출

@@ -66,8 +55,8 @@ const RecentTransactionsSection: React.FC = ({
{transactions.length > 0 ? transactions.map(transaction =>
handleTransactionClick(transaction)} className="flex justify-between py-3 px-4 cursor-pointer hover:bg-gray-50">
- {getCategoryIcon(transaction.category)} -
+ +

{transaction.title}

{transaction.date}

@@ -84,4 +73,5 @@ const RecentTransactionsSection: React.FC = ({ {selectedTransaction && }
; }; + export default RecentTransactionsSection; From 0fe4825741fc4704c0af680705a15e88c16a4c57 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 11:56:29 +0000 Subject: [PATCH 05/30] Visual edit in Lovable Edited UI in Lovable --- src/components/RecentTransactionsSection.tsx | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/components/RecentTransactionsSection.tsx b/src/components/RecentTransactionsSection.tsx index d54f99f..716db8f 100644 --- a/src/components/RecentTransactionsSection.tsx +++ b/src/components/RecentTransactionsSection.tsx @@ -6,12 +6,10 @@ import { useBudget } from '@/contexts/BudgetContext'; import { Link } from 'react-router-dom'; import { categoryIcons } from '@/constants/categoryIcons'; import TransactionIcon from './transaction/TransactionIcon'; - interface RecentTransactionsSectionProps { transactions: Transaction[]; onUpdateTransaction?: (transaction: Transaction) => void; } - const RecentTransactionsSection: React.FC = ({ transactions, onUpdateTransaction @@ -22,12 +20,10 @@ const RecentTransactionsSection: React.FC = ({ updateTransaction, deleteTransaction } = useBudget(); - const handleTransactionClick = (transaction: Transaction) => { setSelectedTransaction(transaction); setIsDialogOpen(true); }; - const handleUpdateTransaction = (updatedTransaction: Transaction) => { if (onUpdateTransaction) { onUpdateTransaction(updatedTransaction); @@ -35,16 +31,13 @@ const RecentTransactionsSection: React.FC = ({ // 직접 컨텍스트를 통해 업데이트 updateTransaction(updatedTransaction); }; - const handleDeleteTransaction = (id: string) => { // 직접 컨텍스트를 통해 삭제 deleteTransaction(id); }; - const formatCurrency = (amount: number) => { return amount.toLocaleString('ko-KR') + '원'; }; - return

최근 지출

@@ -53,7 +46,7 @@ const RecentTransactionsSection: React.FC = ({
- {transactions.length > 0 ? transactions.map(transaction =>
handleTransactionClick(transaction)} className="flex justify-between py-3 px-4 cursor-pointer hover:bg-gray-50"> + {transactions.length > 0 ? transactions.map(transaction =>
handleTransactionClick(transaction)} className="flex justify-between py-3 cursor-pointer hover:bg-gray-50 px-[5px]">
@@ -73,5 +66,4 @@ const RecentTransactionsSection: React.FC = ({ {selectedTransaction && }
; }; - -export default RecentTransactionsSection; +export default RecentTransactionsSection; \ No newline at end of file From ccc1d913be57180065ad4d93639c516d45190850 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 11:58:52 +0000 Subject: [PATCH 06/30] Emphasize initial budget setting Add visual emphasis to the budget setting prompt on the home screen to guide new users. --- src/components/BudgetInputCard.tsx | 21 ++-- src/components/BudgetTabContent.tsx | 168 +++++++++++----------------- 2 files changed, 79 insertions(+), 110 deletions(-) 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} + /> +
+ )}
); }; From f9fb5364bb0d6da21bbed3bd34c158ce89f2197b 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:06:19 +0000 Subject: [PATCH 07/30] Enhance budget display and alerts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Increase font size of "예산 목표 설정하기" text. - Change budget bar color to yellow if remaining budget is less than 10%, and to red if over budget. - Display "예산 초과" and the exceeded amount when the budget is exceeded. --- src/components/BudgetCategoriesSection.tsx | 30 +++++++++++++++++----- src/components/BudgetTabContent.tsx | 29 ++++++++++++++++++--- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/components/BudgetCategoriesSection.tsx b/src/components/BudgetCategoriesSection.tsx index 834380b..83c0e5f 100644 --- a/src/components/BudgetCategoriesSection.tsx +++ b/src/components/BudgetCategoriesSection.tsx @@ -18,9 +18,27 @@ const BudgetCategoriesSection: React.FC = ({

지출 그래프

{categories.map((category, index) => { - // 남은 예산 계산 (음수가 되지 않도록) - const remaining = Math.max(0, category.total - category.current); - const percentage = Math.min(Math.round((category.current / category.total) * 100), 100); + // 예산 초과 여부 확인 + const isOverBudget = category.current > category.total && category.total > 0; + // 예산이 얼마 남지 않은 경우 (10% 미만) + const percentage = Math.min(Math.round((category.current / (category.total || 1)) * 100), 100); + const isLowBudget = category.total > 0 && percentage >= 90 && percentage < 100; + + // 프로그레스 바 색상 결정 + const progressBarColor = isOverBudget + ? 'bg-red-500' + : isLowBudget + ? 'bg-yellow-400' + : 'bg-neuro-income'; + + // 남은 예산 또는 초과 예산 + const budgetStatusText = isOverBudget + ? '예산 초과: ' + : '남은 예산: '; + + const budgetAmount = isOverBudget + ? Math.abs(category.total - category.current) + : Math.max(0, category.total - category.current); return (
@@ -38,14 +56,14 @@ const BudgetCategoriesSection: React.FC = ({
- - 남은 예산: {formatCurrency(remaining)} + + {budgetStatusText}{formatCurrency(budgetAmount)} {percentage}% diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 0c8bfca..b5f86e2 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -30,6 +30,27 @@ const BudgetTabContent: React.FC = ({ const percentage = calculatePercentage(spentAmount, targetAmount); const isFirstBudget = targetAmount === 0; + // 예산 초과 여부 계산 + const isOverBudget = spentAmount > targetAmount; + // 예산이 얼마 남지 않은 경우 (10% 미만) + const isLowBudget = targetAmount > 0 && percentage >= 90 && percentage < 100; + + // 프로그레스 바 색상 결정 + const progressBarColor = isOverBudget + ? 'bg-red-500' + : isLowBudget + ? 'bg-yellow-400' + : 'bg-neuro-income'; + + // 남은 예산 또는 초과 예산 텍스트 및 금액 + const budgetStatusText = isOverBudget + ? '예산 초과: ' + : '남은 예산: '; + + const budgetAmount = isOverBudget + ? formatCurrency(Math.abs(targetAmount - spentAmount)) + : formatCurrency(Math.max(0, targetAmount - spentAmount)); + return (
{targetAmount > 0 ? ( @@ -41,14 +62,14 @@ const BudgetTabContent: React.FC = ({
-
- 남은 예산: {formatCurrency(Math.max(0, targetAmount - spentAmount))} +
+ {budgetStatusText}{budgetAmount}
{percentage}% @@ -58,7 +79,7 @@ const BudgetTabContent: React.FC = ({
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 08/30] 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 => ( From c7300bebb7afdb5456797e68973c1520a30449a2 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:14:33 +0000 Subject: [PATCH 09/30] Visual edit in Lovable Edited UI in Lovable --- src/components/BudgetTabContent.tsx | 106 ++++++++-------------------- 1 file changed, 29 insertions(+), 77 deletions(-) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 3a4981f..35db633 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -1,23 +1,19 @@ - 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; spentAmount: number; remainingAmount: number; } - interface BudgetTabContentProps { data: BudgetData; formatCurrency: (amount: number) => string; calculatePercentage: (spent: number, target: number) => number; onSaveBudget: (amount: number, categoryBudgets?: Record) => void; } - const BudgetTabContent: React.FC = ({ data, formatCurrency, @@ -26,37 +22,24 @@ const BudgetTabContent: React.FC = ({ }) => { const [categoryBudgets, setCategoryBudgets] = useState>({}); const [showBudgetInput, setShowBudgetInput] = useState(false); - const spentAmount = data.spentAmount; const targetAmount = data.targetAmount; // 실제 백분율 계산 (초과해도 실제 퍼센트로 표시) - const actualPercentage = targetAmount > 0 - ? Math.round((spentAmount / targetAmount) * 100) - : 0; + const actualPercentage = targetAmount > 0 ? Math.round(spentAmount / targetAmount * 100) : 0; const percentage = actualPercentage; const isFirstBudget = targetAmount === 0; - + // 예산 초과 여부 계산 const isOverBudget = spentAmount > targetAmount; // 예산이 얼마 남지 않은 경우 (10% 미만) const isLowBudget = targetAmount > 0 && percentage >= 90 && percentage < 100; - + // 프로그레스 바 색상 결정 - const progressBarColor = isOverBudget - ? 'bg-red-500' - : isLowBudget - ? 'bg-yellow-400' - : 'bg-neuro-income'; - + const progressBarColor = isOverBudget ? 'bg-red-500' : isLowBudget ? 'bg-yellow-400' : 'bg-neuro-income'; + // 남은 예산 또는 초과 예산 텍스트 및 금액 - const budgetStatusText = isOverBudget - ? '예산 초과: ' - : '남은 예산: '; - - const budgetAmount = isOverBudget - ? formatCurrency(Math.abs(targetAmount - spentAmount)) - : formatCurrency(Math.max(0, targetAmount - spentAmount)); - + const budgetStatusText = isOverBudget ? '예산 초과: ' : '남은 예산: '; + const budgetAmount = isOverBudget ? 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 => ({ @@ -64,21 +47,17 @@ const BudgetTabContent: React.FC = ({ [category]: numValue })); }; - - return ( -
- {targetAmount > 0 ? ( - <> + return
+ {targetAmount > 0 ? <>
{formatCurrency(spentAmount)}
/ {formatCurrency(targetAmount)}
-
+
@@ -91,52 +70,31 @@ const BudgetTabContent: React.FC = ({
-
- - ) : ( -
+ :
아직 예산이 설정되지 않았습니다
- -
- )} +
} - {showBudgetInput && ( -
+ {showBudgetInput &&

전체 예산 설정

- 0 ? targetAmount : ''} - onChange={(e) => { - const value = e.target.value.replace(/[^0-9]/g, ''); - if (value) { - const amount = parseInt(value, 10); - onSaveBudget(amount, categoryBudgets); - } - }} - /> -
@@ -144,16 +102,10 @@ const BudgetTabContent: React.FC = ({

카테고리별 예산 설정

- +
-
- )} -
- ); +
} +
; }; - -export default BudgetTabContent; +export default BudgetTabContent; \ No newline at end of file From 236925f787e24f3e7d3421a832b80b1cd9042565 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:17:32 +0000 Subject: [PATCH 10/30] Enhance budget input UI - Improve the '+' icon for budget modification. - Display the sum of category budgets instead of an input field for the total budget. - Change the wallet icon in budget input. --- src/components/BudgetCategoriesSection.tsx | 2 +- src/components/BudgetTabContent.tsx | 68 ++++++++++++++++------ src/components/CategoryBudgetInputs.tsx | 8 +-- 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/src/components/BudgetCategoriesSection.tsx b/src/components/BudgetCategoriesSection.tsx index a0063c3..614a3b6 100644 --- a/src/components/BudgetCategoriesSection.tsx +++ b/src/components/BudgetCategoriesSection.tsx @@ -24,7 +24,7 @@ const BudgetCategoriesSection: React.FC = ({ const actualPercentage = category.total > 0 ? Math.round((category.current / category.total) * 100) : 0; - // 프로그레스 바용 퍼센트 (100%로 제한하지 않음) + // 프로그레스 바용 퍼센트 - 제한 없이 실제 퍼센트 표시 const displayPercentage = actualPercentage; // 예산이 얼마 남지 않은 경우 (10% 미만) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 35db633..5a4dffa 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -1,19 +1,23 @@ + import React, { useState, useEffect } from 'react'; -import { Plus, Wallet } from 'lucide-react'; +import { CirclePlus, Save, Check } from 'lucide-react'; import BudgetInputCard from './BudgetInputCard'; import { Button } from '@/components/ui/button'; import CategoryBudgetInputs from './CategoryBudgetInputs'; + interface BudgetData { targetAmount: number; spentAmount: number; remainingAmount: number; } + interface BudgetTabContentProps { data: BudgetData; formatCurrency: (amount: number) => string; calculatePercentage: (spent: number, target: number) => number; onSaveBudget: (amount: number, categoryBudgets?: Record) => void; } + const BudgetTabContent: React.FC = ({ data, formatCurrency, @@ -22,8 +26,10 @@ const BudgetTabContent: React.FC = ({ }) => { const [categoryBudgets, setCategoryBudgets] = useState>({}); const [showBudgetInput, setShowBudgetInput] = useState(false); + const spentAmount = data.spentAmount; const targetAmount = data.targetAmount; + // 실제 백분율 계산 (초과해도 실제 퍼센트로 표시) const actualPercentage = targetAmount > 0 ? Math.round(spentAmount / targetAmount * 100) : 0; const percentage = actualPercentage; @@ -40,6 +46,7 @@ const BudgetTabContent: React.FC = ({ // 남은 예산 또는 초과 예산 텍스트 및 금액 const budgetStatusText = isOverBudget ? '예산 초과: ' : '남은 예산: '; const budgetAmount = isOverBudget ? 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 => ({ @@ -47,6 +54,19 @@ const BudgetTabContent: React.FC = ({ [category]: numValue })); }; + + // 카테고리별 예산 합계 계산 + const calculateTotalBudget = () => { + return Object.values(categoryBudgets).reduce((sum, value) => sum + value, 0); + }; + + // 카테고리 예산 저장 + const handleSaveCategoryBudgets = () => { + const totalBudget = calculateTotalBudget(); + onSaveBudget(totalBudget, categoryBudgets); + setShowBudgetInput(false); + }; + return
{targetAmount > 0 ? <>
@@ -70,14 +90,24 @@ const BudgetTabContent: React.FC = ({
-
:
아직 예산이 설정되지 않았습니다
-
} @@ -85,27 +115,27 @@ const BudgetTabContent: React.FC = ({ {showBudgetInput &&
-

전체 예산 설정

-
- 0 ? targetAmount : ''} onChange={e => { - const value = e.target.value.replace(/[^0-9]/g, ''); - if (value) { - const amount = parseInt(value, 10); - onSaveBudget(amount, categoryBudgets); - } - }} /> - -
+

전체 예산: {formatCurrency(calculateTotalBudget())}

카테고리별 예산 설정

+ +
+ +
}
; }; -export default BudgetTabContent; \ No newline at end of file + +export default BudgetTabContent; diff --git a/src/components/CategoryBudgetInputs.tsx b/src/components/CategoryBudgetInputs.tsx index e77386d..deb850c 100644 --- a/src/components/CategoryBudgetInputs.tsx +++ b/src/components/CategoryBudgetInputs.tsx @@ -35,15 +35,15 @@ const CategoryBudgetInputs: React.FC = ({ }; return ( -
+
{EXPENSE_CATEGORIES.map(category => ( -
- +
+ handleInput(e, category)} placeholder="예산 입력" - className={`neuro-pressed transition-colors duration-300 ${isMobile ? 'w-[150px]' : 'max-w-[150px]'} text-xs`} + className={`neuro-pressed transition-colors duration-300 ${isMobile ? 'w-[150px]' : 'max-w-[150px]'}`} />
))} From 625a1f605ce76d698074d3eabe31e1f070fecd27 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:20:35 +0000 Subject: [PATCH 11/30] Enhance budget input display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Display existing values in budget input fields. - Remove recessed boxes from category inputs. - Add icons to 식비, 생활비, and 교통비 categories. --- src/components/BudgetTabContent.tsx | 19 +++++++++++++++++-- src/components/CategoryBudgetInputs.tsx | 11 +++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 5a4dffa..09e9151 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -67,6 +67,21 @@ const BudgetTabContent: React.FC = ({ setShowBudgetInput(false); }; + // 기존 카테고리 예산 불러오기 + useEffect(() => { + if (showBudgetInput) { + // 로컬 스토리지에서 카테고리 예산 불러오기 + try { + const storedCategoryBudgets = localStorage.getItem('categoryBudgets'); + if (storedCategoryBudgets) { + setCategoryBudgets(JSON.parse(storedCategoryBudgets)); + } + } catch (error) { + console.error('카테고리 예산 불러오기 오류:', error); + } + } + }, [showBudgetInput]); + return
{targetAmount > 0 ? <>
@@ -92,12 +107,12 @@ const BudgetTabContent: React.FC = ({
:
diff --git a/src/components/CategoryBudgetInputs.tsx b/src/components/CategoryBudgetInputs.tsx index deb850c..6a9b99b 100644 --- a/src/components/CategoryBudgetInputs.tsx +++ b/src/components/CategoryBudgetInputs.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Input } from '@/components/ui/input'; -import { EXPENSE_CATEGORIES } from '@/constants/categoryIcons'; +import { EXPENSE_CATEGORIES, categoryIcons } from '@/constants/categoryIcons'; import { useIsMobile } from '@/hooks/use-mobile'; interface CategoryBudgetInputsProps { @@ -37,13 +37,16 @@ const CategoryBudgetInputs: React.FC = ({ return (
{EXPENSE_CATEGORIES.map(category => ( -
- +
+
+ {categoryIcons[category]} + +
handleInput(e, category)} placeholder="예산 입력" - className={`neuro-pressed transition-colors duration-300 ${isMobile ? 'w-[150px]' : 'max-w-[150px]'}`} + className={`transition-colors duration-300 ${isMobile ? 'w-[150px]' : 'max-w-[150px]'}`} />
))} From 90a20df7b746aaa55936e4cb2304c49f2a7fb518 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:21:55 +0000 Subject: [PATCH 12/30] Move total budget display Move the total budget display in BudgetTabContent.tsx to be between the category budget inputs and the save button. --- src/components/BudgetTabContent.tsx | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 09e9151..70fe9e2 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -129,23 +129,26 @@ const BudgetTabContent: React.FC = ({ {showBudgetInput &&
-
-

전체 예산: {formatCurrency(calculateTotalBudget())}

-
-

카테고리별 예산 설정

-
- +
+
+

전체 예산:

+

{formatCurrency(calculateTotalBudget())}

+
+ +
+ +
From 6884b6846614ec46e7d78144a1e6b70695466074 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:23:27 +0000 Subject: [PATCH 13/30] Visual edit in Lovable Edited UI in Lovable --- src/components/BudgetTabContent.tsx | 33 ++++++----------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 70fe9e2..11d0b28 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -1,23 +1,19 @@ - import React, { useState, useEffect } from 'react'; import { CirclePlus, Save, Check } from 'lucide-react'; import BudgetInputCard from './BudgetInputCard'; import { Button } from '@/components/ui/button'; import CategoryBudgetInputs from './CategoryBudgetInputs'; - interface BudgetData { targetAmount: number; spentAmount: number; remainingAmount: number; } - interface BudgetTabContentProps { data: BudgetData; formatCurrency: (amount: number) => string; calculatePercentage: (spent: number, target: number) => number; onSaveBudget: (amount: number, categoryBudgets?: Record) => void; } - const BudgetTabContent: React.FC = ({ data, formatCurrency, @@ -26,10 +22,9 @@ const BudgetTabContent: React.FC = ({ }) => { const [categoryBudgets, setCategoryBudgets] = useState>({}); const [showBudgetInput, setShowBudgetInput] = useState(false); - const spentAmount = data.spentAmount; const targetAmount = data.targetAmount; - + // 실제 백분율 계산 (초과해도 실제 퍼센트로 표시) const actualPercentage = targetAmount > 0 ? Math.round(spentAmount / targetAmount * 100) : 0; const percentage = actualPercentage; @@ -46,7 +41,6 @@ const BudgetTabContent: React.FC = ({ // 남은 예산 또는 초과 예산 텍스트 및 금액 const budgetStatusText = isOverBudget ? '예산 초과: ' : '남은 예산: '; const budgetAmount = isOverBudget ? 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 => ({ @@ -81,7 +75,6 @@ const BudgetTabContent: React.FC = ({ } } }, [showBudgetInput]); - return
{targetAmount > 0 ? <>
@@ -105,10 +98,7 @@ const BudgetTabContent: React.FC = ({
-
:
아직 예산이 설정되지 않았습니다
- @@ -135,16 +121,12 @@ const BudgetTabContent: React.FC = ({
-

전체 예산:

-

{formatCurrency(calculateTotalBudget())}

+

전체 예산:

+

{formatCurrency(calculateTotalBudget())}

- @@ -155,5 +137,4 @@ const BudgetTabContent: React.FC = ({
}
; }; - -export default BudgetTabContent; +export default BudgetTabContent; \ No newline at end of file From 07f87d8ec0218ab2dfffdebf12890ba3f2226f1c 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:25:06 +0000 Subject: [PATCH 14/30] Refactor plus button style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Modified the style of the plus button before "예산 수정하기" - Removed the white circle and increased the size of the plus icon - Kept the same color and animation --- src/components/BudgetTabContent.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 11d0b28..6d4c86c 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -3,17 +3,20 @@ import { CirclePlus, Save, Check } from 'lucide-react'; import BudgetInputCard from './BudgetInputCard'; import { Button } from '@/components/ui/button'; import CategoryBudgetInputs from './CategoryBudgetInputs'; + interface BudgetData { targetAmount: number; spentAmount: number; remainingAmount: number; } + interface BudgetTabContentProps { data: BudgetData; formatCurrency: (amount: number) => string; calculatePercentage: (spent: number, target: number) => number; onSaveBudget: (amount: number, categoryBudgets?: Record) => void; } + const BudgetTabContent: React.FC = ({ data, formatCurrency, @@ -75,6 +78,7 @@ const BudgetTabContent: React.FC = ({ } } }, [showBudgetInput]); + return
{targetAmount > 0 ? <>
@@ -99,16 +103,14 @@ const BudgetTabContent: React.FC = ({
:
아직 예산이 설정되지 않았습니다
} @@ -137,4 +139,5 @@ const BudgetTabContent: React.FC = ({
}
; }; -export default BudgetTabContent; \ No newline at end of file + +export default BudgetTabContent; From 37937b38b382f775fa53fdcedb32be158400a968 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:25:55 +0000 Subject: [PATCH 15/30] Visual edit in Lovable Edited UI in Lovable --- src/components/BudgetTabContent.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 6d4c86c..16b2300 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -3,20 +3,17 @@ import { CirclePlus, Save, Check } from 'lucide-react'; import BudgetInputCard from './BudgetInputCard'; import { Button } from '@/components/ui/button'; import CategoryBudgetInputs from './CategoryBudgetInputs'; - interface BudgetData { targetAmount: number; spentAmount: number; remainingAmount: number; } - interface BudgetTabContentProps { data: BudgetData; formatCurrency: (amount: number) => string; calculatePercentage: (spent: number, target: number) => number; onSaveBudget: (amount: number, categoryBudgets?: Record) => void; } - const BudgetTabContent: React.FC = ({ data, formatCurrency, @@ -78,7 +75,6 @@ const BudgetTabContent: React.FC = ({ } } }, [showBudgetInput]); - return
{targetAmount > 0 ? <>
@@ -104,7 +100,7 @@ const BudgetTabContent: React.FC = ({
:
@@ -139,5 +135,4 @@ const BudgetTabContent: React.FC = ({
}
; }; - -export default BudgetTabContent; +export default BudgetTabContent; \ No newline at end of file From a1e9c6dda560a6fa2d9cc13a5949b4a4c72c1159 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:27:48 +0000 Subject: [PATCH 16/30] Update budget button text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change "예산 수정하기" to "예산 입력하기" when budget is empty and add animation. --- src/components/BudgetTabContent.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 16b2300..2f3a225 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -75,6 +75,11 @@ const BudgetTabContent: React.FC = ({ } } }, [showBudgetInput]); + + // 예산 여부에 따른 텍스트 결정 + const budgetButtonText = targetAmount > 0 ? "예산 수정하기" : "예산 입력하기"; + + return
{targetAmount > 0 ? <>
@@ -100,14 +105,14 @@ const BudgetTabContent: React.FC = ({
:
아직 예산이 설정되지 않았습니다
} @@ -135,4 +140,4 @@ const BudgetTabContent: React.FC = ({
}
; }; -export default BudgetTabContent; \ No newline at end of file +export default BudgetTabContent; From 5aa04cf79641f3a494e8e01652171434f36b2e1e 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:28:42 +0000 Subject: [PATCH 17/30] Visual edit in Lovable Edited UI in Lovable --- src/components/BudgetTabContent.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 2f3a225..784e546 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -75,11 +75,9 @@ const BudgetTabContent: React.FC = ({ } } }, [showBudgetInput]); - + // 예산 여부에 따른 텍스트 결정 const budgetButtonText = targetAmount > 0 ? "예산 수정하기" : "예산 입력하기"; - - return
{targetAmount > 0 ? <>
@@ -125,11 +123,11 @@ const BudgetTabContent: React.FC = ({

전체 예산:

-

{formatCurrency(calculateTotalBudget())}

+

{formatCurrency(calculateTotalBudget())}

- @@ -140,4 +138,4 @@ const BudgetTabContent: React.FC = ({
}
; }; -export default BudgetTabContent; +export default BudgetTabContent; \ No newline at end of file From 96297d67809413c7ca7268b401eaf130af43384d 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:30:07 +0000 Subject: [PATCH 18/30] Add category budget auto-calculation The category budgets are now automatically summed to calculate daily, weekly, and monthly budgets. --- src/components/BudgetTabContent.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index 784e546..efd2b81 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -118,6 +118,7 @@ const BudgetTabContent: React.FC = ({

카테고리별 예산 설정

+

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

@@ -138,4 +139,4 @@ const BudgetTabContent: React.FC = ({
}
; }; -export default BudgetTabContent; \ No newline at end of file +export default BudgetTabContent; From 097419c28cc6d551bd07cba1c55667654e1b63a3 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:31:49 +0000 Subject: [PATCH 19/30] Adjust progress bar color Make the color of the progress bar above the total budget slightly darker. --- src/components/BudgetTabContent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index efd2b81..d517456 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -121,7 +121,7 @@ const BudgetTabContent: React.FC = ({

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

-
+

전체 예산:

{formatCurrency(calculateTotalBudget())}

From 089aa4cb5af396df5b1f4456b6556098b513b384 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:33:37 +0000 Subject: [PATCH 20/30] Toggle budget input on click Modify the budget input to toggle open/close on button click. --- src/components/BudgetTabContent.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/BudgetTabContent.tsx b/src/components/BudgetTabContent.tsx index d517456..7bbf2c1 100644 --- a/src/components/BudgetTabContent.tsx +++ b/src/components/BudgetTabContent.tsx @@ -1,3 +1,4 @@ + import React, { useState, useEffect } from 'react'; import { CirclePlus, Save, Check } from 'lucide-react'; import BudgetInputCard from './BudgetInputCard'; @@ -76,6 +77,11 @@ const BudgetTabContent: React.FC = ({ } }, [showBudgetInput]); + // 예산 버튼 클릭 핸들러 - 토글 기능 추가 + const toggleBudgetInput = () => { + setShowBudgetInput(prev => !prev); + }; + // 예산 여부에 따른 텍스트 결정 const budgetButtonText = targetAmount > 0 ? "예산 수정하기" : "예산 입력하기"; return
@@ -101,14 +107,17 @@ const BudgetTabContent: React.FC = ({
-
:
아직 예산이 설정되지 않았습니다
- From b264ff7d68252203fd1aeaa0de7b38a85da31ea4 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:35:23 +0000 Subject: [PATCH 21/30] Visual edit in Lovable Edited UI in Lovable --- src/components/RecentTransactionsSection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/RecentTransactionsSection.tsx b/src/components/RecentTransactionsSection.tsx index 716db8f..b9bd6b8 100644 --- a/src/components/RecentTransactionsSection.tsx +++ b/src/components/RecentTransactionsSection.tsx @@ -50,7 +50,7 @@ const RecentTransactionsSection: React.FC = ({
-

{transaction.title}

+

{transaction.title}

{transaction.date}

From 02dfe8f73e71d2f79e506ec7edbbcd4b2e81e8a3 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:35:40 +0000 Subject: [PATCH 22/30] Visual edit in Lovable Edited UI in Lovable --- .../transaction/TransactionDetails.tsx | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/components/transaction/TransactionDetails.tsx b/src/components/transaction/TransactionDetails.tsx index 7537ce3..8815f20 100644 --- a/src/components/transaction/TransactionDetails.tsx +++ b/src/components/transaction/TransactionDetails.tsx @@ -1,18 +1,15 @@ - import React from 'react'; - interface TransactionDetailsProps { title: string; date: string; } - -const TransactionDetails: React.FC = ({ title, date }) => { - return ( -
-

{title || '제목 없음'}

+const TransactionDetails: React.FC = ({ + title, + date +}) => { + return
+

{title || '제목 없음'}

{date || '날짜 정보 없음'}

-
- ); +
; }; - -export default TransactionDetails; +export default TransactionDetails; \ No newline at end of file From 38fb16d845ae11adb30c00f73dbc9ac35b8d128f 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:36:00 +0000 Subject: [PATCH 23/30] Visual edit in Lovable Edited UI in Lovable --- src/pages/Settings.tsx | 85 +++++++++++------------------------------- 1 file changed, 22 insertions(+), 63 deletions(-) diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index 772a1c4..526bce0 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -1,4 +1,3 @@ - import React from 'react'; import { useNavigate } from 'react-router-dom'; import NavBar from '@/components/NavBar'; @@ -7,7 +6,6 @@ import { User, CreditCard, Bell, Lock, HelpCircle, LogOut, ChevronRight } from ' import { cn } from '@/lib/utils'; import { useAuth } from '@/contexts/auth'; import { useToast } from '@/hooks/useToast.wrapper'; - const SettingsOption = ({ icon: Icon, label, @@ -23,40 +21,35 @@ const SettingsOption = ({ color?: string; disabled?: boolean; }) => { - return
+ return
-

{label}

- {description &&

{description}

} +

{label}

+ {description &&

{description}

}
; }; - const Settings = () => { const navigate = useNavigate(); - const { user, signOut } = useAuth(); - const { toast } = useToast(); - + const { + user, + signOut + } = useAuth(); + const { + toast + } = useToast(); const handleLogout = async () => { await signOut(); navigate('/login'); }; - const handleClick = (path: string) => { navigate(path); }; - return
{/* Header */} @@ -65,8 +58,7 @@ const Settings = () => { {/* User Profile */}
- {user ? ( -
+ {user ?
@@ -78,16 +70,13 @@ const Settings = () => { {user.email}

-
- ) : ( -
+
:

로그인 필요

계정에 로그인하세요

-
- )} +
}
@@ -100,50 +89,21 @@ const Settings = () => { {/* Settings Options */}

계정

- user ? navigate('/profile') : navigate('/login')} - /> - user ? navigate('/payment-methods') : navigate('/login')} - /> - user ? navigate('/notifications') : navigate('/login')} - /> + user ? navigate('/profile') : navigate('/login')} /> + user ? navigate('/payment-methods') : navigate('/login')} /> + user ? navigate('/notifications') : navigate('/login')} />

앱 설정

- navigate('/security-privacy')} - /> - navigate('/help-support')} - /> + navigate('/security-privacy')} /> + navigate('/help-support')} />
- navigate('/login')} - /> + navigate('/login')} />
@@ -154,5 +114,4 @@ const Settings = () => {
; }; - -export default Settings; +export default Settings; \ No newline at end of file From b8f1762f2c8496f2f32ab8f7494334d057fcd1a6 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:36:19 +0000 Subject: [PATCH 24/30] Visual edit in Lovable Edited UI in Lovable --- src/components/transaction/TransactionDetails.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/transaction/TransactionDetails.tsx b/src/components/transaction/TransactionDetails.tsx index 8815f20..5602554 100644 --- a/src/components/transaction/TransactionDetails.tsx +++ b/src/components/transaction/TransactionDetails.tsx @@ -9,7 +9,7 @@ const TransactionDetails: React.FC = ({ }) => { return

{title || '제목 없음'}

-

{date || '날짜 정보 없음'}

+

{date || '날짜 정보 없음'}

; }; export default TransactionDetails; \ No newline at end of file From 3fb90343b2384825e3b31a921c2697da6d93a0da 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:38:51 +0000 Subject: [PATCH 25/30] Improve Sync Explanation Alert Make the text color in the SyncExplanation component's Alert component black. --- src/components/sync/SyncExplanation.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/sync/SyncExplanation.tsx b/src/components/sync/SyncExplanation.tsx index 0ea1cef..c2b0722 100644 --- a/src/components/sync/SyncExplanation.tsx +++ b/src/components/sync/SyncExplanation.tsx @@ -13,8 +13,8 @@ const SyncExplanation: React.FC = ({ enabled }) => { return ( - 동기화 작동 방식 - + 동기화 작동 방식 + 이 기능은 양방향 동기화입니다. 로그인 후 동기화를 켜면 서버 데이터와 로컬 데이터가 병합됩니다. 데이터 초기화 후에도 동기화 버튼을 누르면 서버에 저장된 데이터를 다시 불러옵니다. From 3ba935151faf106420df26ce9f8e50edff5e1ed4 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:43:11 +0000 Subject: [PATCH 26/30] Display remaining budget Replaced savings with remaining budget and indicated budget overruns. --- src/components/analytics/SummaryCards.tsx | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/components/analytics/SummaryCards.tsx b/src/components/analytics/SummaryCards.tsx index 9045046..6d39183 100644 --- a/src/components/analytics/SummaryCards.tsx +++ b/src/components/analytics/SummaryCards.tsx @@ -16,6 +16,10 @@ const SummaryCards: React.FC = ({ savingsPercentage }) => { const isMobile = useIsMobile(); + + // 남은 예산 계산 + const remainingBudget = totalBudget - totalExpense; + const isOverBudget = remainingBudget < 0; return (
@@ -40,11 +44,17 @@ const SummaryCards: React.FC = ({
-

저축

+

남은 예산

-

- {savingsPercentage}% -

+ {isOverBudget ? ( +

+ 예산 초과: {formatCurrency(Math.abs(remainingBudget))} +

+ ) : ( +

+ {formatCurrency(remainingBudget)} +

+ )}
); From 1072e2c57aced9a5c1a37d2c9a881f25c346b60d 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:45:35 +0000 Subject: [PATCH 27/30] Change remaining budget label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change "남은 예산" to "잔액" or "초과액" and update the piggy bank icon. --- src/components/analytics/SummaryCards.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/analytics/SummaryCards.tsx b/src/components/analytics/SummaryCards.tsx index 6d39183..e51fbfe 100644 --- a/src/components/analytics/SummaryCards.tsx +++ b/src/components/analytics/SummaryCards.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { Wallet, CreditCard, PiggyBank } from 'lucide-react'; +import { Wallet, CreditCard, Coins } from 'lucide-react'; import { formatCurrency } from '@/utils/formatters'; import { useIsMobile } from '@/hooks/use-mobile'; @@ -43,12 +43,12 @@ const SummaryCards: React.FC = ({
- -

남은 예산

+ +

잔액

{isOverBudget ? (

- 예산 초과: {formatCurrency(Math.abs(remainingBudget))} + 초과액: {formatCurrency(Math.abs(remainingBudget))}

) : (

From fd793998e47f7577243296f910581931f70c37c8 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:47:30 +0000 Subject: [PATCH 28/30] Improve monthly chart colors The monthly comparison chart now displays bars in yellow when expense is 90% of budget and in red when expense exceeds budget. --- .../analytics/MonthlyComparisonChart.tsx | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/components/analytics/MonthlyComparisonChart.tsx b/src/components/analytics/MonthlyComparisonChart.tsx index f7f962c..fc7219c 100644 --- a/src/components/analytics/MonthlyComparisonChart.tsx +++ b/src/components/analytics/MonthlyComparisonChart.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, Legend } from 'recharts'; +import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, Legend, Cell } from 'recharts'; import { formatCurrency } from '@/utils/formatters'; interface MonthlyData { @@ -47,6 +47,17 @@ const MonthlyComparisonChart: React.FC = ({ monthlyData.length > 0 && monthlyData.some(item => (item.budget > 0 || item.expense > 0)); + // 지출 색상 결정 함수 추가 + const getExpenseColor = (budget: number, expense: number) => { + if (budget === 0) return "#81c784"; // 예산이 0이면 기본 색상 + + const ratio = expense / budget; + + if (ratio > 1) return "#f44336"; // 빨간색 (예산 초과) + if (ratio >= 0.9) return "#ffeb3b"; // 노란색 (예산의 90% 이상) + return "#81c784"; // 기본 초록색 + }; + return (

{hasValidData ? ( @@ -64,7 +75,14 @@ const MonthlyComparisonChart: React.FC = ({ - + + {monthlyData.map((entry, index) => ( + + ))} + ) : ( From 10af4210fabb8f5a3f44b8fe21ccb7661d9f5c57 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:48:56 +0000 Subject: [PATCH 29/30] Remove chart hover effect Removed the background color change on hover in the monthly comparison chart. --- src/components/analytics/MonthlyComparisonChart.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/analytics/MonthlyComparisonChart.tsx b/src/components/analytics/MonthlyComparisonChart.tsx index fc7219c..d5acf02 100644 --- a/src/components/analytics/MonthlyComparisonChart.tsx +++ b/src/components/analytics/MonthlyComparisonChart.tsx @@ -72,7 +72,11 @@ const MonthlyComparisonChart: React.FC = ({ }}> - + From b223dff324329cbd6559fa7782da51061a802149 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:50:27 +0000 Subject: [PATCH 30/30] Visual edit in Lovable Edited UI in Lovable --- src/pages/Settings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index 526bce0..014767f 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -82,7 +82,7 @@ const Settings = () => { {/* Data Sync Settings */}
-

데이터 동기화

+