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:
hansoo
2025-07-12 15:27:54 +09:00
parent 6a208d6b06
commit 9851627ff1
411 changed files with 14458 additions and 8680 deletions

View File

@@ -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>