feat: setup wizard page for first-deploy initialization

- SetupWizardPage: step-by-step config (DB, admin, project)
- Connects directly to AbstractWizard via SSH tunnel (127.0.0.1)
- App.tsx: detect backend health, show wizard if not ready
- Auto-switch wizard to readonly after setup
- Add VITE_WIZARD_PORT build arg
- Add vite-env.d.ts for type safety
This commit is contained in:
zhi
2026-03-06 13:46:46 +00:00
parent 54d4c4379a
commit f8fac48fcc
5 changed files with 288 additions and 0 deletions

View File

@@ -1,7 +1,9 @@
import { useState, useEffect } from 'react'
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
import { useAuth } from '@/hooks/useAuth'
import Sidebar from '@/components/Sidebar'
import LoginPage from '@/pages/LoginPage'
import SetupWizardPage from '@/pages/SetupWizardPage'
import DashboardPage from '@/pages/DashboardPage'
import IssuesPage from '@/pages/IssuesPage'
import IssueDetailPage from '@/pages/IssueDetailPage'
@@ -11,12 +13,41 @@ import ProjectDetailPage from '@/pages/ProjectDetailPage'
import MilestonesPage from '@/pages/MilestonesPage'
import MilestoneDetailPage from '@/pages/MilestoneDetailPage'
import NotificationsPage from '@/pages/NotificationsPage'
import api from '@/services/api'
const WIZARD_PORT = Number(import.meta.env.VITE_WIZARD_PORT) || 18080
type AppState = 'checking' | 'setup' | 'ready'
export default function App() {
const [appState, setAppState] = useState<AppState>('checking')
const { user, loading, login, logout } = useAuth()
const checkBackend = async () => {
try {
await api.get('/health')
setAppState('ready')
} catch {
setAppState('setup')
}
}
useEffect(() => { checkBackend() }, [])
// Checking backend availability
if (appState === 'checking') {
return <div className="loading">...</div>
}
// Backend not ready — show setup wizard
if (appState === 'setup') {
return <SetupWizardPage wizardPort={WIZARD_PORT} onComplete={checkBackend} />
}
// Backend ready but auth loading
if (loading) return <div className="loading">...</div>
// Not logged in
if (!user) {
return (
<BrowserRouter>