Investigate budget display issue
Examine why budget data is not displaying correctly on the expense and analytics screens, despite being saved successfully.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect, useState } 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/budget/BudgetContext';
|
import { BudgetPeriod } from '@/contexts/budget/BudgetContext';
|
||||||
@@ -31,21 +31,52 @@ const BudgetProgressCard: React.FC<BudgetProgressCardProps> = ({
|
|||||||
calculatePercentage,
|
calculatePercentage,
|
||||||
onSaveBudget
|
onSaveBudget
|
||||||
}) => {
|
}) => {
|
||||||
// 컴포넌트 마운트 시 예산 데이터 업데이트 이벤트 발생
|
// 데이터 상태 추적 (불일치 감지를 위한 로컬 상태)
|
||||||
|
const [localBudgetData, setLocalBudgetData] = useState(budgetData);
|
||||||
|
|
||||||
|
// 컴포넌트 마운트 및 budgetData 변경 시 업데이트
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("BudgetProgressCard 마운트 - 예산 데이터:", budgetData);
|
console.log("BudgetProgressCard 데이터 업데이트 - 예산 데이터:", budgetData);
|
||||||
|
setLocalBudgetData(budgetData);
|
||||||
|
|
||||||
// 지연 작업으로 이벤트 발생 (컴포넌트 마운트 후 데이터 갱신)
|
// 지연 작업으로 이벤트 발생 (컴포넌트 마운트 후 데이터 갱신)
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
window.dispatchEvent(new Event('budgetDataUpdated'));
|
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||||
}, 500);
|
}, 300);
|
||||||
|
|
||||||
return () => clearTimeout(timeoutId);
|
return () => clearTimeout(timeoutId);
|
||||||
|
}, [budgetData]);
|
||||||
|
|
||||||
|
// budgetDataUpdated 이벤트 감지
|
||||||
|
useEffect(() => {
|
||||||
|
const handleBudgetDataUpdated = () => {
|
||||||
|
console.log("BudgetProgressCard: 예산 데이터 업데이트 이벤트 감지");
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('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;
|
||||||
|
|
||||||
|
console.log(`BudgetProgressCard 상태: 일=${isDailyBudgetSet}, 주=${isWeeklyBudgetSet}, 월=${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={setSelectedTab} className="w-full">
|
<Tabs defaultValue="daily" value={selectedTab} onValueChange={handleTabChange} className="w-full">
|
||||||
<TabsList className="grid grid-cols-3 mb-4 bg-transparent">
|
<TabsList className="grid grid-cols-3 mb-4 bg-transparent">
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="daily"
|
value="daily"
|
||||||
|
|||||||
@@ -29,13 +29,35 @@ const BudgetTabContent: React.FC<BudgetTabContentProps> = ({
|
|||||||
const spentAmount = data.spentAmount;
|
const spentAmount = data.spentAmount;
|
||||||
const targetAmount = data.targetAmount;
|
const targetAmount = data.targetAmount;
|
||||||
|
|
||||||
// 예산 설정 여부 확인 (수정: 0보다 큰지만 확인)
|
// 로그 추가 - 받은 데이터 확인
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(`BudgetTabContent 수신 데이터:`, data);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
// 전역 예산 데이터가 변경되었을 때 로컬 상태 갱신
|
||||||
|
useEffect(() => {
|
||||||
|
const handleBudgetDataUpdated = () => {
|
||||||
|
console.log(`BudgetTabContent: 전역 예산 데이터 이벤트 감지, 현재 targetAmount=${targetAmount}`);
|
||||||
|
// 입력 폼이 열려있고 예산이 설정된 경우 폼 닫기
|
||||||
|
if (showBudgetInput && targetAmount > 0) {
|
||||||
|
console.log('예산이 설정되어 입력 폼을 닫습니다.');
|
||||||
|
setShowBudgetInput(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('budgetDataUpdated', handleBudgetDataUpdated);
|
||||||
|
return () => window.removeEventListener('budgetDataUpdated', handleBudgetDataUpdated);
|
||||||
|
}, [showBudgetInput, targetAmount]);
|
||||||
|
|
||||||
|
// 예산 설정 여부 확인 - 데이터 targetAmount가 실제로 0보다 큰지 확인
|
||||||
const isBudgetSet = targetAmount > 0;
|
const isBudgetSet = targetAmount > 0;
|
||||||
|
|
||||||
// 디버깅을 위한 로그 추가
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(`BudgetTabContent 렌더링: targetAmount=${targetAmount}, isBudgetSet=${isBudgetSet}`);
|
if (isBudgetSet && showBudgetInput) {
|
||||||
}, [targetAmount, isBudgetSet]);
|
console.log('예산이 설정되었으므로 입력 폼을 닫습니다.');
|
||||||
|
setShowBudgetInput(false);
|
||||||
|
}
|
||||||
|
}, [isBudgetSet, showBudgetInput]);
|
||||||
|
|
||||||
// 실제 백분율 계산 (초과해도 실제 퍼센트로 표시)
|
// 실제 백분율 계산 (초과해도 실제 퍼센트로 표시)
|
||||||
const actualPercentage = targetAmount > 0 ? Math.round((spentAmount / targetAmount) * 100) : 0;
|
const actualPercentage = targetAmount > 0 ? Math.round((spentAmount / targetAmount) * 100) : 0;
|
||||||
@@ -116,12 +138,16 @@ const BudgetTabContent: React.FC<BudgetTabContentProps> = ({
|
|||||||
|
|
||||||
// 예산 버튼 클릭 핸들러 - 토글 기능 추가
|
// 예산 버튼 클릭 핸들러 - 토글 기능 추가
|
||||||
const toggleBudgetInput = () => {
|
const toggleBudgetInput = () => {
|
||||||
|
console.log('예산 입력 폼 토글. 현재 상태:', showBudgetInput, '예산 설정 여부:', isBudgetSet);
|
||||||
setShowBudgetInput(prev => !prev);
|
setShowBudgetInput(prev => !prev);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 예산 여부에 따른 텍스트 결정
|
// 예산 여부에 따른 텍스트 결정
|
||||||
const budgetButtonText = isBudgetSet ? "예산 수정하기" : "예산 입력하기";
|
const budgetButtonText = isBudgetSet ? "예산 수정하기" : "예산 입력하기";
|
||||||
|
|
||||||
|
// 화면에 표시할 내용 - 디버깅을 위한 로그 추가
|
||||||
|
console.log(`BudgetTabContent 렌더링: targetAmount=${targetAmount}, isBudgetSet=${isBudgetSet}, 표시될 화면:`, isBudgetSet ? "예산 진행 상황" : "예산 입력하기 버튼");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{isBudgetSet ? (
|
{isBudgetSet ? (
|
||||||
|
|||||||
@@ -63,7 +63,13 @@ export const calculateUpdatedBudgetData = (
|
|||||||
type: BudgetPeriod,
|
type: BudgetPeriod,
|
||||||
amount: number
|
amount: number
|
||||||
): BudgetData => {
|
): BudgetData => {
|
||||||
console.log(`예산 업데이트 계산: 타입=${type}, 금액=${amount}`);
|
console.log(`예산 업데이트 계산 시작: 타입=${type}, 금액=${amount}`);
|
||||||
|
|
||||||
|
// 값이 없거나 유효하지 않은 경우 로깅
|
||||||
|
if (!prevBudgetData) {
|
||||||
|
console.error('이전 예산 데이터가 없습니다. 기본값 사용.');
|
||||||
|
prevBudgetData = getInitialBudgetData();
|
||||||
|
}
|
||||||
|
|
||||||
// 선택된 타입에 따라 다른 타입의 예산도 자동으로 계산
|
// 선택된 타입에 따라 다른 타입의 예산도 자동으로 계산
|
||||||
let monthlyAmount: number, weeklyAmount: number, dailyAmount: number;
|
let monthlyAmount: number, weeklyAmount: number, dailyAmount: number;
|
||||||
@@ -71,7 +77,9 @@ export const calculateUpdatedBudgetData = (
|
|||||||
if (type === 'monthly') {
|
if (type === 'monthly') {
|
||||||
// 월간 예산이 직접 입력된 경우
|
// 월간 예산이 직접 입력된 경우
|
||||||
monthlyAmount = amount;
|
monthlyAmount = amount;
|
||||||
|
// 월 30일 기준 (실제 사용 시 값 확인)
|
||||||
dailyAmount = Math.round(monthlyAmount / 30);
|
dailyAmount = Math.round(monthlyAmount / 30);
|
||||||
|
// 월 4.3주 기준 (실제 사용 시 값 확인)
|
||||||
weeklyAmount = Math.round(monthlyAmount / 4.3);
|
weeklyAmount = Math.round(monthlyAmount / 4.3);
|
||||||
} else if (type === 'weekly') {
|
} else if (type === 'weekly') {
|
||||||
// 주간 예산이 직접 입력된 경우
|
// 주간 예산이 직접 입력된 경우
|
||||||
@@ -90,29 +98,38 @@ export const calculateUpdatedBudgetData = (
|
|||||||
weeklyAmount = Math.max(0, weeklyAmount);
|
weeklyAmount = Math.max(0, weeklyAmount);
|
||||||
dailyAmount = Math.max(0, dailyAmount);
|
dailyAmount = Math.max(0, dailyAmount);
|
||||||
|
|
||||||
console.log(`최종 예산 계산: 월간=${monthlyAmount}원, 주간=${weeklyAmount}원, 일일=${dailyAmount}원`);
|
console.log(`최종 예산 계산 결과: 월간=${monthlyAmount}원, 주간=${weeklyAmount}원, 일일=${dailyAmount}원`);
|
||||||
|
|
||||||
// prevBudgetData 출력하여 디버깅
|
// 로그에 이전 예산 데이터 출력
|
||||||
console.log("이전 예산 데이터:", JSON.stringify(prevBudgetData));
|
console.log("이전 예산 데이터:", JSON.stringify(prevBudgetData));
|
||||||
|
|
||||||
|
// 이전 지출 데이터 보존
|
||||||
|
const dailySpent = prevBudgetData.daily?.spentAmount || 0;
|
||||||
|
const weeklySpent = prevBudgetData.weekly?.spentAmount || 0;
|
||||||
|
const monthlySpent = prevBudgetData.monthly?.spentAmount || 0;
|
||||||
|
|
||||||
// 새 예산 데이터 생성 (spentAmount는 이전 값 유지)
|
// 새 예산 데이터 생성 (spentAmount는 이전 값 유지)
|
||||||
return {
|
const updatedBudgetData = {
|
||||||
daily: {
|
daily: {
|
||||||
targetAmount: dailyAmount,
|
targetAmount: dailyAmount,
|
||||||
spentAmount: prevBudgetData.daily.spentAmount,
|
spentAmount: dailySpent,
|
||||||
remainingAmount: Math.max(0, dailyAmount - prevBudgetData.daily.spentAmount)
|
remainingAmount: Math.max(0, dailyAmount - dailySpent)
|
||||||
},
|
},
|
||||||
weekly: {
|
weekly: {
|
||||||
targetAmount: weeklyAmount,
|
targetAmount: weeklyAmount,
|
||||||
spentAmount: prevBudgetData.weekly.spentAmount,
|
spentAmount: weeklySpent,
|
||||||
remainingAmount: Math.max(0, weeklyAmount - prevBudgetData.weekly.spentAmount)
|
remainingAmount: Math.max(0, weeklyAmount - weeklySpent)
|
||||||
},
|
},
|
||||||
monthly: {
|
monthly: {
|
||||||
targetAmount: monthlyAmount,
|
targetAmount: monthlyAmount,
|
||||||
spentAmount: prevBudgetData.monthly.spentAmount,
|
spentAmount: monthlySpent,
|
||||||
remainingAmount: Math.max(0, monthlyAmount - prevBudgetData.monthly.spentAmount)
|
remainingAmount: Math.max(0, monthlyAmount - monthlySpent)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log("새 예산 데이터:", JSON.stringify(updatedBudgetData));
|
||||||
|
|
||||||
|
return updatedBudgetData;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 지출액 계산 (일일, 주간, 월간) - 문제 수정
|
// 지출액 계산 (일일, 주간, 월간) - 문제 수정
|
||||||
@@ -120,6 +137,8 @@ export const calculateSpentAmounts = (
|
|||||||
transactions: Transaction[],
|
transactions: Transaction[],
|
||||||
prevBudgetData: BudgetData
|
prevBudgetData: BudgetData
|
||||||
): BudgetData => {
|
): BudgetData => {
|
||||||
|
console.log("지출액 계산 시작, 트랜잭션 수:", transactions.length);
|
||||||
|
|
||||||
// 지출 거래 필터링
|
// 지출 거래 필터링
|
||||||
const expenseTransactions = transactions.filter(t => t.type === 'expense');
|
const expenseTransactions = transactions.filter(t => t.type === 'expense');
|
||||||
|
|
||||||
@@ -140,13 +159,13 @@ export const calculateSpentAmounts = (
|
|||||||
// 이번 달 총 지출 계산
|
// 이번 달 총 지출 계산
|
||||||
const monthlySpent = expenseTransactions.reduce((sum, t) => sum + t.amount, 0);
|
const monthlySpent = expenseTransactions.reduce((sum, t) => sum + t.amount, 0);
|
||||||
|
|
||||||
// 기존 예산 목표 유지
|
// 기존 예산 목표 유지 (없으면 기본값 0)
|
||||||
const dailyTarget = prevBudgetData.daily.targetAmount;
|
const dailyTarget = prevBudgetData?.daily?.targetAmount || 0;
|
||||||
const weeklyTarget = prevBudgetData.weekly.targetAmount;
|
const weeklyTarget = prevBudgetData?.weekly?.targetAmount || 0;
|
||||||
const monthlyTarget = prevBudgetData.monthly.targetAmount;
|
const monthlyTarget = prevBudgetData?.monthly?.targetAmount || 0;
|
||||||
|
|
||||||
// 예산 데이터 업데이트
|
// 예산 데이터 업데이트
|
||||||
return {
|
const updatedBudget = {
|
||||||
daily: {
|
daily: {
|
||||||
targetAmount: dailyTarget,
|
targetAmount: dailyTarget,
|
||||||
spentAmount: dailySpent,
|
spentAmount: dailySpent,
|
||||||
@@ -163,6 +182,10 @@ export const calculateSpentAmounts = (
|
|||||||
remainingAmount: Math.max(0, monthlyTarget - monthlySpent)
|
remainingAmount: Math.max(0, monthlyTarget - monthlySpent)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log("지출액 계산 결과:", updatedBudget);
|
||||||
|
|
||||||
|
return updatedBudget;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 초기 예산 데이터 생성
|
// 초기 예산 데이터 생성
|
||||||
@@ -185,3 +208,25 @@ export const getInitialBudgetData = (): BudgetData => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 스토리지에서 안전하게 예산 데이터 가져오기
|
||||||
|
export const safelyLoadBudgetData = (defaultData: BudgetData = getInitialBudgetData()): BudgetData => {
|
||||||
|
try {
|
||||||
|
const budgetDataStr = localStorage.getItem('budgetData');
|
||||||
|
if (budgetDataStr) {
|
||||||
|
const parsed = JSON.parse(budgetDataStr);
|
||||||
|
|
||||||
|
// 데이터 구조 검증 (daily, weekly, monthly 키 존재 확인)
|
||||||
|
if (parsed && parsed.daily && parsed.weekly && parsed.monthly) {
|
||||||
|
return parsed;
|
||||||
|
} else {
|
||||||
|
console.warn('저장된 예산 데이터 구조가 유효하지 않습니다. 기본값 사용.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('예산 데이터 로드 오류:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 오류 발생 또는 데이터 없음 시 기본값 반환
|
||||||
|
return defaultData;
|
||||||
|
};
|
||||||
|
|||||||
@@ -9,16 +9,19 @@ import {
|
|||||||
import { toast } from '@/components/ui/use-toast';
|
import { toast } from '@/components/ui/use-toast';
|
||||||
import {
|
import {
|
||||||
calculateUpdatedBudgetData,
|
calculateUpdatedBudgetData,
|
||||||
calculateSpentAmounts
|
calculateSpentAmounts,
|
||||||
|
safelyLoadBudgetData
|
||||||
} from '../budgetUtils';
|
} from '../budgetUtils';
|
||||||
|
|
||||||
import { Transaction } from '../types';
|
import { Transaction } from '../types';
|
||||||
|
|
||||||
// 예산 데이터 상태 관리 훅
|
// 예산 데이터 상태 관리 훅
|
||||||
export const useBudgetDataState = (transactions: Transaction[]) => {
|
export const useBudgetDataState = (transactions: Transaction[]) => {
|
||||||
const [budgetData, setBudgetData] = useState<BudgetData>(loadBudgetDataFromStorage());
|
// 초기 데이터 로드 시 safelyLoadBudgetData 함수 사용
|
||||||
|
const [budgetData, setBudgetData] = useState<BudgetData>(safelyLoadBudgetData());
|
||||||
const [selectedTab, setSelectedTab] = useState<BudgetPeriod>("daily");
|
const [selectedTab, setSelectedTab] = useState<BudgetPeriod>("daily");
|
||||||
const [isInitialized, setIsInitialized] = useState(false);
|
const [isInitialized, setIsInitialized] = useState(false);
|
||||||
|
const [lastUpdateTime, setLastUpdateTime] = useState(0);
|
||||||
|
|
||||||
// 초기 로드 및 이벤트 리스너 설정 - 최적화된 버전
|
// 초기 로드 및 이벤트 리스너 설정 - 최적화된 버전
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -30,54 +33,51 @@ export const useBudgetDataState = (transactions: Transaction[]) => {
|
|||||||
// 비동기 작업을 마이크로태스크로 지연
|
// 비동기 작업을 마이크로태스크로 지연
|
||||||
await new Promise<void>(resolve => queueMicrotask(() => resolve()));
|
await new Promise<void>(resolve => queueMicrotask(() => resolve()));
|
||||||
|
|
||||||
const loadedData = loadBudgetDataFromStorage();
|
// 안전하게 데이터 로드
|
||||||
|
const loadedData = safelyLoadBudgetData();
|
||||||
console.log('로드된 예산 데이터:', JSON.stringify(loadedData));
|
console.log('로드된 예산 데이터:', JSON.stringify(loadedData));
|
||||||
|
|
||||||
// 새로 로드한 데이터와 현재 데이터가 다를 때만 업데이트
|
// 새로 로드한 데이터와 현재 데이터가 다를 때만 업데이트
|
||||||
if (JSON.stringify(loadedData) !== JSON.stringify(budgetData)) {
|
if (JSON.stringify(loadedData) !== JSON.stringify(budgetData)) {
|
||||||
// 상태 업데이트를 마이크로태스크로 지연
|
console.log('새 예산 데이터 감지됨, 상태 업데이트');
|
||||||
queueMicrotask(() => {
|
setBudgetData(loadedData);
|
||||||
setBudgetData(loadedData);
|
setLastUpdateTime(Date.now());
|
||||||
console.log('예산 데이터 업데이트 완료');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 초기화 상태 업데이트
|
// 초기화 상태 업데이트
|
||||||
if (!isInitialized) {
|
if (!isInitialized) {
|
||||||
queueMicrotask(() => {
|
setIsInitialized(true);
|
||||||
setIsInitialized(true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('예산 데이터 로드 중 오류:', error);
|
console.error('예산 데이터 로드 중 오류:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 초기 로드 - 지연 시간 추가
|
// 초기 로드 - 직접 호출
|
||||||
setTimeout(() => {
|
loadBudget();
|
||||||
|
|
||||||
|
// 필수 이벤트 등록
|
||||||
|
const handleBudgetUpdate = () => {
|
||||||
|
console.log('예산 데이터 업데이트 이벤트 감지');
|
||||||
loadBudget();
|
loadBudget();
|
||||||
}, 100); // 지연된 초기 로드
|
};
|
||||||
|
|
||||||
// 필수 이벤트만 등록
|
window.addEventListener('budgetDataUpdated', handleBudgetUpdate);
|
||||||
const handleBudgetUpdate = () => loadBudget();
|
|
||||||
|
|
||||||
// 필수 이벤트만 등록
|
|
||||||
const budgetUpdateHandler = () => handleBudgetUpdate();
|
|
||||||
window.addEventListener('budgetDataUpdated', budgetUpdateHandler);
|
|
||||||
|
|
||||||
// 스토리지 이벤트도 함께 처리 (다른 탭/창에서의 업데이트 감지)
|
// 스토리지 이벤트도 함께 처리 (다른 탭/창에서의 업데이트 감지)
|
||||||
const storageUpdateHandler = (e: StorageEvent) => {
|
const storageUpdateHandler = (e: StorageEvent) => {
|
||||||
if (e.key === 'budgetData' || e.key === null) {
|
if (e.key === 'budgetData' || e.key === null) {
|
||||||
|
console.log('스토리지 이벤트 감지 - 예산 데이터 업데이트');
|
||||||
handleBudgetUpdate();
|
handleBudgetUpdate();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.addEventListener('storage', storageUpdateHandler);
|
window.addEventListener('storage', storageUpdateHandler);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('budgetDataUpdated', budgetUpdateHandler);
|
window.removeEventListener('budgetDataUpdated', handleBudgetUpdate);
|
||||||
window.removeEventListener('storage', storageUpdateHandler);
|
window.removeEventListener('storage', storageUpdateHandler);
|
||||||
};
|
};
|
||||||
}, [isInitialized, budgetData]);
|
}, [isInitialized]);
|
||||||
|
|
||||||
// 트랜잭션 변경 시 지출 금액 업데이트
|
// 트랜잭션 변경 시 지출 금액 업데이트
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -85,19 +85,18 @@ export const useBudgetDataState = (transactions: Transaction[]) => {
|
|||||||
console.log('트랜잭션 변경으로 인한 예산 데이터 업데이트. 트랜잭션 수:', transactions.length);
|
console.log('트랜잭션 변경으로 인한 예산 데이터 업데이트. 트랜잭션 수:', transactions.length);
|
||||||
try {
|
try {
|
||||||
// 현재 예산 데이터 다시 로드 (최신 상태 확보)
|
// 현재 예산 데이터 다시 로드 (최신 상태 확보)
|
||||||
const currentBudgetData = loadBudgetDataFromStorage();
|
const currentBudgetData = safelyLoadBudgetData();
|
||||||
|
|
||||||
// 지출 금액 업데이트
|
// 지출 금액 업데이트
|
||||||
const updatedBudgetData = calculateSpentAmounts(transactions, currentBudgetData);
|
const updatedBudgetData = calculateSpentAmounts(transactions, currentBudgetData);
|
||||||
|
|
||||||
// 변경이 있을 때만 저장
|
// 변경이 있을 때만 저장
|
||||||
if (JSON.stringify(updatedBudgetData) !== JSON.stringify(currentBudgetData)) {
|
if (JSON.stringify(updatedBudgetData) !== JSON.stringify(currentBudgetData)) {
|
||||||
|
console.log('예산 지출액 업데이트 감지 - 데이터 저장');
|
||||||
// 상태 및 스토리지 모두 업데이트
|
// 상태 및 스토리지 모두 업데이트
|
||||||
setBudgetData(updatedBudgetData);
|
setBudgetData(updatedBudgetData);
|
||||||
saveBudgetDataToStorage(updatedBudgetData);
|
saveBudgetDataToStorage(updatedBudgetData);
|
||||||
|
setLastUpdateTime(Date.now());
|
||||||
// 저장 시간 업데이트
|
|
||||||
localStorage.setItem('lastBudgetSaveTime', new Date().toISOString());
|
|
||||||
|
|
||||||
// 기타 컴포넌트에 이벤트 알림
|
// 기타 컴포넌트에 이벤트 알림
|
||||||
window.dispatchEvent(new Event('budgetDataUpdated'));
|
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||||
@@ -128,7 +127,7 @@ export const useBudgetDataState = (transactions: Transaction[]) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 현재 최신 예산 데이터 로드 (다른 곳에서 변경되었을 수 있음)
|
// 현재 최신 예산 데이터 로드 (다른 곳에서 변경되었을 수 있음)
|
||||||
const currentBudgetData = loadBudgetDataFromStorage();
|
const currentBudgetData = safelyLoadBudgetData();
|
||||||
|
|
||||||
// 예산 데이터 업데이트 - 일간, 주간, 월간 예산이 모두 자동으로 계산됨
|
// 예산 데이터 업데이트 - 일간, 주간, 월간 예산이 모두 자동으로 계산됨
|
||||||
const updatedBudgetData = calculateUpdatedBudgetData(currentBudgetData, type, amount);
|
const updatedBudgetData = calculateUpdatedBudgetData(currentBudgetData, type, amount);
|
||||||
@@ -137,9 +136,7 @@ export const useBudgetDataState = (transactions: Transaction[]) => {
|
|||||||
// 상태 및 스토리지 둘 다 업데이트
|
// 상태 및 스토리지 둘 다 업데이트
|
||||||
setBudgetData(updatedBudgetData);
|
setBudgetData(updatedBudgetData);
|
||||||
saveBudgetDataToStorage(updatedBudgetData);
|
saveBudgetDataToStorage(updatedBudgetData);
|
||||||
|
setLastUpdateTime(Date.now());
|
||||||
// 저장 시간 업데이트
|
|
||||||
localStorage.setItem('lastBudgetSaveTime', new Date().toISOString());
|
|
||||||
|
|
||||||
// 이벤트 발생시켜 다른 컴포넌트에 알림
|
// 이벤트 발생시켜 다른 컴포넌트에 알림
|
||||||
window.dispatchEvent(new Event('budgetDataUpdated'));
|
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||||
@@ -151,7 +148,16 @@ export const useBudgetDataState = (transactions: Transaction[]) => {
|
|||||||
key: 'budgetData',
|
key: 'budgetData',
|
||||||
newValue: JSON.stringify(updatedBudgetData)
|
newValue: JSON.stringify(updatedBudgetData)
|
||||||
}));
|
}));
|
||||||
}, 1000);
|
}, 500);
|
||||||
|
|
||||||
|
// 2초 후 데이터 갱신 이벤트 한 번 더 발생
|
||||||
|
setTimeout(() => {
|
||||||
|
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||||
|
window.dispatchEvent(new StorageEvent('storage', {
|
||||||
|
key: 'budgetData',
|
||||||
|
newValue: JSON.stringify(updatedBudgetData)
|
||||||
|
}));
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
console.log('예산 목표 업데이트 완료:', updatedBudgetData);
|
console.log('예산 목표 업데이트 완료:', updatedBudgetData);
|
||||||
|
|
||||||
@@ -178,8 +184,9 @@ export const useBudgetDataState = (transactions: Transaction[]) => {
|
|||||||
clearAllBudgetData();
|
clearAllBudgetData();
|
||||||
|
|
||||||
// 로컬스토리지에서 다시 로드
|
// 로컬스토리지에서 다시 로드
|
||||||
const freshData = loadBudgetDataFromStorage();
|
const freshData = safelyLoadBudgetData();
|
||||||
setBudgetData(freshData);
|
setBudgetData(freshData);
|
||||||
|
setLastUpdateTime(Date.now());
|
||||||
|
|
||||||
// 이벤트 발생시켜 다른 컴포넌트에 알림
|
// 이벤트 발생시켜 다른 컴포넌트에 알림
|
||||||
window.dispatchEvent(new Event('budgetDataUpdated'));
|
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||||
@@ -195,8 +202,8 @@ export const useBudgetDataState = (transactions: Transaction[]) => {
|
|||||||
|
|
||||||
// 디버깅 로그 추가
|
// 디버깅 로그 추가
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('최신 예산 데이터:', JSON.stringify(budgetData));
|
console.log('최신 예산 데이터:', JSON.stringify(budgetData), '마지막 업데이트:', new Date(lastUpdateTime).toISOString());
|
||||||
}, [budgetData]);
|
}, [budgetData, lastUpdateTime]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
budgetData,
|
budgetData,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const useExtendedBudgetUpdate = (
|
|||||||
amount: number,
|
amount: number,
|
||||||
newCategoryBudgets?: Record<string, number>
|
newCategoryBudgets?: Record<string, number>
|
||||||
) => {
|
) => {
|
||||||
console.log(`확장된 예산 목표 업데이트: ${type}, 금액: ${amount}, 카테고리 예산:`, newCategoryBudgets);
|
console.log(`확장된 예산 목표 업데이트 호출: ${type}, 금액: ${amount}, 카테고리 예산:`, newCategoryBudgets);
|
||||||
|
|
||||||
// 카테고리 예산이 제공된 경우 업데이트
|
// 카테고리 예산이 제공된 경우 업데이트
|
||||||
if (newCategoryBudgets) {
|
if (newCategoryBudgets) {
|
||||||
@@ -48,7 +48,7 @@ export const useExtendedBudgetUpdate = (
|
|||||||
|
|
||||||
// 총액 계산 (0 확인)
|
// 총액 계산 (0 확인)
|
||||||
const totalAmount = Object.values(updatedCategoryBudgets).reduce((sum, val) => sum + val, 0);
|
const totalAmount = Object.values(updatedCategoryBudgets).reduce((sum, val) => sum + val, 0);
|
||||||
console.log('카테고리 총액:', totalAmount);
|
console.log('카테고리 예산 총합:', totalAmount, updatedCategoryBudgets);
|
||||||
|
|
||||||
if (totalAmount <= 0) {
|
if (totalAmount <= 0) {
|
||||||
toast({
|
toast({
|
||||||
@@ -71,19 +71,39 @@ export const useExtendedBudgetUpdate = (
|
|||||||
description: `월간 총 예산이 ${totalAmount.toLocaleString()}원으로 설정되었습니다.`
|
description: `월간 총 예산이 ${totalAmount.toLocaleString()}원으로 설정되었습니다.`
|
||||||
});
|
});
|
||||||
|
|
||||||
// 여러 번의 이벤트 발생으로 UI 업데이트 보장 (타이밍 문제 해결)
|
// 다중 이벤트 발생으로 UI 업데이트 보장
|
||||||
|
// 0.5초 후 1차 업데이트
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
console.log("예산 UI 업데이트 이벤트 발생 (1차)");
|
||||||
window.dispatchEvent(new Event('budgetDataUpdated'));
|
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||||
}, 300);
|
}, 500);
|
||||||
|
|
||||||
|
// 1.5초 후 2차 업데이트
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
console.log("예산 UI 업데이트 이벤트 발생 (2차)");
|
||||||
window.dispatchEvent(new Event('budgetDataUpdated'));
|
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||||
// 스토리지 이벤트도 발생시켜 데이터 로드 보장
|
// 스토리지 이벤트도 발생시켜 데이터 로드 보장
|
||||||
window.dispatchEvent(new StorageEvent('storage', {
|
const savedData = localStorage.getItem('budgetData');
|
||||||
key: 'budgetData',
|
if (savedData) {
|
||||||
newValue: localStorage.getItem('budgetData')
|
window.dispatchEvent(new StorageEvent('storage', {
|
||||||
}));
|
key: 'budgetData',
|
||||||
}, 1000);
|
newValue: savedData
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// 3초 후 3차 업데이트 (최종 보장)
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log("예산 UI 업데이트 이벤트 발생 (3차/최종)");
|
||||||
|
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||||
|
const savedData = localStorage.getItem('budgetData');
|
||||||
|
if (savedData) {
|
||||||
|
window.dispatchEvent(new StorageEvent('storage', {
|
||||||
|
key: 'budgetData',
|
||||||
|
newValue: savedData
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('카테고리 예산 업데이트 오류:', error);
|
console.error('카테고리 예산 업데이트 오류:', error);
|
||||||
toast({
|
toast({
|
||||||
@@ -132,19 +152,38 @@ export const useExtendedBudgetUpdate = (
|
|||||||
description: `${periodText} 예산이 ${amount.toLocaleString()}원으로 설정되었습니다.`
|
description: `${periodText} 예산이 ${amount.toLocaleString()}원으로 설정되었습니다.`
|
||||||
});
|
});
|
||||||
|
|
||||||
// 데이터 표시 강제 갱신 (타이밍 문제 해결을 위한 여러 이벤트 발생)
|
// 다중 이벤트 발생
|
||||||
|
// 0.5초 후 1차 업데이트
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
console.log("예산 UI 업데이트 이벤트 발생 (1차)");
|
||||||
window.dispatchEvent(new Event('budgetDataUpdated'));
|
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||||
}, 300);
|
}, 500);
|
||||||
|
|
||||||
|
// 1.5초 후 2차 업데이트
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
console.log("예산 UI 업데이트 이벤트 발생 (2차)");
|
||||||
window.dispatchEvent(new Event('budgetDataUpdated'));
|
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||||
// 스토리지 이벤트도 발생시켜 데이터 로드 보장
|
const savedData = localStorage.getItem('budgetData');
|
||||||
window.dispatchEvent(new StorageEvent('storage', {
|
if (savedData) {
|
||||||
key: 'budgetData',
|
window.dispatchEvent(new StorageEvent('storage', {
|
||||||
newValue: localStorage.getItem('budgetData')
|
key: 'budgetData',
|
||||||
}));
|
newValue: savedData
|
||||||
}, 1000);
|
}));
|
||||||
|
}
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// 3초 후 3차 업데이트 (최종 보장)
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log("예산 UI 업데이트 이벤트 발생 (3차/최종)");
|
||||||
|
window.dispatchEvent(new Event('budgetDataUpdated'));
|
||||||
|
const savedData = localStorage.getItem('budgetData');
|
||||||
|
if (savedData) {
|
||||||
|
window.dispatchEvent(new StorageEvent('storage', {
|
||||||
|
key: 'budgetData',
|
||||||
|
newValue: savedData
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
}
|
}
|
||||||
}, [categoryBudgets, handleBudgetGoalUpdate, updateCategoryBudgets]);
|
}, [categoryBudgets, handleBudgetGoalUpdate, updateCategoryBudgets]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user