diff --git a/src/contexts/budget/BudgetContext.tsx b/src/contexts/budget/BudgetContext.tsx index a8c12ee..87ed144 100644 --- a/src/contexts/budget/BudgetContext.tsx +++ b/src/contexts/budget/BudgetContext.tsx @@ -1,13 +1,30 @@ -import React, { createContext, useContext, ReactNode } from 'react'; -import { BudgetContextType } from './types'; +import React, { createContext, useContext } from 'react'; import { useBudgetState } from './useBudgetState'; +import { BudgetData, BudgetPeriod, Transaction } from './types'; -// Context 생성 +// 컨텍스트 인터페이스 정의 +interface BudgetContextType { + transactions: Transaction[]; + selectedTab: BudgetPeriod; + setSelectedTab: (tab: BudgetPeriod) => void; + budgetData: BudgetData; + categoryBudgets: Record; + getCategorySpending: () => Array<{ + title: string; + current: number; + total: number; + }>; + updateTransaction: (transaction: Transaction) => void; + handleBudgetGoalUpdate: (type: BudgetPeriod, amount: number, newCategoryBudgets?: Record) => void; + resetBudgetData?: () => void; // 선택적 필드로 추가 +} + +// 컨텍스트 생성 const BudgetContext = createContext(undefined); -// Context Provider 컴포넌트 -export const BudgetProvider: React.FC<{ children: ReactNode }> = ({ children }) => { +// 컨텍스트 프로바이더 컴포넌트 +export const BudgetProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const budgetState = useBudgetState(); return ( @@ -17,11 +34,13 @@ export const BudgetProvider: React.FC<{ children: ReactNode }> = ({ children }) ); }; -// Context 사용을 위한 Hook -export const useBudget = () => { +// 훅을 통한 컨텍스트 접근 +export const useBudget = (): BudgetContextType => { const context = useContext(BudgetContext); - if (!context) { + if (context === undefined) { throw new Error('useBudget must be used within a BudgetProvider'); } return context; }; + +export type { BudgetPeriod } from './types'; diff --git a/src/contexts/budget/storageUtils.ts b/src/contexts/budget/storageUtils.ts index 753ebaa..db83180 100644 --- a/src/contexts/budget/storageUtils.ts +++ b/src/contexts/budget/storageUtils.ts @@ -92,6 +92,8 @@ export const clearAllBudgetData = (): void => { // 모든 데이터 초기화 (첫 로그인 상태) export const resetAllData = (): void => { + console.log('완전 초기화 시작 - resetAllData'); + // 모든 관련 데이터 키 목록 (분석 페이지의 데이터 포함) const dataKeys = [ 'transactions', @@ -104,19 +106,29 @@ export const resetAllData = (): void => { 'expenseAnalytics', // 지출 분석 데이터 'expenseHistory', // 지출 이력 'budgetHistory', // 예산 이력 - 'analyticsCache' // 분석 캐시 데이터 + 'analyticsCache', // 분석 캐시 데이터 + 'monthlyTotals', // 월간 합계 데이터 + 'analytics', // 분석 페이지 데이터 + 'dailyBudget', // 일일 예산 + 'weeklyBudget', // 주간 예산 + 'monthlyBudget', // 월간 예산 + 'chartData', // 차트 데이터 + 'dontShowWelcome' // 환영 메시지 표시 여부 ]; // 모든 관련 데이터 키 삭제 - dataKeys.forEach(key => localStorage.removeItem(key)); + dataKeys.forEach(key => { + console.log(`삭제 중: ${key}`); + localStorage.removeItem(key); + }); // 기본 데이터로 초기화 clearAllTransactions(); clearAllCategoryBudgets(); clearAllBudgetData(); - // 추가적으로 사용자 기기에 저장된 모든 데이터 검사 - for (let i = 0; i < localStorage.length; i++) { + // 추가적으로 사용자 기기에 저장된 모든 데이터 검사 (역순으로 루프) + for (let i = localStorage.length - 1; i >= 0; i--) { const key = localStorage.key(i); if (key && ( key.includes('expense') || @@ -124,13 +136,28 @@ export const resetAllData = (): void => { key.includes('transaction') || key.includes('analytics') || key.includes('spending') || - key.includes('financial') + key.includes('financial') || + key.includes('chart') || + key.includes('month') || + key.includes('sync') || + key.includes('total') || + key.includes('welcome') || + key.includes('visited') )) { console.log(`추가 데이터 삭제: ${key}`); localStorage.removeItem(key); } } + // 강제로 빈 데이터로 초기화 + localStorage.setItem('transactions', JSON.stringify([])); + localStorage.setItem('budget', JSON.stringify({total: 0})); + localStorage.setItem('budgetData', JSON.stringify({ + daily: {targetAmount: 0, spentAmount: 0, remainingAmount: 0}, + weekly: {targetAmount: 0, spentAmount: 0, remainingAmount: 0}, + monthly: {targetAmount: 0, spentAmount: 0, remainingAmount: 0} + })); + localStorage.setItem('categoryBudgets', JSON.stringify(DEFAULT_CATEGORY_BUDGETS)); + console.log('모든 데이터가 초기화되었습니다.'); }; - diff --git a/src/contexts/budget/useBudgetState.ts b/src/contexts/budget/useBudgetState.ts index 6e7b4ce..1de4454 100644 --- a/src/contexts/budget/useBudgetState.ts +++ b/src/contexts/budget/useBudgetState.ts @@ -1,5 +1,5 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useCallback } from 'react'; import { BudgetData, BudgetPeriod, Transaction } from './types'; import { toast } from '@/components/ui/use-toast'; import { @@ -8,7 +8,10 @@ import { loadCategoryBudgetsFromStorage, saveCategoryBudgetsToStorage, loadBudgetDataFromStorage, - saveBudgetDataToStorage + saveBudgetDataToStorage, + clearAllTransactions, + clearAllCategoryBudgets, + clearAllBudgetData } from './storageUtils'; import { calculateCategorySpending, @@ -23,6 +26,23 @@ export const useBudgetState = () => { const [categoryBudgets, setCategoryBudgets] = useState>(loadCategoryBudgetsFromStorage()); const [budgetData, setBudgetData] = useState(loadBudgetDataFromStorage()); + // 데이터 리셋 함수 + const resetBudgetData = useCallback(() => { + console.log('BudgetContext에서 데이터 리셋 시작'); + + // 로컬 스토리지 초기화 + clearAllTransactions(); + clearAllCategoryBudgets(); + clearAllBudgetData(); + + // 메모리내 상태 초기화 + setTransactions([]); + setCategoryBudgets(loadCategoryBudgetsFromStorage()); + setBudgetData(loadBudgetDataFromStorage()); + + console.log('BudgetContext에서 데이터 리셋 완료'); + }, []); + // 트랜잭션 로드 useEffect(() => { const loadTransactions = () => { @@ -93,7 +113,7 @@ export const useBudgetState = () => { // 월간 예산을 업데이트하고 일일, 주간도 자동 계산 if (type === 'monthly') { - const ratio = amount / budgetData.monthly.targetAmount; + const ratio = amount / (budgetData.monthly.targetAmount || 1); // 0으로 나누기 방지 const updatedCategoryBudgets: Record = {}; Object.keys(categoryBudgets).forEach(category => { @@ -133,6 +153,7 @@ export const useBudgetState = () => { setSelectedTab, updateTransaction, handleBudgetGoalUpdate, - getCategorySpending + getCategorySpending, + resetBudgetData // 새로 추가된 리셋 함수 }; }; diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index b39dc2d..e1f5421 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -22,7 +22,8 @@ const Index = () => { setSelectedTab, handleBudgetGoalUpdate, updateTransaction, - getCategorySpending + getCategorySpending, + resetBudgetData } = useBudget(); const { user } = useAuth(); @@ -31,25 +32,65 @@ const Index = () => { // 화면이 처음 로드될 때 데이터 초기화 useEffect(() => { - if (!isInitialized) { - // 모든 데이터 완전히 삭제 및 초기화 (두 가지 초기화 함수 모두 반복 호출) - resetAllData(); - resetAllStorageData(); - resetAllData(); // 한번 더 실행해서 확실히 지움 + // 초기화 함수 모음 + const initializeAllData = () => { + console.log('모든 데이터 초기화 시작'); - // localStorage 직접 초기화 (추가 보호) - localStorage.removeItem('budget'); - localStorage.removeItem('budgetData'); - localStorage.removeItem('categoryBudgets'); - localStorage.removeItem('transactions'); - localStorage.removeItem('monthlyExpenses'); - localStorage.removeItem('monthlyData'); + // 여러번 초기화 실행 + for (let i = 0; i < 3; i++) { + // 모든 데이터 완전히 삭제 및 초기화 + resetAllData(); + resetAllStorageData(); + + // localStorage 직접 초기화 (추가 보호) + clearAllAnalyticsData(); + } - // 데이터를 비운 후 빈 값 저장 - localStorage.setItem('transactions', JSON.stringify([])); + // 컨텍스트 데이터 리셋 (마지막에 한번 더) + if (resetBudgetData) { + resetBudgetData(); + } - setIsInitialized(true); console.log('모든 데이터 초기화 완료'); + return true; + }; + + // 분석 페이지 데이터 초기화 함수 + const clearAllAnalyticsData = () => { + // 분석 관련 데이터 강제 삭제 + const analyticsKeys = [ + 'analytics', 'monthlyTotals', 'chartData', + 'expenseHistory', 'budgetHistory', 'categorySpending', + 'monthlyData', 'expenseData', 'analyticData' + ]; + + analyticsKeys.forEach(key => { + localStorage.removeItem(key); + }); + + // 모든 localStorage 순회하며 월간, 차트, 분석 관련 키워드 삭제 + for (let i = localStorage.length - 1; i >= 0; i--) { + const key = localStorage.key(i); + if (key && ( + key.includes('month') || + key.includes('chart') || + key.includes('analytics') || + key.includes('expense') || + key.includes('budget') || + key.includes('total') + )) { + console.log(`분석 데이터 삭제: ${key}`); + localStorage.removeItem(key); + } + } + + return true; + }; + + if (!isInitialized) { + // 데이터 초기화 실행 + const result = initializeAllData(); + setIsInitialized(result); } // 환영 다이얼로그 표시 여부 결정 (데이터 초기화 후) @@ -60,7 +101,7 @@ const Index = () => { // 방문 기록 저장 (초기화 후에 저장) localStorage.setItem('hasVisitedBefore', 'true'); - }, [isInitialized]); + }, [isInitialized, resetBudgetData]); // 환영 팝업 닫기 const handleCloseWelcome = (dontShowAgain: boolean) => { diff --git a/src/utils/storageUtils.ts b/src/utils/storageUtils.ts index 4b82582..7752e82 100644 --- a/src/utils/storageUtils.ts +++ b/src/utils/storageUtils.ts @@ -33,7 +33,9 @@ export const loadBudgetFromStorage = (): number => { // 모든 데이터 완전히 초기화 export const resetAllStorageData = (): void => { - // 모든 Storage 키 삭제 + console.log('완전 초기화 시작 - resetAllStorageData'); + + // 모든 Storage 키 목록 (명시적으로 더 많은 키 추가) const keysToRemove = [ 'transactions', 'budget', @@ -44,20 +46,42 @@ export const resetAllStorageData = (): void => { 'expenseData', 'chartData', 'monthlyData', - 'spendingData' + 'spendingData', + 'categorySpending', + 'monthlyBudget', + 'dailyBudget', + 'weeklyBudget', + 'hasVisitedBefore', + 'dontShowWelcome', + 'monthlyTotals', + 'analytics', + 'expenseHistory', + 'budgetHistory', + 'transactionHistory', + 'lastSync', + 'syncEnabled' ]; // 명시적으로 알려진 키들 삭제 - keysToRemove.forEach(key => localStorage.removeItem(key)); + keysToRemove.forEach(key => { + console.log(`삭제 중: ${key}`); + localStorage.removeItem(key); + }); // 명시적으로 트랜잭션 초기화 localStorage.setItem('transactions', JSON.stringify([])); // 모든 예산 관련, 지출 관련 데이터 검색 및 삭제 - const keywordsToFind = ['budget', 'expense', 'transaction', 'analytic', 'spending', 'chart', 'financial', 'money', 'category']; + const keywordsToFind = [ + 'budget', 'expense', 'transaction', 'analytic', + 'spending', 'chart', 'financial', 'money', + 'category', 'month', 'daily', 'weekly', 'total', + 'sync', 'cache', 'visited', 'welcome', 'target', + 'remain', 'goal', 'analytics', 'data' + ]; // 모든 localStorage 순회하며 키워드 포함된 항목 삭제 - for (let i = 0; i < localStorage.length; i++) { + for (let i = localStorage.length - 1; i >= 0; i--) { const key = localStorage.key(i); if (key) { const lowerKey = key.toLowerCase(); @@ -68,5 +92,24 @@ export const resetAllStorageData = (): void => { } } + // 강제로 빈 데이터로 초기화 + localStorage.setItem('transactions', JSON.stringify([])); + localStorage.setItem('budget', JSON.stringify({total: 0})); + localStorage.setItem('budgetData', JSON.stringify({ + daily: {targetAmount: 0, spentAmount: 0, remainingAmount: 0}, + weekly: {targetAmount: 0, spentAmount: 0, remainingAmount: 0}, + monthly: {targetAmount: 0, spentAmount: 0, remainingAmount: 0} + })); + localStorage.setItem('categoryBudgets', JSON.stringify({ + 식비: 0, + 교통비: 0, + 생활비: 0, + 쇼핑: 0, + 의료: 0, + 여가: 0, + 교육: 0, + 기타: 0 + })); + console.log('모든 저장소 데이터가 완전히 초기화되었습니다.'); };