feat(admin): add cohort and student management portal
New /admin route (frontend/src/admin/), gated by a separate admin session (scrypt + timingSafeEqual against ADMIN_PASSWORD, no plaintext storage, no new dependency). Covers cohort CRUD + roster + curriculum assignment, and student CRUD + cohort assignment + environment/progress/ attempt views, all under /api/admin/* on the Platform API. main.jsx now does a three-way path split (lab / admin / platform) so the existing, unmodified Lab UI, the student dashboard, and the new admin portal all ship in one Vite bundle without a router dependency.
This commit is contained in:
@@ -2,22 +2,24 @@ import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App.jsx'
|
||||
import PlatformShell from './platform/PlatformShell.jsx'
|
||||
import AdminPortal from './admin/AdminPortal.jsx'
|
||||
import './index.css'
|
||||
|
||||
// Apply saved theme before first paint to avoid flash
|
||||
const savedTheme = localStorage.getItem('kubekosh-theme') || 'dark'
|
||||
document.documentElement.setAttribute('data-theme', savedTheme)
|
||||
|
||||
// This bundle is served both by the persistent identity/platform instance (root paths) and by
|
||||
// This bundle is served both by the lightweight Platform API (root paths + /admin) and by
|
||||
// every ephemeral per-student Lab container (reached via the Gateway at /lab/<token>/) — same
|
||||
// build, same code, split purely by the URL path at runtime. See
|
||||
// docs/PHASE2A_GATEWAY_AND_STUDENT_FLOW.md "Student flow" for why: it lets the existing Lab UI
|
||||
// (<App/>) stay completely unmodified while the new Platform Shell (entry/dashboard/launch)
|
||||
// lives alongside it in the same bundle.
|
||||
const isLabSession = window.location.pathname.startsWith('/lab/')
|
||||
// docs/PHASE2B_ADMIN_AND_PLATFORM_DATA.md "Student/admin flow" for why: it lets the existing
|
||||
// Lab UI (<App/>) stay completely unmodified while the Platform Shell and Admin Portal live
|
||||
// alongside it in the same bundle.
|
||||
const path = window.location.pathname
|
||||
const view = path.startsWith('/lab/') ? 'lab' : path.startsWith('/admin') ? 'admin' : 'platform'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<React.StrictMode>
|
||||
{isLabSession ? <App /> : <PlatformShell />}
|
||||
{view === 'lab' ? <App /> : view === 'admin' ? <AdminPortal /> : <PlatformShell />}
|
||||
</React.StrictMode>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user