Refactor BudgetInputCard placement

Move BudgetInputCard to be inside BudgetProgressCard.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-15 02:26:15 +00:00
parent ae391e606b
commit 9ae296326a
2 changed files with 76 additions and 18 deletions

View File

@@ -1,6 +1,10 @@
import React from 'react';
import React, { useState } 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 { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
interface BudgetData {
targetAmount: number;
@@ -18,6 +22,7 @@ interface BudgetProgressCardProps {
setSelectedTab: (value: string) => void;
formatCurrency: (amount: number) => string;
calculatePercentage: (spent: number, target: number) => number;
onSaveBudget: (type: 'daily' | 'weekly' | 'monthly', amount: number) => void;
}
const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
@@ -25,7 +30,8 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
selectedTab,
setSelectedTab,
formatCurrency,
calculatePercentage
calculatePercentage,
onSaveBudget
}) => {
return (
<div className="neuro-card mb-6 overflow-hidden">
@@ -48,7 +54,8 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
<BudgetTabContent
data={budgetData.daily}
formatCurrency={formatCurrency}
calculatePercentage={calculatePercentage}
calculatePercentage={calculatePercentage}
onSaveBudget={(amount) => onSaveBudget('daily', amount)}
/>
</TabsContent>
@@ -56,7 +63,8 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
<BudgetTabContent
data={budgetData.weekly}
formatCurrency={formatCurrency}
calculatePercentage={calculatePercentage}
calculatePercentage={calculatePercentage}
onSaveBudget={(amount) => onSaveBudget('weekly', amount)}
/>
</TabsContent>
@@ -64,7 +72,8 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
<BudgetTabContent
data={budgetData.monthly}
formatCurrency={formatCurrency}
calculatePercentage={calculatePercentage}
calculatePercentage={calculatePercentage}
onSaveBudget={(amount) => onSaveBudget('monthly', amount)}
/>
</TabsContent>
</Tabs>
@@ -76,10 +85,35 @@ interface BudgetTabContentProps {
data: BudgetData;
formatCurrency: (amount: number) => string;
calculatePercentage: (spent: number, target: number) => number;
onSaveBudget: (amount: number) => void;
}
const BudgetTabContent: React.FC<BudgetTabContentProps> = ({ data, formatCurrency, calculatePercentage }) => {
const BudgetTabContent: React.FC<BudgetTabContentProps> = ({
data,
formatCurrency,
calculatePercentage,
onSaveBudget
}) => {
const percentage = calculatePercentage(data.spentAmount, data.targetAmount);
const [isOpen, setIsOpen] = useState(false);
const [budgetInput, setBudgetInput] = useState(data.targetAmount.toString());
const handleInputChange = (value: string) => {
// Remove all non-numeric characters
const numericValue = value.replace(/[^0-9]/g, '');
setBudgetInput(numericValue);
};
const handleSave = () => {
const amount = parseInt(budgetInput, 10) || 0;
onSaveBudget(amount);
setIsOpen(false);
};
// Format with commas for display
const formatWithCommas = (amount: string) => {
return amount.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
};
return (
<div className="space-y-4">
@@ -92,7 +126,9 @@ const BudgetTabContent: React.FC<BudgetTabContentProps> = ({ data, formatCurrenc
<div className="relative h-3 neuro-pressed overflow-hidden mt-2">
<div
style={{ width: `${percentage}%` }}
className="absolute top-0 left-0 h-full transition-all duration-700 ease-out bg-neuro-income"
className={`absolute top-0 left-0 h-full transition-all duration-700 ease-out ${
percentage >= 90 ? "bg-yellow-400" : "bg-neuro-income"
}`}
/>
</div>
@@ -107,6 +143,38 @@ const BudgetTabContent: React.FC<BudgetTabContentProps> = ({ data, formatCurrenc
<span className="text-gray-500 text-sm"> </span>
<span className="font-semibold text-neuro-income">{formatCurrency(data.remainingAmount)}</span>
</div>
<div className="pt-2 border-t border-gray-100">
<Collapsible open={isOpen} onOpenChange={setIsOpen}>
<CollapsibleTrigger className="flex items-center justify-between w-full px-1 py-2 text-left">
<span className="text-sm font-medium text-gray-600"> </span>
{isOpen ? (
<ChevronUp size={16} className="text-gray-500" />
) : (
<ChevronDown size={16} className="text-gray-500" />
)}
</CollapsibleTrigger>
<CollapsibleContent className="pt-2">
<div className="flex items-center space-x-2">
<Input
value={budgetInput}
onChange={(e) => handleInputChange(e.target.value)}
placeholder="목표 금액 입력"
className="neuro-pressed"
/>
<Button
onClick={handleSave}
size="icon"
className="neuro-flat text-slate-50 bg-slate-400 hover:bg-slate-300"
>
<Check size={18} />
</Button>
</div>
<p className="text-xs text-gray-500 mt-1"> : {formatWithCommas(budgetInput)}</p>
</CollapsibleContent>
</Collapsible>
</div>
</div>
);
};

View File

@@ -1,7 +1,6 @@
import React, { useState } from 'react';
import NavBar from '@/components/NavBar';
import BudgetInputCard from '@/components/BudgetInputCard';
import AddTransactionButton from '@/components/AddTransactionButton';
import Header from '@/components/Header';
import BudgetProgressCard from '@/components/BudgetProgressCard';
@@ -96,21 +95,12 @@ const Index = () => {
setSelectedTab={setSelectedTab}
formatCurrency={formatCurrency}
calculatePercentage={calculatePercentage}
onSaveBudget={handleBudgetGoalUpdate}
/>
{/* 지출 카테고리 */}
<BudgetCategoriesSection categories={categories} />
{/* 예산 입력 카드 */}
<BudgetInputCard
initialBudgets={{
daily: budgetData.daily.targetAmount,
weekly: budgetData.weekly.targetAmount,
monthly: budgetData.monthly.targetAmount
}}
onSave={handleBudgetGoalUpdate}
/>
{/* 최근 지출 */}
<RecentTransactionsSection transactions={transactions} />
</div>