trainlog/web/src/app/App.tsx

58 lines
2.9 KiB
TypeScript

import { useCallback, useEffect, useState } from 'react'
import { fetchHealth, type Health } from '../api/health'
import { fetchDashboard, type DashboardSnapshot } from '../api/dashboard'
import { Footer } from '../components/Footer'
import { Header } from '../components/Header'
import { DashboardPage } from '../routes/DashboardPage'
import { PlaceholderPage } from '../routes/PlaceholderPage'
import type { RouteId } from './routes'
import { useRoute } from './useRoute'
const placeholderContent: Record<Exclude<RouteId, 'dashboard'>, [string, string, string]> = {
analysis: ['Analyse', 'COMPRENDRE', 'Les analyses détaillées apparaîtront ici lorsque leurs read models Core seront disponibles.'],
programs: ['Programmes', 'PRÉPARER', 'La préparation des programmes utilisera des command services Core explicites.'],
sessions: ['Séances', 'ORGANISER', 'Les séances préparées et terminées seront présentées sans confondre plan et réalisé.'],
exercises: ['Exercices', 'EXPLORER', 'Le catalogue canonique des exercices sera consultable depuis cette page.'],
}
export function App() {
const [route, navigate] = useRoute()
const [health, setHealth] = useState<Health | null>(null)
const [healthPending, setHealthPending] = useState(true)
const [healthFailed, setHealthFailed] = useState(false)
const [dashboard, setDashboard] = useState<DashboardSnapshot | null>(null)
const [dashboardPending, setDashboardPending] = useState(true)
const [dashboardFailed, setDashboardFailed] = useState(false)
const reloadDashboard = useCallback(() => {
fetchDashboard().then((value) => { setDashboard(value); setDashboardFailed(false) })
.catch(() => setDashboardFailed(true)).finally(() => setDashboardPending(false))
}, [])
useEffect(() => {
const controller = new AbortController()
fetchHealth(controller.signal).then((value) => {
setHealth(value)
setHealthFailed(false)
}).catch(() => setHealthFailed(true)).finally(() => setHealthPending(false))
fetchDashboard(controller.signal).then((value) => {
setDashboard(value); setDashboardFailed(false)
}).catch(() => {
setDashboard(null); setDashboardFailed(true)
}).finally(() => setDashboardPending(false))
return () => controller.abort()
}, [])
const content = route.id === 'dashboard' ? <DashboardPage dashboard={dashboard} pending={dashboardPending} failed={dashboardFailed} /> :
<PlaceholderPage title={placeholderContent[route.id][0]}
eyebrow={placeholderContent[route.id][1]}
description={placeholderContent[route.id][2]} />
return (
<div className="app-shell">
<a className="skip-link" href="#main-content">Aller au contenu</a>
<Header activeRoute={route} onNavigate={navigate} onSyncCommitted={reloadDashboard} />
<main className="app-main" id="main-content">{content}</main>
<Footer health={health} healthPending={healthPending} healthFailed={healthFailed} dashboard={dashboard} />
</div>
)
}