import React, { useEffect } from 'react'; import NavBar from '@/components/NavBar'; import AddTransactionButton from '@/components/AddTransactionButton'; import Header from '@/components/Header'; import WelcomeDialog from '@/components/onboarding/WelcomeDialog'; import HomeContent from '@/components/home/HomeContent'; import { useBudget } from '@/contexts/budget/BudgetContext'; import { useAuth } from '@/contexts/auth'; import { useWelcomeDialog } from '@/hooks/useWelcomeDialog'; import { useDataInitialization } from '@/hooks/useDataInitialization'; import { useIsMobile } from '@/hooks/use-mobile'; import useNotifications from '@/hooks/useNotifications'; import SafeAreaContainer from '@/components/SafeAreaContainer'; import { BudgetData } from '@/contexts/budget/types'; // 기본 예산 데이터 (빈 객체 대신 사용할 더미 데이터) const defaultBudgetData: BudgetData = { daily: { targetAmount: 0, spentAmount: 0, remainingAmount: 0 }, weekly: { targetAmount: 0, spentAmount: 0, remainingAmount: 0 }, monthly: { targetAmount: 0, spentAmount: 0, remainingAmount: 0 } }; // 메인 컴포넌트 const Index = () => { const { transactions, budgetData, selectedTab, setSelectedTab, handleBudgetGoalUpdate, updateTransaction, getCategorySpending, resetBudgetData } = useBudget(); const { user } = useAuth(); const { showWelcome, checkWelcomeDialogState, handleCloseWelcome } = useWelcomeDialog(); const { isInitialized } = useDataInitialization(resetBudgetData); const isMobile = useIsMobile(); const { addNotification } = useNotifications(); // 초기화 후 환영 메시지 표시 상태 확인 useEffect(() => { if (isInitialized) { const timeoutId = setTimeout(checkWelcomeDialogState, 500); return () => clearTimeout(timeoutId); } }, [isInitialized, checkWelcomeDialogState]); // 앱 시작시 예시 알림 추가 (실제 앱에서는 필요한 이벤트에 따라 알림 추가) useEffect(() => { try { // 환영 메시지가 이미 표시되었는지 확인하는 키 const welcomeNotificationSent = sessionStorage.getItem('welcomeNotificationSent'); if (isInitialized && user && !welcomeNotificationSent) { // 사용자 로그인 시 알림 예시 (한 번만 실행) const timeoutId = setTimeout(() => { addNotification( '환영합니다!', '젤리의 적자탈출에 오신 것을 환영합니다. 예산을 설정하고 지출을 기록해보세요.' ); // 세션 스토리지에 환영 메시지 표시 여부 저장 sessionStorage.setItem('welcomeNotificationSent', 'true'); }, 2000); return () => clearTimeout(timeoutId); } } catch (error) { console.error('환영 메시지 알림 표시 중 오류:', error); } }, [isInitialized, user, addNotification]); // 페이지가 처음 로드될 때 데이터 로딩 확인 - 에러 방지를 위해 try/catch 추가 useEffect(() => { try { console.log('Index 페이지 마운트, 현재 데이터 상태:'); console.log('트랜잭션:', transactions?.length || 0); console.log('예산 데이터:', budgetData || defaultBudgetData); // 페이지 첫 마운트 시에만 실행되는 로직으로 수정 const isFirstMount = sessionStorage.getItem('initialDataLoaded') !== 'true'; if (isFirstMount) { try { // 백업된 데이터 복구 확인 (메인 데이터가 없는 경우만) if (!localStorage.getItem('budgetData')) { const budgetBackup = localStorage.getItem('budgetData_backup'); if (budgetBackup) { console.log('예산 데이터 백업에서 복구'); localStorage.setItem('budgetData', budgetBackup); } } if (!localStorage.getItem('categoryBudgets')) { const categoryBackup = localStorage.getItem('categoryBudgets_backup'); if (categoryBackup) { console.log('카테고리 예산 백업에서 복구'); localStorage.setItem('categoryBudgets', categoryBackup); } } if (!localStorage.getItem('transactions')) { const transactionBackup = localStorage.getItem('transactions_backup'); if (transactionBackup) { console.log('트랜잭션 백업에서 복구'); localStorage.setItem('transactions', transactionBackup); } } // 한 번만 이벤트 발생 window.dispatchEvent(new Event('transactionUpdated')); window.dispatchEvent(new Event('budgetDataUpdated')); window.dispatchEvent(new Event('categoryBudgetsUpdated')); // 초기 로드 완료 표시 sessionStorage.setItem('initialDataLoaded', 'true'); } catch (error) { console.error('백업 복구 시도 중 오류:', error); } } } catch (error) { console.error('Index 페이지 초기화 중 오류:', error); } }, []); // 의존성 배열 비움 - 컴포넌트 마운트 시 한 번만 실행 // 앱이 포커스를 얻었을 때 데이터를 새로고침 useEffect(() => { const handleFocus = () => { try { console.log('창이 포커스를 얻음 - 데이터 새로고침'); // 이미 리프레시 중인지 확인하는 플래그 if (sessionStorage.getItem('isRefreshing') === 'true') { console.log('이미 리프레시 진행 중, 중복 실행 방지'); return; } try { sessionStorage.setItem('isRefreshing', 'true'); // 이벤트 발생시켜 데이터 새로고침 window.dispatchEvent(new Event('storage')); window.dispatchEvent(new Event('transactionUpdated')); window.dispatchEvent(new Event('budgetDataUpdated')); window.dispatchEvent(new Event('categoryBudgetsUpdated')); // 리프레시 완료 표시 (300ms 후에 플래그 해제) setTimeout(() => { sessionStorage.setItem('isRefreshing', 'false'); }, 300); } catch (e) { console.error('이벤트 발생 오류:', e); sessionStorage.setItem('isRefreshing', 'false'); } } catch (error) { console.error('포커스 이벤트 처리 중 오류:', error); } }; // 포커스 이벤트 window.addEventListener('focus', handleFocus); // 가시성 변경 이벤트 (백그라운드에서 전경으로 돌아올 때) const handleVisibilityChange = () => { try { if (document.visibilityState === 'visible') { console.log('페이지가 다시 보임 - 데이터 새로고침'); handleFocus(); } } catch (error) { console.error('가시성 이벤트 처리 중 오류:', error); } }; document.addEventListener('visibilitychange', handleVisibilityChange); // 정기적인 데이터 새로고침 (60초마다로 변경 - 너무 빈번한 리프레시 방지) const refreshInterval = setInterval(() => { try { if (document.visibilityState === 'visible' && sessionStorage.getItem('isRefreshing') !== 'true') { console.log('정기 새로고침 - 데이터 업데이트'); handleFocus(); } } catch (error) { console.error('정기 새로고침 처리 중 오류:', error); } }, 60000); // 10초에서 60초로 변경 return () => { window.removeEventListener('focus', handleFocus); document.removeEventListener('visibilitychange', handleVisibilityChange); clearInterval(refreshInterval); }; }, []); return (
{/* 첫 사용자 안내 팝업 */}
); }; export default Index;