Files
zellyy-finance/src/pages/Index.tsx
gpt-engineer-app[bot] a5fac97a95 Implement budget input per category
Implement budget input fields for each category in the monthly budget settings, and automatically calculate and populate daily, weekly, and monthly budgets based on the sum of the category inputs.
2025-03-15 04:02:43 +00:00

173 lines
5.5 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import NavBar from '@/components/NavBar';
import AddTransactionButton from '@/components/AddTransactionButton';
import Header from '@/components/Header';
import BudgetProgressCard from '@/components/BudgetProgressCard';
import BudgetCategoriesSection from '@/components/BudgetCategoriesSection';
import RecentTransactionsSection from '@/components/RecentTransactionsSection';
import { formatCurrency, calculatePercentage } from '@/utils/formatters';
import { toast } from '@/components/ui/use-toast';
import { Transaction } from '@/components/TransactionCard';
const Index = () => {
const [selectedTab, setSelectedTab] = useState("daily");
// Sample data - in a real app, this would come from a data source
const transactions: Transaction[] = [{
id: '1',
title: '식료품 구매',
amount: 25000,
date: '오늘, 12:30 PM',
category: '식비',
type: 'expense'
}, {
id: '2',
title: '주유소',
amount: 50000,
date: '어제, 3:45 PM',
category: '교통비',
type: 'expense'
}, {
id: '3',
title: '월급',
amount: 2500000,
date: '2일전, 9:00 AM',
category: 'income',
type: 'income'
}];
// 카테고리별 예산
const [categoryBudgets, setCategoryBudgets] = useState({
식비: 400000,
생활비: 600000,
교통비: 200000
});
// 예산 데이터 - 월간 예산을 기반으로 일일, 주간 계산
const [budgetData, setBudgetData] = useState({
daily: {
targetAmount: 0,
spentAmount: 15000,
remainingAmount: 0
},
weekly: {
targetAmount: 0,
spentAmount: 120000,
remainingAmount: 0
},
monthly: {
targetAmount: 0,
spentAmount: 750000,
remainingAmount: 0
}
});
// 초기 로드 및 카테고리 예산 변경 시 전체 예산 업데이트
useEffect(() => {
const totalMonthlyBudget = Object.values(categoryBudgets).reduce((sum, value) => sum + value, 0);
const totalDailyBudget = Math.round(totalMonthlyBudget / 30); // 월간을 일일로 변환
const totalWeeklyBudget = Math.round(totalMonthlyBudget / 4.3); // 월간을 주간으로 변환
setBudgetData({
daily: {
targetAmount: totalDailyBudget,
spentAmount: budgetData.daily.spentAmount,
remainingAmount: totalDailyBudget - budgetData.daily.spentAmount
},
weekly: {
targetAmount: totalWeeklyBudget,
spentAmount: budgetData.weekly.spentAmount,
remainingAmount: totalWeeklyBudget - budgetData.weekly.spentAmount
},
monthly: {
targetAmount: totalMonthlyBudget,
spentAmount: budgetData.monthly.spentAmount,
remainingAmount: totalMonthlyBudget - budgetData.monthly.spentAmount
}
});
}, [categoryBudgets]);
// 카테고리 업데이트
const categories = [
{ title: '식비', current: budgetData.monthly.spentAmount * 0.32, total: categoryBudgets.식비 },
{ title: '생활비', current: budgetData.monthly.spentAmount * 0.47, total: categoryBudgets.생활비 },
{ title: '교통비', current: budgetData.monthly.spentAmount * 0.21, total: categoryBudgets.교통비 },
];
// 예산 목표 업데이트 함수
const handleBudgetGoalUpdate = (type: 'daily' | 'weekly' | 'monthly', amount: number) => {
// 월간 예산을 업데이트하고 일일, 주간도 자동 계산
if (type === 'monthly') {
const dailyAmount = Math.round(amount / 30);
const weeklyAmount = Math.round(amount / 4.3);
setBudgetData(prev => ({
daily: {
targetAmount: dailyAmount,
spentAmount: prev.daily.spentAmount,
remainingAmount: Math.max(0, dailyAmount - prev.daily.spentAmount)
},
weekly: {
targetAmount: weeklyAmount,
spentAmount: prev.weekly.spentAmount,
remainingAmount: Math.max(0, weeklyAmount - prev.weekly.spentAmount)
},
monthly: {
targetAmount: amount,
spentAmount: prev.monthly.spentAmount,
remainingAmount: Math.max(0, amount - prev.monthly.spentAmount)
}
}));
} else {
// 일일이나 주간 예산이 직접 업데이트되는 경우
setBudgetData(prev => {
const remainingAmount = Math.max(0, amount - prev[type].spentAmount);
return {
...prev,
[type]: {
...prev[type],
targetAmount: amount,
remainingAmount: remainingAmount
}
};
});
}
toast({
title: "목표 업데이트 완료",
description: `${type === 'daily' ? '일일' : type === 'weekly' ? '주간' : '월간'} 목표가 ${amount.toLocaleString()}원으로 설정되었습니다.`
});
};
return (
<div className="min-h-screen bg-neuro-background pb-24">
<div className="max-w-md mx-auto px-6">
<Header />
{/* 목표 진행 상황 */}
<h2 className="text-lg font-semibold mb-3"> </h2>
<BudgetProgressCard
budgetData={budgetData}
selectedTab={selectedTab}
setSelectedTab={setSelectedTab}
formatCurrency={formatCurrency}
calculatePercentage={calculatePercentage}
onSaveBudget={handleBudgetGoalUpdate}
/>
{/* 지출 카테고리 */}
<BudgetCategoriesSection categories={categories} />
{/* 최근 지출 */}
<RecentTransactionsSection transactions={transactions} />
</div>
<AddTransactionButton />
<NavBar />
</div>
);
};
export default Index;