feat(demo): add Demo Guide (8-step guided tour) and scenario overview
Adds a compact "Probeer een demonstratiescenario" page listing the 5 named scenarios with live readiness from the manifest, plus a Demo Guide side panel (bottom sheet on mobile) that walks an Operations Manager through all 8 steps with per-step context, live-resolved routes, sessionStorage progress, and a "Demo opnieuw voorbereiden" restart. Login's guided-demo CTA now actually opens the guide. Fixes a real mobile topbar overflow the new guide trigger introduced.
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Link, useSearchParams } from "react-router-dom";
|
||||
import { api } from "../api/client";
|
||||
import type { Dashboard as DashboardData, IntegrationStatus, KnowledgeHealth } from "../api/types";
|
||||
import { useAuth } from "../context/AuthContext";
|
||||
import { useDemoGuide } from "../context/DemoGuideContext";
|
||||
import { useDemoManifest } from "../context/DemoManifestContext";
|
||||
import { SeverityBadge, StatusBadge } from "../components/Badge";
|
||||
import { Icon } from "../components/Icons";
|
||||
import { ErrorState, IntegrationMark, LoadingState, PageHeader, SectionHeading } from "../components/PageChrome";
|
||||
@@ -26,8 +28,21 @@ function localTime(value: string, withDate = false) {
|
||||
|
||||
export function Dashboard() {
|
||||
const { user } = useAuth();
|
||||
const { manifest } = useDemoManifest();
|
||||
const { openGuide, restart, currentIndex, completed, totalSteps } = useDemoGuide();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const canSeeQuality = user?.role === "operations_manager";
|
||||
const canSeeAutomation = user?.role === "operations_manager";
|
||||
|
||||
useEffect(() => {
|
||||
if (searchParams.get("guide") === "start") {
|
||||
restart();
|
||||
openGuide();
|
||||
setSearchParams({}, { replace: true });
|
||||
}
|
||||
// Only ever react to the initial `?guide=start` marker set by the login screen's
|
||||
// "Start begeleide demo" CTA, so this intentionally runs once on mount.
|
||||
}, []);
|
||||
const [data, setData] = useState<DashboardData | null>(null);
|
||||
const [knowledge, setKnowledge] = useState<KnowledgeHealth | null>(null);
|
||||
const [integrationStatus, setIntegrationStatus] = useState<IntegrationStatus | null>(null);
|
||||
@@ -64,6 +79,26 @@ export function Dashboard() {
|
||||
<div className="page dashboard-page">
|
||||
<PageHeader eyebrow="Operations / Live overview" title="Good morning. Here’s the fleet." description="Readiness, exceptions and hand-offs across today’s operation." actions={<Link className="button button-secondary" to="/vehicles"><Icon name="fleet" /> View fleet</Link>} />
|
||||
|
||||
<section className="demo-start-panel" aria-label="Demo starten">
|
||||
<div>
|
||||
<Icon name="spark" />
|
||||
<div>
|
||||
<strong>Probeer een demonstratiescenario</strong>
|
||||
<span>
|
||||
{manifest ? `${manifest.scenarios.filter((s) => s.ready).length} van ${manifest.scenarios.length} scenario's klaar voor demo.` : "Vijf afgebakende scenario's."}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="demo-start-actions">
|
||||
{user?.role === "operations_manager" && (
|
||||
<button type="button" className="button button-secondary" onClick={openGuide}>
|
||||
<Icon name="spark" /> {completed.size > 0 ? `Verder met demo-gids (${currentIndex + 1}/${totalSteps})` : "Start demo-gids"}
|
||||
</button>
|
||||
)}
|
||||
<Link className="button button-primary" to="/scenarios">Bekijk scenario's <Icon name="chevron" /></Link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="readiness-band" aria-labelledby="readiness-heading">
|
||||
<div className="readiness-label">
|
||||
<span className="live-indicator" />
|
||||
|
||||
Reference in New Issue
Block a user