| import { useState, Suspense, lazy } from 'react'; | |
| import { Target } from 'lucide-react'; | |
| import type { JobConfig, Extras } from './types'; | |
| import { JobRunnerProvider, useJobRunner } from './hooks/JobRunnerProvider'; | |
| const ConfigPage = lazy(() => import('./pages/ConfigPage')); | |
| const ResultsPage = lazy(() => import('./pages/ResultsPage')); | |
| type Tab = 'config'|'results'|'reports'; | |
| function AppInner() { | |
| const [tab, setTab] = useState<Tab>('config'); | |
| const { start } = useJobRunner(); | |
| const run = (cfg: JobConfig, extras: Extras) => { | |
| start(cfg, extras); | |
| setTab('results'); | |
| }; | |
| const tabBtn = (active: boolean) => | |
| `relative px-4 py-2 rounded-xl text-sm font-medium transition-all ${ | |
| active | |
| ? 'text-white bg-gradient-to-r from-indigo-600 via-violet-600 to-fuchsia-600 shadow-lg shadow-indigo-600/20' | |
| : 'text-slate-600 hover:text-slate-800 bg-white/70 backdrop-blur border border-white/30 hover:shadow-md' | |
| }`; | |
| return ( | |
| <div className="min-h-screen bg-[radial-gradient(1200px_800px_at_20%_-10%,#c7d2fe_0%,transparent_60%),radial-gradient(1200px_800px_at_120%_20%,#fbcfe8_0%,transparent_55%)] bg-slate-50"> | |
| <header className="sticky top-0 z-50"> | |
| <div className="backdrop-blur-xl bg-white/60 border-b border-white/40 shadow-[0_10px_30px_-12px_rgba(30,41,59,0.25)] supports-[backdrop-filter]:bg-white/40"> | |
| <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between"> | |
| <div className="flex items-center gap-3"> | |
| <div className="p-2 rounded-xl bg-gradient-to-br from-indigo-600 to-fuchsia-600 shadow-md shadow-indigo-600/30"> | |
| <Target className="w-6 h-6 text-white" /> | |
| </div> | |
| <div> | |
| <h1 className="text-lg sm:text-xl font-bold tracking-tight text-slate-900">AAAI Demo</h1> | |
| <p className="text-xs text-slate-600">Rank Sampling</p> | |
| </div> | |
| </div> | |
| <div className="hidden sm:flex items-center gap-2"> | |
| <span className="px-3 py-1 rounded-full text-xs font-medium bg-emerald-50 text-emerald-700 border border-emerald-200">System Health</span> | |
| <span className="px-3 py-1 rounded-full text-xs font-medium bg-slate-100 text-slate-700 border border-slate-200">v1.0.0</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div className="border-b border-white/40 bg-white/30 backdrop-blur supports-[backdrop-filter]:bg-white/20"> | |
| <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-3 flex gap-3"> | |
| <button className={tabBtn(tab==='config')} onClick={() => setTab('config')}>Config Setting</button> | |
| <button className={tabBtn(tab==='results')} onClick={() => setTab('results')}>Results</button> | |
| </div> | |
| </div> | |
| </header> | |
| <main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8"> | |
| <Suspense fallback={ | |
| <div className="p-8 rounded-2xl border border-white/30 bg-white/60 backdrop-blur text-slate-600"> | |
| Loading | |
| </div> | |
| }> | |
| {/* 改成把 extras 一起傳 */} | |
| {tab === 'config' && <ConfigPage onRun={run} />} | |
| {tab === 'results' && <ResultsPage />} | |
| </Suspense> | |
| </main> | |
| </div> | |
| ); | |
| } | |
| export default function App() { | |
| return ( | |
| <JobRunnerProvider> | |
| <AppInner /> | |
| </JobRunnerProvider> | |
| ); | |
| } | |