snp-batch-validation/frontend/src/App.tsx
HYOJIN b3d9938422 feat: S&P Bypass 피드백 반영 (#123)
- Response JSON 원본 반환 (ApiResponse 래핑 제거, executeRaw 추가)
- 메뉴명 변경: Bypass API → API 관리
- 사용자용 API 카탈로그 페이지 (/bypass-catalog) 추가
- 운영 환경 코드 생성 차단 (app.environment=prod 시 비활성화)
- Bypass API 코드 생성 (compliance, risk 도메인)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 08:35:07 +09:00

80 lines
3.3 KiB
TypeScript

import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom';
import { ToastProvider, useToastContext } from './contexts/ToastContext';
import { ThemeProvider } from './contexts/ThemeContext';
import Navbar from './components/Navbar';
import ToastContainer from './components/Toast';
import LoadingSpinner from './components/LoadingSpinner';
const MainMenu = lazy(() => import('./pages/MainMenu'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Jobs = lazy(() => import('./pages/Jobs'));
const Executions = lazy(() => import('./pages/Executions'));
const ExecutionDetail = lazy(() => import('./pages/ExecutionDetail'));
const Recollects = lazy(() => import('./pages/Recollects'));
const RecollectDetail = lazy(() => import('./pages/RecollectDetail'));
const Schedules = lazy(() => import('./pages/Schedules'));
const Timeline = lazy(() => import('./pages/Timeline'));
const BypassConfig = lazy(() => import('./pages/BypassConfig'));
const BypassCatalog = lazy(() => import('./pages/BypassCatalog'));
const ScreeningGuide = lazy(() => import('./pages/ScreeningGuide'));
const RiskComplianceHistory = lazy(() => import('./pages/RiskComplianceHistory'));
function AppLayout() {
const { toasts, removeToast } = useToastContext();
const location = useLocation();
const isMainMenu = location.pathname === '/';
return (
<div className="h-screen bg-wing-bg text-wing-text flex flex-col overflow-hidden">
{/* 메인 화면: 전체화면, 섹션 페이지: 탭 + 스크롤 콘텐츠 */}
{isMainMenu ? (
<div className="flex-1 overflow-auto px-4">
<Suspense fallback={<LoadingSpinner />}>
<Routes>
<Route path="/" element={<MainMenu />} />
</Routes>
</Suspense>
</div>
) : (
<>
<div className="flex-shrink-0 px-4 pt-4 max-w-7xl mx-auto w-full">
<Navbar />
</div>
<div className="flex-1 overflow-auto px-4 pb-4 pt-6 max-w-7xl mx-auto w-full">
<Suspense fallback={<LoadingSpinner />}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/jobs" element={<Jobs />} />
<Route path="/executions" element={<Executions />} />
<Route path="/executions/:id" element={<ExecutionDetail />} />
<Route path="/recollects" element={<Recollects />} />
<Route path="/recollects/:id" element={<RecollectDetail />} />
<Route path="/schedules" element={<Schedules />} />
<Route path="/schedule-timeline" element={<Timeline />} />
<Route path="/bypass-catalog" element={<BypassCatalog />} />
<Route path="/bypass-config" element={<BypassConfig />} />
<Route path="/screening-guide" element={<ScreeningGuide />} />
<Route path="/risk-compliance-history" element={<RiskComplianceHistory />} />
</Routes>
</Suspense>
</div>
</>
)}
<ToastContainer toasts={toasts} onRemove={removeToast} />
</div>
);
}
export default function App() {
return (
<ThemeProvider>
<BrowserRouter basename="/snp-api">
<ToastProvider>
<AppLayout />
</ToastProvider>
</BrowserRouter>
</ThemeProvider>
);
}