Fix type errors in BudgetContext

Addresses type errors related to category budgets in BudgetContext and Index page. Specifically, ensures correct type assignment for category budget updates.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-15 10:54:24 +00:00
parent 53096ae26e
commit bbf0f75b66
4 changed files with 35 additions and 65 deletions

View File

@@ -2,6 +2,7 @@
import React from 'react'; import React from 'react';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import BudgetTabContent from './BudgetTabContent'; import BudgetTabContent from './BudgetTabContent';
import { BudgetPeriod } from '@/contexts/BudgetContext';
interface BudgetData { interface BudgetData {
targetAmount: number; targetAmount: number;
@@ -9,12 +10,6 @@ interface BudgetData {
remainingAmount: number; remainingAmount: number;
} }
interface CategoryBudget {
식비: number;
생활비: number;
교통비: number;
}
interface BudgetProgressCardProps { interface BudgetProgressCardProps {
budgetData: { budgetData: {
daily: BudgetData; daily: BudgetData;
@@ -25,7 +20,7 @@ interface BudgetProgressCardProps {
setSelectedTab: (value: string) => void; setSelectedTab: (value: string) => void;
formatCurrency: (amount: number) => string; formatCurrency: (amount: number) => string;
calculatePercentage: (spent: number, target: number) => number; calculatePercentage: (spent: number, target: number) => number;
onSaveBudget: (type: 'daily' | 'weekly' | 'monthly', amount: number, categoryBudgets?: CategoryBudget) => void; onSaveBudget: (type: BudgetPeriod, amount: number, newCategoryBudgets?: Record<string, number>) => void;
} }
const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({

View File

@@ -6,6 +6,7 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/component
import BudgetProgress from './BudgetProgress'; import BudgetProgress from './BudgetProgress';
import CategoryBudgetInputs from './CategoryBudgetInputs'; import CategoryBudgetInputs from './CategoryBudgetInputs';
import { toast } from '@/components/ui/use-toast'; import { toast } from '@/components/ui/use-toast';
import { EXPENSE_CATEGORIES } from '@/constants/categoryIcons';
interface BudgetData { interface BudgetData {
targetAmount: number; targetAmount: number;
@@ -13,17 +14,11 @@ interface BudgetData {
remainingAmount: number; remainingAmount: number;
} }
interface CategoryBudget {
식비: number;
생활비: number;
교통비: number;
}
interface BudgetTabContentProps { interface BudgetTabContentProps {
data: BudgetData; data: BudgetData;
formatCurrency: (amount: number) => string; formatCurrency: (amount: number) => string;
calculatePercentage: (spent: number, target: number) => number; calculatePercentage: (spent: number, target: number) => number;
onSaveBudget: (amount: number, categoryBudgets?: CategoryBudget) => void; onSaveBudget: (amount: number, categoryBudgets?: Record<string, number>) => void;
} }
const BudgetTabContent: React.FC<BudgetTabContentProps> = ({ const BudgetTabContent: React.FC<BudgetTabContentProps> = ({
@@ -40,13 +35,12 @@ const BudgetTabContent: React.FC<BudgetTabContentProps> = ({
const savedCategoryBudgets = localStorage.getItem('categoryBudgets'); const savedCategoryBudgets = localStorage.getItem('categoryBudgets');
const initialCategoryBudgets = savedCategoryBudgets const initialCategoryBudgets = savedCategoryBudgets
? JSON.parse(savedCategoryBudgets) ? JSON.parse(savedCategoryBudgets)
: { : EXPENSE_CATEGORIES.reduce((acc, category) => {
식비: Math.round(data.targetAmount * 0.4), acc[category] = Math.round(data.targetAmount / EXPENSE_CATEGORIES.length);
생활비: Math.round(data.targetAmount * 0.4), return acc;
교통비: Math.round(data.targetAmount * 0.2) }, {} as Record<string, number>);
};
const [categoryBudgets, setCategoryBudgets] = useState<CategoryBudget>(initialCategoryBudgets); const [categoryBudgets, setCategoryBudgets] = useState<Record<string, number>>(initialCategoryBudgets);
const handleInputChange = (value: string) => { const handleInputChange = (value: string) => {
// Remove all non-numeric characters // Remove all non-numeric characters
@@ -54,7 +48,7 @@ const BudgetTabContent: React.FC<BudgetTabContentProps> = ({
setBudgetInput(numericValue); setBudgetInput(numericValue);
}; };
const handleCategoryInputChange = (value: string, category: keyof CategoryBudget) => { const handleCategoryInputChange = (value: string, category: string) => {
// Remove all non-numeric characters // Remove all non-numeric characters
const numericValue = value.replace(/[^0-9]/g, ''); const numericValue = value.replace(/[^0-9]/g, '');
setCategoryBudgets(prev => ({ setCategoryBudgets(prev => ({

View File

@@ -1,16 +1,11 @@
import React from 'react'; import React from 'react';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { EXPENSE_CATEGORIES } from '@/constants/categoryIcons';
interface CategoryBudget {
식비: number;
생활비: number;
교통비: number;
}
interface CategoryBudgetInputsProps { interface CategoryBudgetInputsProps {
categoryBudgets: CategoryBudget; categoryBudgets: Record<string, number>;
handleCategoryInputChange: (value: string, category: keyof CategoryBudget) => void; handleCategoryInputChange: (value: string, category: string) => void;
} }
const CategoryBudgetInputs: React.FC<CategoryBudgetInputsProps> = ({ const CategoryBudgetInputs: React.FC<CategoryBudgetInputsProps> = ({
@@ -23,7 +18,7 @@ const CategoryBudgetInputs: React.FC<CategoryBudgetInputsProps> = ({
}; };
// Handle input with comma formatting // Handle input with comma formatting
const handleInput = (e: React.ChangeEvent<HTMLInputElement>, category: keyof CategoryBudget) => { const handleInput = (e: React.ChangeEvent<HTMLInputElement>, category: string) => {
// Remove all non-numeric characters before passing to parent handler // Remove all non-numeric characters before passing to parent handler
const numericValue = e.target.value.replace(/[^0-9]/g, ''); const numericValue = e.target.value.replace(/[^0-9]/g, '');
handleCategoryInputChange(numericValue, category); handleCategoryInputChange(numericValue, category);
@@ -31,32 +26,16 @@ const CategoryBudgetInputs: React.FC<CategoryBudgetInputsProps> = ({
return ( return (
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center justify-between"> {EXPENSE_CATEGORIES.map(category => (
<label className="text-sm text-gray-600"></label> <div key={category} className="flex items-center justify-between">
<Input <label className="text-sm text-gray-600">{category}</label>
value={formatWithCommas(categoryBudgets.)} <Input
onChange={(e) => handleInput(e, '식비')} value={formatWithCommas(categoryBudgets[category] || 0)}
className="neuro-pressed max-w-[150px]" onChange={(e) => handleInput(e, category)}
/> className="neuro-pressed max-w-[150px]"
</div> />
</div>
<div className="flex items-center justify-between"> ))}
<label className="text-sm text-gray-600"></label>
<Input
value={formatWithCommas(categoryBudgets.)}
onChange={(e) => handleInput(e, '생활비')}
className="neuro-pressed max-w-[150px]"
/>
</div>
<div className="flex items-center justify-between">
<label className="text-sm text-gray-600"></label>
<Input
value={formatWithCommas(categoryBudgets.)}
onChange={(e) => handleInput(e, '교통비')}
className="neuro-pressed max-w-[150px]"
/>
</div>
</div> </div>
); );
}; };

View File

@@ -1,7 +1,7 @@
import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'; import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { Transaction } from '@/components/TransactionCard'; import { Transaction } from '@/components/TransactionCard';
import { DEFAULT_CATEGORY_BUDGETS, DEFAULT_MONTHLY_BUDGET } from '@/constants/categoryIcons'; import { DEFAULT_CATEGORY_BUDGETS, DEFAULT_MONTHLY_BUDGET, EXPENSE_CATEGORIES } from '@/constants/categoryIcons';
import { toast } from '@/components/ui/use-toast'; import { toast } from '@/components/ui/use-toast';
// 예산 데이터 타입 정의 // 예산 데이터 타입 정의
@@ -44,7 +44,7 @@ const BudgetContext = createContext<BudgetContextType | undefined>(undefined);
export const BudgetProvider: React.FC<{ children: ReactNode }> = ({ children }) => { export const BudgetProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const [selectedTab, setSelectedTab] = useState<BudgetPeriod>("daily"); const [selectedTab, setSelectedTab] = useState<BudgetPeriod>("daily");
const [transactions, setTransactions] = useState<Transaction[]>([]); const [transactions, setTransactions] = useState<Transaction[]>([]);
const [categoryBudgets, setCategoryBudgets] = useState(DEFAULT_CATEGORY_BUDGETS); const [categoryBudgets, setCategoryBudgets] = useState<Record<string, number>>(DEFAULT_CATEGORY_BUDGETS);
const [budgetData, setBudgetData] = useState<BudgetData>({ const [budgetData, setBudgetData] = useState<BudgetData>({
daily: { daily: {
targetAmount: Math.round(DEFAULT_MONTHLY_BUDGET / 30), targetAmount: Math.round(DEFAULT_MONTHLY_BUDGET / 30),
@@ -195,9 +195,12 @@ export const BudgetProvider: React.FC<{ children: ReactNode }> = ({ children })
// 카테고리별 지출 계산 // 카테고리별 지출 계산
const getCategorySpending = () => { const getCategorySpending = () => {
const expenseTransactions = transactions.filter(t => t.type === 'expense'); const expenseTransactions = transactions.filter(t => t.type === 'expense');
const categorySpending: Record<string, number> = { ...Object.fromEntries( const categorySpending: Record<string, number> = {};
Object.keys(categoryBudgets).map(key => [key, 0])
)}; // 모든 카테고리에 대해 초기값 0 설정
EXPENSE_CATEGORIES.forEach(category => {
categorySpending[category] = 0;
});
expenseTransactions.forEach(t => { expenseTransactions.forEach(t => {
if (t.category in categorySpending) { if (t.category in categorySpending) {
@@ -227,11 +230,10 @@ export const BudgetProvider: React.FC<{ children: ReactNode }> = ({ children })
// 월간 총 예산이 변경되면 카테고리별 예산도 비례하여 조정 // 월간 총 예산이 변경되면 카테고리별 예산도 비례하여 조정
const ratio = amount / budgetData.monthly.targetAmount; const ratio = amount / budgetData.monthly.targetAmount;
const updatedCategoryBudgets = {...categoryBudgets}; const updatedCategoryBudgets: Record<string, number> = {};
Object.keys(updatedCategoryBudgets).forEach(category => { Object.keys(categoryBudgets).forEach(category => {
updatedCategoryBudgets[category as keyof typeof categoryBudgets] = updatedCategoryBudgets[category] = Math.round(categoryBudgets[category] * ratio);
Math.round(categoryBudgets[category as keyof typeof categoryBudgets] * ratio);
}); });
setCategoryBudgets(updatedCategoryBudgets); setCategoryBudgets(updatedCategoryBudgets);