Refactor: Split Index.tsx into smaller components and hooks

Split the large Index.tsx file into smaller, more manageable components and custom hooks to improve code readability and maintainability. Ensure all functionality remains the same after refactoring.
This commit is contained in:
gpt-engineer-app[bot]
2025-04-05 05:31:21 +00:00
parent c8f0855f6c
commit a326981e5d
6 changed files with 265 additions and 200 deletions

View File

@@ -0,0 +1,76 @@
import { useEffect } from 'react';
/**
* 앱이 포커스를 얻었을 때나 가시성이 변경될 때 데이터를 새로고침하는 커스텀 훅
*/
export const useAppFocusEvents = () => {
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); // 60초마다
return () => {
window.removeEventListener('focus', handleFocus);
document.removeEventListener('visibilitychange', handleVisibilityChange);
clearInterval(refreshInterval);
};
}, []);
};

View File

@@ -0,0 +1,57 @@
import { useEffect } from 'react';
/**
* 앱 첫 실행 시 로컬스토리지 데이터를 로드하는 커스텀 훅
*/
export const useInitialDataLoading = () => {
useEffect(() => {
try {
console.log('Index 페이지 마운트, 데이터 확인 중...');
// 페이지 첫 마운트 시에만 실행되는 로직
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);
}
}, []); // 컴포넌트 마운트 시 한 번만 실행
};

View File

@@ -0,0 +1,35 @@
import { useEffect } from 'react';
import { useAuth } from '@/contexts/auth';
import useNotifications from '@/hooks/useNotifications';
/**
* 앱 초기화 후 환영 메시지 알림을 표시하는 커스텀 훅
*/
export const useWelcomeNotification = (isInitialized: boolean) => {
const { user } = useAuth();
const { addNotification } = useNotifications();
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]);
};