Remove daily and weekly tabs

Removed the daily and weekly budget tabs from the budget progress card, leaving only the monthly tab.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-22 12:06:32 +00:00
parent 0bc53208b5
commit 8cda329feb
6 changed files with 57 additions and 187 deletions

View File

@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Check, ChevronDown, ChevronUp, Wallet } from 'lucide-react'; import { Check, ChevronDown, ChevronUp, Wallet } from 'lucide-react';
@@ -21,12 +21,9 @@ const BudgetInputCard: React.FC<BudgetGoalProps> = ({
onSave, onSave,
highlight = false highlight = false
}) => { }) => {
const [selectedTab, setSelectedTab] = useState<'daily' | 'weekly' | 'monthly'>('monthly'); const [budgetInput, setBudgetInput] = useState(
const [budgetInputs, setBudgetInputs] = useState({ initialBudgets.monthly > 0 ? initialBudgets.monthly.toString() : ''
daily: initialBudgets.daily > 0 ? initialBudgets.daily.toString() : '', );
weekly: initialBudgets.weekly > 0 ? initialBudgets.weekly.toString() : '',
monthly: initialBudgets.monthly > 0 ? initialBudgets.monthly.toString() : ''
});
const [isOpen, setIsOpen] = useState(highlight); const [isOpen, setIsOpen] = useState(highlight);
// Format with commas for display // Format with commas for display
@@ -39,33 +36,23 @@ const BudgetInputCard: React.FC<BudgetGoalProps> = ({
// 초기값 변경시 입력 필드 값 업데이트 // 초기값 변경시 입력 필드 값 업데이트
useEffect(() => { useEffect(() => {
console.log("BudgetInputCard - 초기 예산값 업데이트:", initialBudgets); console.log("BudgetInputCard - 초기 예산값 업데이트:", initialBudgets);
setBudgetInputs({ setBudgetInput(initialBudgets.monthly > 0 ? initialBudgets.monthly.toString() : '');
daily: initialBudgets.daily > 0 ? initialBudgets.daily.toString() : '',
weekly: initialBudgets.weekly > 0 ? initialBudgets.weekly.toString() : '',
monthly: initialBudgets.monthly > 0 ? initialBudgets.monthly.toString() : ''
});
}, [initialBudgets]); }, [initialBudgets]);
const handleInputChange = (value: string, type: 'daily' | 'weekly' | 'monthly') => { const handleInputChange = (value: 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, '');
setBudgetInputs(prev => ({ setBudgetInput(numericValue);
...prev,
[type]: numericValue
}));
}; };
const handleSave = () => { const handleSave = () => {
const amount = parseInt(budgetInputs[selectedTab].replace(/,/g, ''), 10) || 0; const amount = parseInt(budgetInput.replace(/,/g, ''), 10) || 0;
if (amount <= 0) { if (amount <= 0) {
return; // 0 이하의 금액은 저장하지 않음 return; // 0 이하의 금액은 저장하지 않음
} }
// 즉시 입력 필드를 업데이트하여 사용자에게 피드백 제공 // 즉시 입력 필드를 업데이트하여 사용자에게 피드백 제공
setBudgetInputs(prev => ({ setBudgetInput(amount.toString());
...prev,
[selectedTab]: amount.toString()
}));
// 즉시 콜랩시블을 닫아 사용자에게 완료 피드백 제공 // 즉시 콜랩시블을 닫아 사용자에게 완료 피드백 제공
setIsOpen(false); setIsOpen(false);
@@ -73,32 +60,27 @@ const BudgetInputCard: React.FC<BudgetGoalProps> = ({
// 예산 변경 시 수정 추적 시스템에 기록 // 예산 변경 시 수정 추적 시스템에 기록
try { try {
markBudgetAsModified(amount); markBudgetAsModified(amount);
console.log(`[예산 추적] ${selectedTab} 예산 변경 추적: ${amount}`); console.log(`[예산 추적] 월간 예산 변경 추적: ${amount}`);
} catch (error) { } catch (error) {
console.error('[예산 추적] 예산 변경 추적 실패:', error); console.error('[예산 추적] 예산 변경 추적 실패:', error);
} }
console.log(`BudgetInputCard - 저장 버튼 클릭: ${selectedTab} 예산 = ${amount}`); console.log(`BudgetInputCard - 저장 버튼 클릭: 월간 예산 = ${amount}`);
// 주간 탭에서 월간 예산으로 동기화하는 경우 // 예산 저장 (항상 monthly로 저장)
if (selectedTab === 'weekly') { onSave('monthly', amount);
console.log(`주간 탭에서 설정된 ${amount}원을 월간 예산으로 직접 설정`);
}
// 예산 저장
onSave(selectedTab, amount);
}; };
// 비어있으면 빈 문자열을, 그렇지 않으면 포맷팅된 문자열을 반환 // 비어있으면 빈 문자열을, 그렇지 않으면 포맷팅된 문자열을 반환
const getDisplayValue = (type: 'daily' | 'weekly' | 'monthly') => { const getDisplayValue = () => {
return budgetInputs[type] === '' ? '' : formatWithCommas(budgetInputs[type]); return budgetInput === '' ? '' : formatWithCommas(budgetInput);
}; };
// 금액을 표시할 때 0원이면 '설정되지 않음'으로 표시 // 금액을 표시할 때 0원이면 '설정되지 않음'으로 표시
const getGoalDisplayText = (type: 'daily' | 'weekly' | 'monthly') => { const getGoalDisplayText = () => {
const amount = parseInt(budgetInputs[type].replace(/,/g, ''), 10) || 0; const amount = parseInt(budgetInput.replace(/,/g, ''), 10) || 0;
if (amount === 0) return '설정되지 않음'; if (amount === 0) return '설정되지 않음';
return formatWithCommas(budgetInputs[type]) + '원'; return formatWithCommas(budgetInput) + '원';
}; };
return ( return (
@@ -110,7 +92,7 @@ const BudgetInputCard: React.FC<BudgetGoalProps> = ({
<CollapsibleTrigger className="flex items-center justify-between w-full p-4"> <CollapsibleTrigger className="flex items-center justify-between w-full p-4">
<span className={`text-sm font-medium flex items-center ${highlight ? 'text-neuro-income' : ''}`}> <span className={`text-sm font-medium flex items-center ${highlight ? 'text-neuro-income' : ''}`}>
{highlight && <Wallet size={18} className="mr-2 animate-pulse" />} {highlight && <Wallet size={18} className="mr-2 animate-pulse" />}
</span> </span>
{isOpen ? ( {isOpen ? (
<ChevronUp size={18} className="text-gray-500" /> <ChevronUp size={18} className="text-gray-500" />
@@ -120,64 +102,22 @@ const BudgetInputCard: React.FC<BudgetGoalProps> = ({
</CollapsibleTrigger> </CollapsibleTrigger>
<CollapsibleContent className="px-4 pb-4"> <CollapsibleContent className="px-4 pb-4">
<Tabs defaultValue="monthly" value={selectedTab} onValueChange={value => setSelectedTab(value as 'daily' | 'weekly' | 'monthly')} className="w-full"> <div className="space-y-4 mt-0">
<TabsList className="grid grid-cols-3 mb-4 bg-transparent"> <div className="flex items-center space-x-2">
<TabsTrigger value="daily" className="data-[state=active]:shadow-neuro-pressed data-[state=active]:bg-transparent"> </TabsTrigger> <Input
<TabsTrigger value="weekly" className="data-[state=active]:shadow-neuro-pressed data-[state=active]:bg-transparent"> </TabsTrigger> value={getDisplayValue()}
<TabsTrigger value="monthly" className="data-[state=active]:shadow-neuro-pressed data-[state=active]:bg-transparent"> </TabsTrigger> onChange={e => handleInputChange(e.target.value)}
</TabsList> placeholder="목표 금액 입력"
className="neuro-pressed"
<TabsContent value="daily" className="space-y-4 mt-0"> />
<div className="flex items-center space-x-2"> <Button onClick={handleSave} size="icon" className={`neuro-flat ${highlight ? 'bg-neuro-income hover:bg-neuro-income/90' : 'bg-slate-400 hover:bg-slate-300'} text-white`}>
<Input <Check size={18} />
value={getDisplayValue('daily')} </Button>
onChange={e => handleInputChange(e.target.value, 'daily')} </div>
placeholder="목표 금액 입력" <p className="text-xs text-gray-500">
className="neuro-pressed" : {getGoalDisplayText()}
/> </p>
<Button onClick={handleSave} size="icon" className={`neuro-flat ${highlight ? 'bg-neuro-income hover:bg-neuro-income/90' : 'bg-slate-400 hover:bg-slate-300'} text-white`}> </div>
<Check size={18} />
</Button>
</div>
<p className="text-xs text-gray-500">
: {getGoalDisplayText('daily')}
</p>
</TabsContent>
<TabsContent value="weekly" className="space-y-4 mt-0">
<div className="flex items-center space-x-2">
<Input
value={getDisplayValue('weekly')}
onChange={e => handleInputChange(e.target.value, 'weekly')}
placeholder="목표 금액 입력"
className="neuro-pressed"
/>
<Button onClick={handleSave} size="icon" className={`neuro-flat ${highlight ? 'bg-neuro-income hover:bg-neuro-income/90' : 'bg-slate-400 hover:bg-slate-300'} text-white`}>
<Check size={18} />
</Button>
</div>
<p className="text-xs text-gray-500">
: {getGoalDisplayText('weekly')}
</p>
</TabsContent>
<TabsContent value="monthly" className="space-y-4 mt-0">
<div className="flex items-center space-x-2">
<Input
value={getDisplayValue('monthly')}
onChange={e => handleInputChange(e.target.value, 'monthly')}
placeholder="목표 금액 입력"
className="neuro-pressed"
/>
<Button onClick={handleSave} size="icon" className={`neuro-flat ${highlight ? 'bg-neuro-income hover:bg-neuro-income/90' : 'bg-slate-400 hover:bg-slate-300'} text-white`}>
<Check size={18} />
</Button>
</div>
<p className="text-xs text-gray-500">
: {getGoalDisplayText('monthly')}
</p>
</TabsContent>
</Tabs>
</CollapsibleContent> </CollapsibleContent>
</Collapsible> </Collapsible>
); );

View File

@@ -1,6 +1,5 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import BudgetTabContent from './BudgetTabContent'; import BudgetTabContent from './BudgetTabContent';
import { BudgetPeriod } from '@/contexts/budget/BudgetContext'; import { BudgetPeriod } from '@/contexts/budget/BudgetContext';
@@ -38,8 +37,6 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
useEffect(() => { useEffect(() => {
console.log("BudgetProgressCard 데이터 업데이트 - 예산 데이터:", budgetData); console.log("BudgetProgressCard 데이터 업데이트 - 예산 데이터:", budgetData);
console.log("월간 예산:", budgetData.monthly.targetAmount); console.log("월간 예산:", budgetData.monthly.targetAmount);
console.log("주간 예산:", budgetData.weekly.targetAmount);
console.log("일일 예산:", budgetData.daily.targetAmount);
setLocalBudgetData(budgetData); setLocalBudgetData(budgetData);
// 지연 작업으로 이벤트 발생 (컴포넌트 마운트 후 데이터 갱신) // 지연 작업으로 이벤트 발생 (컴포넌트 마운트 후 데이터 갱신)
@@ -52,9 +49,9 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
// 초기 탭 설정을 위한 효과 // 초기 탭 설정을 위한 효과
useEffect(() => { useEffect(() => {
if (!selectedTab) { if (!selectedTab || selectedTab !== "monthly") {
console.log("초기 탭 설정: daily"); console.log("초기 탭 설정: monthly");
setSelectedTab('daily'); setSelectedTab('monthly');
} }
}, []); }, []);
@@ -68,78 +65,21 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
return () => window.removeEventListener('budgetDataUpdated', handleBudgetDataUpdated); return () => window.removeEventListener('budgetDataUpdated', handleBudgetDataUpdated);
}, []); }, []);
// 탭 변경 처리 // 월간 예산 설정 여부 계산
const handleTabChange = (value: string) => {
console.log(`탭 변경: ${value}, 현재 예산 데이터:`, {
daily: budgetData.daily.targetAmount,
weekly: budgetData.weekly.targetAmount,
monthly: budgetData.monthly.targetAmount
});
// 탭 값 업데이트
setSelectedTab(value);
};
// 각 탭에 대한 현재 예산 설정 여부 계산
const isDailyBudgetSet = budgetData.daily.targetAmount > 0;
const isWeeklyBudgetSet = budgetData.weekly.targetAmount > 0;
const isMonthlyBudgetSet = budgetData.monthly.targetAmount > 0; const isMonthlyBudgetSet = budgetData.monthly.targetAmount > 0;
console.log(`BudgetProgressCard 상태: 일=${isDailyBudgetSet}, 주=${isWeeklyBudgetSet}, 월=${isMonthlyBudgetSet}`); console.log(`BudgetProgressCard 상태: 월=${isMonthlyBudgetSet}`);
return ( return (
<div className="neuro-card mb-6 overflow-hidden w-full"> <div className="neuro-card mb-6 overflow-hidden w-full">
<Tabs defaultValue="daily" value={selectedTab} onValueChange={handleTabChange} className="w-full"> <div className="text-sm text-gray-600 mb-2 px-3 pt-3"> / </div>
<TabsList className="grid grid-cols-3 mb-4 bg-transparent">
<TabsTrigger
value="daily"
className="data-[state=active]:shadow-[inset_4px_4px_8px_rgba(209,217,230,0.9),inset_-4px_-4px_8px_rgba(255,255,255,0.9)] data-[state=active]:bg-transparent data-[state=active]:font-medium transition-all duration-200"
>
</TabsTrigger>
<TabsTrigger
value="weekly"
className="data-[state=active]:shadow-[inset_4px_4px_8px_rgba(209,217,230,0.9),inset_-4px_-4px_8px_rgba(255,255,255,0.9)] data-[state=active]:bg-transparent data-[state=active]:font-medium transition-all duration-200"
>
</TabsTrigger>
<TabsTrigger
value="monthly"
className="data-[state=active]:shadow-[inset_4px_4px_8px_rgba(209,217,230,0.9),inset_-4px_-4px_8px_rgba(255,255,255,0.9)] data-[state=active]:bg-transparent data-[state=active]:font-medium transition-all duration-200"
>
</TabsTrigger>
</TabsList>
<div className="text-sm text-gray-600 mb-2 px-1"> / </div> <BudgetTabContent
data={budgetData.monthly}
<TabsContent value="daily" className="space-y-4 mt-0"> formatCurrency={formatCurrency}
<BudgetTabContent calculatePercentage={calculatePercentage}
data={budgetData.daily} onSaveBudget={(amount, categoryBudgets) => onSaveBudget('monthly', amount, categoryBudgets)}
formatCurrency={formatCurrency} />
calculatePercentage={calculatePercentage}
onSaveBudget={(amount, categoryBudgets) => onSaveBudget('daily', amount, categoryBudgets)}
/>
</TabsContent>
<TabsContent value="weekly" className="space-y-4 mt-0">
<BudgetTabContent
data={budgetData.weekly}
formatCurrency={formatCurrency}
calculatePercentage={calculatePercentage}
onSaveBudget={(amount, categoryBudgets) => onSaveBudget('weekly', amount, categoryBudgets)}
/>
</TabsContent>
<TabsContent value="monthly" className="space-y-4 mt-0">
<BudgetTabContent
data={budgetData.monthly}
formatCurrency={formatCurrency}
calculatePercentage={calculatePercentage}
onSaveBudget={(amount, categoryBudgets) => onSaveBudget('monthly', amount, categoryBudgets)}
/>
</TabsContent>
</Tabs>
</div> </div>
); );
}; };

View File

@@ -48,14 +48,14 @@ const BudgetTabContent: React.FC<BudgetTabContentProps> = ({
onSaveBudget onSaveBudget
}); });
// 월간 예산 모드를 명시적으로 로깅 // 월간 예산 모드 로깅
React.useEffect(() => { React.useEffect(() => {
console.log('BudgetTabContent 렌더링: 월간 예산 모드'); console.log('BudgetTabContent 렌더링: 월간 예산');
console.log('현재 예산 데이터:', data); console.log('현재 예산 데이터:', data);
}, [data]); }, [data]);
return ( return (
<div> <div className="px-3 pb-3">
{isBudgetSet ? ( {isBudgetSet ? (
<> <>
<BudgetHeader <BudgetHeader

View File

@@ -1,3 +1,4 @@
import React from 'react'; import React from 'react';
import BudgetProgressCard from '@/components/BudgetProgressCard'; import BudgetProgressCard from '@/components/BudgetProgressCard';
import BudgetCategoriesSection from '@/components/BudgetCategoriesSection'; import BudgetCategoriesSection from '@/components/BudgetCategoriesSection';
@@ -56,7 +57,7 @@ const HomeContent: React.FC<HomeContentProps> = ({
)} )}
{/* 목표 진행 상황 */} {/* 목표 진행 상황 */}
<h2 className="text-lg font-semibold mb-2 mt-4"> </h2> <h2 className="text-lg font-semibold mb-2 mt-4"> </h2>
<BudgetProgressCard <BudgetProgressCard
budgetData={budgetData} budgetData={budgetData}
selectedTab={selectedTab} selectedTab={selectedTab}

View File

@@ -12,7 +12,7 @@ export const useBudgetState = () => {
console.log('초기 예산 데이터 로드:', initialBudgetData); console.log('초기 예산 데이터 로드:', initialBudgetData);
const [budgetData, setBudgetData] = useState<BudgetData>(initialBudgetData); const [budgetData, setBudgetData] = useState<BudgetData>(initialBudgetData);
const [selectedTab, setSelectedTab] = useState<BudgetPeriod>("daily"); // 초기값은 daily const [selectedTab, setSelectedTab] = useState<BudgetPeriod>("monthly"); // 초기값은 monthly로 변경
const [isInitialized, setIsInitialized] = useState(false); const [isInitialized, setIsInitialized] = useState(false);
const [lastUpdateTime, setLastUpdateTime] = useState(0); const [lastUpdateTime, setLastUpdateTime] = useState(0);

View File

@@ -17,20 +17,9 @@ export const useExtendedBudgetUpdate = (
) => { ) => {
console.log('확장 예산 업데이트 시작:', type, amount, newCategoryBudgets); console.log('확장 예산 업데이트 시작:', type, amount, newCategoryBudgets);
// 항상 입력값을 월간 기준으로 변환하여 예산 업데이트 // 타입에 상관없이 항상 월간으로 처리
let monthlyAmount = amount; console.log(`예산 업데이트: 입력 금액=${amount}, 항상 월간으로 설정`);
handleBudgetUpdate('monthly', amount);
if (type === 'weekly') {
// 주간 예산을 월간으로 변환 (4.345주/월)
monthlyAmount = Math.round(amount * 4.345);
} else if (type === 'daily') {
// 일일 예산을 월간으로 변환 (30일/월)
monthlyAmount = Math.round(amount * 30);
}
// 월간 기준으로 예산 업데이트
console.log(`예산 업데이트: 원래 타입=${type}, 금액=${amount}, 변환된 월간 금액=${monthlyAmount}`);
handleBudgetUpdate('monthly', monthlyAmount);
// 카테고리 예산 업데이트 (제공된 경우) // 카테고리 예산 업데이트 (제공된 경우)
if (newCategoryBudgets) { if (newCategoryBudgets) {