Implement error handling and loading states for Appwrite integration
This commit is contained in:
172
src/App.tsx
172
src/App.tsx
@@ -1,5 +1,4 @@
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState, Suspense, Component, ErrorInfo, ReactNode } from 'react';
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
import { BudgetProvider } from './contexts/budget/BudgetContext';
|
||||
import { AuthProvider } from './contexts/auth/AuthProvider';
|
||||
@@ -19,35 +18,150 @@ import NotificationSettings from './pages/NotificationSettings';
|
||||
import ForgotPassword from './pages/ForgotPassword';
|
||||
import AppwriteSettingsPage from './pages/AppwriteSettingsPage';
|
||||
|
||||
function App() {
|
||||
useEffect(() => {
|
||||
document.title = "적자 탈출 가계부";
|
||||
}, []);
|
||||
// 간단한 오류 경계 컴포넌트 구현
|
||||
interface ErrorBoundaryProps {
|
||||
children: ReactNode;
|
||||
fallback?: ReactNode;
|
||||
}
|
||||
|
||||
return (
|
||||
<AuthProvider>
|
||||
<BudgetProvider>
|
||||
<div className="App">
|
||||
<Routes>
|
||||
<Route path="/" element={<Index />} />
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route path="/settings" element={<Settings />} />
|
||||
<Route path="/transactions" element={<Transactions />} />
|
||||
<Route path="/analytics" element={<Analytics />} />
|
||||
<Route path="/profile" element={<ProfileManagement />} />
|
||||
<Route path="/payment-methods" element={<PaymentMethods />} />
|
||||
<Route path="/help-support" element={<HelpSupport />} />
|
||||
<Route path="/security-privacy" element={<SecurityPrivacySettings />} />
|
||||
<Route path="/notifications" element={<NotificationSettings />} />
|
||||
<Route path="/forgot-password" element={<ForgotPassword />} />
|
||||
<Route path="/appwrite-settings" element={<AppwriteSettingsPage />} />
|
||||
<Route path="*" element={<NotFound />} />
|
||||
</Routes>
|
||||
<Toaster />
|
||||
interface ErrorBoundaryState {
|
||||
hasError: boolean;
|
||||
error: Error | null;
|
||||
}
|
||||
|
||||
class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
constructor(props: ErrorBoundaryProps) {
|
||||
super(props);
|
||||
this.state = { hasError: false, error: null };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
|
||||
return { hasError: true, error };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
||||
console.error('애플리케이션 오류:', error, errorInfo);
|
||||
}
|
||||
|
||||
render(): ReactNode {
|
||||
if (this.state.hasError) {
|
||||
// 오류 발생 시 대체 UI 표시
|
||||
return this.props.fallback || (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen p-4 text-center">
|
||||
<h2 className="text-xl font-bold mb-4">앱 로딩 중 오류가 발생했습니다</h2>
|
||||
<p className="mb-4">잠시 후 다시 시도해주세요.</p>
|
||||
<button
|
||||
onClick={() => window.location.reload()}
|
||||
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
|
||||
>
|
||||
새로고침
|
||||
</button>
|
||||
</div>
|
||||
</BudgetProvider>
|
||||
</AuthProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
// 로딩 상태 표시 컴포넌트
|
||||
const LoadingScreen: React.FC = () => (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen p-4 text-center bg-neuro-background">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500 mb-4"></div>
|
||||
<h2 className="text-xl font-bold mb-2">Zellyy Finance</h2>
|
||||
<p className="text-gray-600">앱을 로딩하고 있습니다...</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
// 오류 화면 컴포넌트
|
||||
const ErrorScreen: React.FC<{ error: Error | null; retry: () => void }> = ({ error, retry }) => (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen p-4 text-center bg-neuro-background">
|
||||
<div className="text-red-500 text-5xl mb-4">⚠️</div>
|
||||
<h2 className="text-xl font-bold mb-4">애플리케이션 오류</h2>
|
||||
<p className="text-center mb-6">{error?.message || '애플리케이션 로딩 중 오류가 발생했습니다.'}</p>
|
||||
<button
|
||||
onClick={retry}
|
||||
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
|
||||
>
|
||||
재시도
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
// 기본 레이아웃 컴포넌트 - 인증 없이도 표시 가능
|
||||
const BasicLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => (
|
||||
<div className="App">
|
||||
{children}
|
||||
<Toaster />
|
||||
</div>
|
||||
);
|
||||
|
||||
function App() {
|
||||
const [appState, setAppState] = useState<'loading' | 'error' | 'ready'>('loading');
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const [appwriteEnabled, setAppwriteEnabled] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = "Zellyy Finance";
|
||||
|
||||
// 애플리케이션 초기화 시간 지연 설정
|
||||
const timer = setTimeout(() => {
|
||||
setAppState('ready');
|
||||
}, 1500); // 1.5초 후 로딩 상태 해제
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// 재시도 기능
|
||||
const handleRetry = () => {
|
||||
setAppState('loading');
|
||||
setError(null);
|
||||
|
||||
// 재시도 시 지연 후 상태 변경
|
||||
setTimeout(() => {
|
||||
setAppState('ready');
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
// 로딩 상태 표시
|
||||
if (appState === 'loading') {
|
||||
return (
|
||||
<ErrorBoundary fallback={<ErrorScreen error={error} retry={handleRetry} />}>
|
||||
<LoadingScreen />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
// 오류 상태 표시
|
||||
if (appState === 'error') {
|
||||
return <ErrorScreen error={error} retry={handleRetry} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<ErrorBoundary fallback={<ErrorScreen error={error} retry={handleRetry} />}>
|
||||
<AuthProvider>
|
||||
<BudgetProvider>
|
||||
<BasicLayout>
|
||||
<Routes>
|
||||
<Route path="/" element={<Index />} />
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route path="/settings" element={<Settings />} />
|
||||
<Route path="/transactions" element={<Transactions />} />
|
||||
<Route path="/analytics" element={<Analytics />} />
|
||||
<Route path="/profile" element={<ProfileManagement />} />
|
||||
<Route path="/payment-methods" element={<PaymentMethods />} />
|
||||
<Route path="/help-support" element={<HelpSupport />} />
|
||||
<Route path="/security-privacy" element={<SecurityPrivacySettings />} />
|
||||
<Route path="/notifications" element={<NotificationSettings />} />
|
||||
<Route path="/forgot-password" element={<ForgotPassword />} />
|
||||
<Route path="/appwrite-settings" element={<AppwriteSettingsPage />} />
|
||||
<Route path="*" element={<NotFound />} />
|
||||
</Routes>
|
||||
</BasicLayout>
|
||||
</BudgetProvider>
|
||||
</AuthProvider>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user