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:
@@ -1,5 +1,5 @@
|
||||
|
||||
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, Wallet } from 'lucide-react';
|
||||
@@ -21,12 +21,9 @@ const BudgetInputCard: React.FC<BudgetGoalProps> = ({
|
||||
onSave,
|
||||
highlight = false
|
||||
}) => {
|
||||
const [selectedTab, setSelectedTab] = useState<'daily' | 'weekly' | 'monthly'>('monthly');
|
||||
const [budgetInputs, setBudgetInputs] = useState({
|
||||
daily: initialBudgets.daily > 0 ? initialBudgets.daily.toString() : '',
|
||||
weekly: initialBudgets.weekly > 0 ? initialBudgets.weekly.toString() : '',
|
||||
monthly: initialBudgets.monthly > 0 ? initialBudgets.monthly.toString() : ''
|
||||
});
|
||||
const [budgetInput, setBudgetInput] = useState(
|
||||
initialBudgets.monthly > 0 ? initialBudgets.monthly.toString() : ''
|
||||
);
|
||||
const [isOpen, setIsOpen] = useState(highlight);
|
||||
|
||||
// Format with commas for display
|
||||
@@ -39,33 +36,23 @@ const BudgetInputCard: React.FC<BudgetGoalProps> = ({
|
||||
// 초기값 변경시 입력 필드 값 업데이트
|
||||
useEffect(() => {
|
||||
console.log("BudgetInputCard - 초기 예산값 업데이트:", initialBudgets);
|
||||
setBudgetInputs({
|
||||
daily: initialBudgets.daily > 0 ? initialBudgets.daily.toString() : '',
|
||||
weekly: initialBudgets.weekly > 0 ? initialBudgets.weekly.toString() : '',
|
||||
monthly: initialBudgets.monthly > 0 ? initialBudgets.monthly.toString() : ''
|
||||
});
|
||||
setBudgetInput(initialBudgets.monthly > 0 ? initialBudgets.monthly.toString() : '');
|
||||
}, [initialBudgets]);
|
||||
|
||||
const handleInputChange = (value: string, type: 'daily' | 'weekly' | 'monthly') => {
|
||||
const handleInputChange = (value: string) => {
|
||||
// Remove all non-numeric characters
|
||||
const numericValue = value.replace(/[^0-9]/g, '');
|
||||
setBudgetInputs(prev => ({
|
||||
...prev,
|
||||
[type]: numericValue
|
||||
}));
|
||||
setBudgetInput(numericValue);
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
const amount = parseInt(budgetInputs[selectedTab].replace(/,/g, ''), 10) || 0;
|
||||
const amount = parseInt(budgetInput.replace(/,/g, ''), 10) || 0;
|
||||
if (amount <= 0) {
|
||||
return; // 0 이하의 금액은 저장하지 않음
|
||||
}
|
||||
|
||||
// 즉시 입력 필드를 업데이트하여 사용자에게 피드백 제공
|
||||
setBudgetInputs(prev => ({
|
||||
...prev,
|
||||
[selectedTab]: amount.toString()
|
||||
}));
|
||||
setBudgetInput(amount.toString());
|
||||
|
||||
// 즉시 콜랩시블을 닫아 사용자에게 완료 피드백 제공
|
||||
setIsOpen(false);
|
||||
@@ -73,32 +60,27 @@ const BudgetInputCard: React.FC<BudgetGoalProps> = ({
|
||||
// 예산 변경 시 수정 추적 시스템에 기록
|
||||
try {
|
||||
markBudgetAsModified(amount);
|
||||
console.log(`[예산 추적] ${selectedTab} 예산 변경 추적: ${amount}원`);
|
||||
console.log(`[예산 추적] 월간 예산 변경 추적: ${amount}원`);
|
||||
} catch (error) {
|
||||
console.error('[예산 추적] 예산 변경 추적 실패:', error);
|
||||
}
|
||||
|
||||
console.log(`BudgetInputCard - 저장 버튼 클릭: ${selectedTab} 예산 = ${amount}원`);
|
||||
console.log(`BudgetInputCard - 저장 버튼 클릭: 월간 예산 = ${amount}원`);
|
||||
|
||||
// 주간 탭에서 월간 예산으로 동기화하는 경우
|
||||
if (selectedTab === 'weekly') {
|
||||
console.log(`주간 탭에서 설정된 ${amount}원을 월간 예산으로 직접 설정`);
|
||||
}
|
||||
|
||||
// 예산 저장
|
||||
onSave(selectedTab, amount);
|
||||
// 예산 저장 (항상 monthly로 저장)
|
||||
onSave('monthly', amount);
|
||||
};
|
||||
|
||||
// 비어있으면 빈 문자열을, 그렇지 않으면 포맷팅된 문자열을 반환
|
||||
const getDisplayValue = (type: 'daily' | 'weekly' | 'monthly') => {
|
||||
return budgetInputs[type] === '' ? '' : formatWithCommas(budgetInputs[type]);
|
||||
const getDisplayValue = () => {
|
||||
return budgetInput === '' ? '' : formatWithCommas(budgetInput);
|
||||
};
|
||||
|
||||
// 금액을 표시할 때 0원이면 '설정되지 않음'으로 표시
|
||||
const getGoalDisplayText = (type: 'daily' | 'weekly' | 'monthly') => {
|
||||
const amount = parseInt(budgetInputs[type].replace(/,/g, ''), 10) || 0;
|
||||
const getGoalDisplayText = () => {
|
||||
const amount = parseInt(budgetInput.replace(/,/g, ''), 10) || 0;
|
||||
if (amount === 0) return '설정되지 않음';
|
||||
return formatWithCommas(budgetInputs[type]) + '원';
|
||||
return formatWithCommas(budgetInput) + '원';
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -110,7 +92,7 @@ const BudgetInputCard: React.FC<BudgetGoalProps> = ({
|
||||
<CollapsibleTrigger className="flex items-center justify-between w-full p-4">
|
||||
<span className={`text-sm font-medium flex items-center ${highlight ? 'text-neuro-income' : ''}`}>
|
||||
{highlight && <Wallet size={18} className="mr-2 animate-pulse" />}
|
||||
예산 목표 설정하기
|
||||
월간 예산 설정하기
|
||||
</span>
|
||||
{isOpen ? (
|
||||
<ChevronUp size={18} className="text-gray-500" />
|
||||
@@ -120,64 +102,22 @@ const BudgetInputCard: React.FC<BudgetGoalProps> = ({
|
||||
</CollapsibleTrigger>
|
||||
|
||||
<CollapsibleContent className="px-4 pb-4">
|
||||
<Tabs defaultValue="monthly" value={selectedTab} onValueChange={value => setSelectedTab(value as 'daily' | 'weekly' | 'monthly')} className="w-full">
|
||||
<TabsList className="grid grid-cols-3 mb-4 bg-transparent">
|
||||
<TabsTrigger value="daily" className="data-[state=active]:shadow-neuro-pressed data-[state=active]:bg-transparent">일일 예산</TabsTrigger>
|
||||
<TabsTrigger value="weekly" className="data-[state=active]:shadow-neuro-pressed data-[state=active]:bg-transparent">주간 예산</TabsTrigger>
|
||||
<TabsTrigger value="monthly" className="data-[state=active]:shadow-neuro-pressed data-[state=active]:bg-transparent">월간 예산</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="daily" className="space-y-4 mt-0">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Input
|
||||
value={getDisplayValue('daily')}
|
||||
onChange={e => handleInputChange(e.target.value, 'daily')}
|
||||
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('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>
|
||||
<div className="space-y-4 mt-0">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Input
|
||||
value={getDisplayValue()}
|
||||
onChange={e => handleInputChange(e.target.value)}
|
||||
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()}
|
||||
</p>
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import BudgetTabContent from './BudgetTabContent';
|
||||
import { BudgetPeriod } from '@/contexts/budget/BudgetContext';
|
||||
|
||||
@@ -38,8 +37,6 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
|
||||
useEffect(() => {
|
||||
console.log("BudgetProgressCard 데이터 업데이트 - 예산 데이터:", budgetData);
|
||||
console.log("월간 예산:", budgetData.monthly.targetAmount);
|
||||
console.log("주간 예산:", budgetData.weekly.targetAmount);
|
||||
console.log("일일 예산:", budgetData.daily.targetAmount);
|
||||
setLocalBudgetData(budgetData);
|
||||
|
||||
// 지연 작업으로 이벤트 발생 (컴포넌트 마운트 후 데이터 갱신)
|
||||
@@ -52,9 +49,9 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
|
||||
|
||||
// 초기 탭 설정을 위한 효과
|
||||
useEffect(() => {
|
||||
if (!selectedTab) {
|
||||
console.log("초기 탭 설정: daily");
|
||||
setSelectedTab('daily');
|
||||
if (!selectedTab || selectedTab !== "monthly") {
|
||||
console.log("초기 탭 설정: monthly");
|
||||
setSelectedTab('monthly');
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -68,78 +65,21 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
|
||||
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;
|
||||
|
||||
console.log(`BudgetProgressCard 상태: 일=${isDailyBudgetSet}, 주=${isWeeklyBudgetSet}, 월=${isMonthlyBudgetSet}`);
|
||||
console.log(`BudgetProgressCard 상태: 월=${isMonthlyBudgetSet}`);
|
||||
|
||||
return (
|
||||
<div className="neuro-card mb-6 overflow-hidden w-full">
|
||||
<Tabs defaultValue="daily" value={selectedTab} onValueChange={handleTabChange} className="w-full">
|
||||
<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>
|
||||
|
||||
<TabsContent value="daily" className="space-y-4 mt-0">
|
||||
<BudgetTabContent
|
||||
data={budgetData.daily}
|
||||
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 className="text-sm text-gray-600 mb-2 px-3 pt-3">지출 / 예산</div>
|
||||
|
||||
<BudgetTabContent
|
||||
data={budgetData.monthly}
|
||||
formatCurrency={formatCurrency}
|
||||
calculatePercentage={calculatePercentage}
|
||||
onSaveBudget={(amount, categoryBudgets) => onSaveBudget('monthly', amount, categoryBudgets)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -48,14 +48,14 @@ const BudgetTabContent: React.FC<BudgetTabContentProps> = ({
|
||||
onSaveBudget
|
||||
});
|
||||
|
||||
// 월간 예산 모드를 명시적으로 로깅
|
||||
// 월간 예산 모드 로깅
|
||||
React.useEffect(() => {
|
||||
console.log('BudgetTabContent 렌더링: 월간 예산 모드');
|
||||
console.log('BudgetTabContent 렌더링: 월간 예산');
|
||||
console.log('현재 예산 데이터:', data);
|
||||
}, [data]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="px-3 pb-3">
|
||||
{isBudgetSet ? (
|
||||
<>
|
||||
<BudgetHeader
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
import React from 'react';
|
||||
import BudgetProgressCard from '@/components/BudgetProgressCard';
|
||||
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
|
||||
budgetData={budgetData}
|
||||
selectedTab={selectedTab}
|
||||
|
||||
@@ -12,7 +12,7 @@ export const useBudgetState = () => {
|
||||
console.log('초기 예산 데이터 로드:', 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 [lastUpdateTime, setLastUpdateTime] = useState(0);
|
||||
|
||||
|
||||
@@ -17,20 +17,9 @@ export const useExtendedBudgetUpdate = (
|
||||
) => {
|
||||
console.log('확장 예산 업데이트 시작:', type, amount, newCategoryBudgets);
|
||||
|
||||
// 항상 입력값을 월간 기준으로 변환하여 예산 업데이트
|
||||
let monthlyAmount = 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);
|
||||
// 타입에 상관없이 항상 월간으로 처리
|
||||
console.log(`예산 업데이트: 입력 금액=${amount}, 항상 월간으로 설정`);
|
||||
handleBudgetUpdate('monthly', amount);
|
||||
|
||||
// 카테고리 예산 업데이트 (제공된 경우)
|
||||
if (newCategoryBudgets) {
|
||||
|
||||
Reference in New Issue
Block a user