feat: Add CI/CD pipeline and code quality improvements
- Add GitHub Actions workflow for automated CI/CD - Configure Node.js 18.x and 20.x matrix testing - Add TypeScript type checking step - Add ESLint code quality checks with enhanced rules - Add Prettier formatting verification - Add production build validation - Upload build artifacts for deployment - Set up automated testing on push/PR - Replace console.log with environment-aware logger - Add pre-commit hooks for code quality - Exclude archive folder from linting 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
129
src/App.tsx
129
src/App.tsx
@@ -1,22 +1,29 @@
|
||||
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';
|
||||
import { Toaster } from './components/ui/toaster';
|
||||
import Index from './pages/Index';
|
||||
import Login from './pages/Login';
|
||||
import Register from './pages/Register';
|
||||
import Settings from './pages/Settings';
|
||||
import Transactions from './pages/Transactions';
|
||||
import Analytics from './pages/Analytics';
|
||||
import ProfileManagement from './pages/ProfileManagement';
|
||||
import NotFound from './pages/NotFound';
|
||||
import PaymentMethods from './pages/PaymentMethods';
|
||||
import HelpSupport from './pages/HelpSupport';
|
||||
import SecurityPrivacySettings from './pages/SecurityPrivacySettings';
|
||||
import NotificationSettings from './pages/NotificationSettings';
|
||||
import ForgotPassword from './pages/ForgotPassword';
|
||||
import AppwriteSettingsPage from './pages/AppwriteSettingsPage';
|
||||
import React, {
|
||||
useEffect,
|
||||
useState,
|
||||
Component,
|
||||
ErrorInfo,
|
||||
ReactNode,
|
||||
} from "react";
|
||||
import { logger } from "@/utils/logger";
|
||||
import { Routes, Route } from "react-router-dom";
|
||||
import { BudgetProvider } from "./contexts/budget/BudgetContext";
|
||||
import { AuthProvider } from "./contexts/auth/AuthProvider";
|
||||
import { Toaster } from "./components/ui/toaster";
|
||||
import Index from "./pages/Index";
|
||||
import Login from "./pages/Login";
|
||||
import Register from "./pages/Register";
|
||||
import Settings from "./pages/Settings";
|
||||
import Transactions from "./pages/Transactions";
|
||||
import Analytics from "./pages/Analytics";
|
||||
import ProfileManagement from "./pages/ProfileManagement";
|
||||
import NotFound from "./pages/NotFound";
|
||||
import PaymentMethods from "./pages/PaymentMethods";
|
||||
import HelpSupport from "./pages/HelpSupport";
|
||||
import SecurityPrivacySettings from "./pages/SecurityPrivacySettings";
|
||||
import NotificationSettings from "./pages/NotificationSettings";
|
||||
import ForgotPassword from "./pages/ForgotPassword";
|
||||
import AppwriteSettingsPage from "./pages/AppwriteSettingsPage";
|
||||
|
||||
// 간단한 오류 경계 컴포넌트 구현
|
||||
interface ErrorBoundaryProps {
|
||||
@@ -40,23 +47,27 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
||||
console.error('애플리케이션 오류:', error, errorInfo);
|
||||
logger.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>
|
||||
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>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -74,13 +85,18 @@ const LoadingScreen: React.FC = () => (
|
||||
);
|
||||
|
||||
// 오류 화면 컴포넌트
|
||||
const ErrorScreen: React.FC<{ error: Error | null; retry: () => void }> = ({ error, retry }) => (
|
||||
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}
|
||||
<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"
|
||||
>
|
||||
재시도
|
||||
@@ -97,46 +113,51 @@ const BasicLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => (
|
||||
);
|
||||
|
||||
function App() {
|
||||
const [appState, setAppState] = useState<'loading' | 'error' | 'ready'>('loading');
|
||||
const [appState, setAppState] = useState<"loading" | "error" | "ready">(
|
||||
"loading"
|
||||
);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const [appwriteEnabled, setAppwriteEnabled] = useState(true);
|
||||
// Appwrite 설정 상태는 향후 사용 예정
|
||||
// const [appwriteEnabled, setAppwriteEnabled] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = "Zellyy Finance";
|
||||
|
||||
|
||||
// 애플리케이션 초기화 시간 지연 설정
|
||||
const timer = setTimeout(() => {
|
||||
setAppState('ready');
|
||||
setAppState("ready");
|
||||
}, 1500); // 1.5초 후 로딩 상태 해제
|
||||
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
|
||||
// 재시도 기능
|
||||
const handleRetry = () => {
|
||||
setAppState('loading');
|
||||
setAppState("loading");
|
||||
setError(null);
|
||||
|
||||
|
||||
// 재시도 시 지연 후 상태 변경
|
||||
setTimeout(() => {
|
||||
setAppState('ready');
|
||||
setAppState("ready");
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
// 로딩 상태 표시
|
||||
if (appState === 'loading') {
|
||||
if (appState === "loading") {
|
||||
return (
|
||||
<ErrorBoundary fallback={<ErrorScreen error={error} retry={handleRetry} />}>
|
||||
<ErrorBoundary
|
||||
fallback={<ErrorScreen error={error} retry={handleRetry} />}
|
||||
>
|
||||
<LoadingScreen />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// 오류 상태 표시
|
||||
if (appState === 'error') {
|
||||
if (appState === "error") {
|
||||
return <ErrorScreen error={error} retry={handleRetry} />;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<ErrorBoundary fallback={<ErrorScreen error={error} retry={handleRetry} />}>
|
||||
<AuthProvider>
|
||||
@@ -152,10 +173,16 @@ function App() {
|
||||
<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="/security-privacy"
|
||||
element={<SecurityPrivacySettings />}
|
||||
/>
|
||||
<Route path="/notifications" element={<NotificationSettings />} />
|
||||
<Route path="/forgot-password" element={<ForgotPassword />} />
|
||||
<Route path="/appwrite-settings" element={<AppwriteSettingsPage />} />
|
||||
<Route
|
||||
path="/appwrite-settings"
|
||||
element={<AppwriteSettingsPage />}
|
||||
/>
|
||||
<Route path="*" element={<NotFound />} />
|
||||
</Routes>
|
||||
</BasicLayout>
|
||||
|
||||
Reference in New Issue
Block a user