From 67a688a699cda768a42ac12af1c941a853184998 Mon Sep 17 00:00:00 2001 From: YASLOGIST <265797509+YASLOGIST@users.noreply.github.com> Date: Fri, 2 Oct 2026 20:10:43 +0000 Subject: [PATCH 1/6] feat: complete V8 control room upgrade Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- LOGISDATA/.env.example | 3 +- LOGISDATA/next.config.ts | 7 +- LOGISDATA/src/app/api/health/route.ts | 5 +- LOGISDATA/src/app/globals.css | 45 ++- LOGISDATA/src/components/HandoutView.tsx | 3 +- LOGISDATA/src/components/Presentation.tsx | 18 +- .../src/components/archived/IntroScreen.tsx | 2 +- .../src/components/sections/AuditSection.tsx | 18 +- .../src/components/sections/DemandSection.tsx | 2 +- .../src/components/sections/HeroSection.tsx | 8 +- .../src/components/sections/RoutesSection.tsx | 13 +- .../components/sections/WarehouseSection.tsx | 2 +- LOGISDATA/src/components/ui/AudioToggle.tsx | 2 +- LOGISDATA/src/components/ui/DatasetExport.tsx | 14 +- LOGISDATA/src/components/ui/KeyboardHelp.tsx | 21 +- .../src/components/ui/LiveTelemetryFeed.tsx | 54 ++- .../src/components/ui/NodeInspectorModal.tsx | 27 +- .../src/components/ui/RecoveryCalculator.tsx | 15 +- .../src/components/ui/ScenarioSwitcher.tsx | 74 ++-- LOGISDATA/src/lib/export.ts | 153 +++++--- LOGISDATA/src/lib/i18n.ts | 28 +- LOGISDATA/src/lib/keyboard.ts | 41 ++ LOGISDATA/src/lib/metrics.ts | 12 +- LOGISDATA/src/lib/sound.ts | 2 + LOGISDATA/src/lib/useNativeDialog.ts | 48 +++ LOGISDATA/tests/e2e/navigation.spec.ts | 25 +- LOGISDATA/tests/setup.ts | 9 +- LOGISDATA/tests/unit/components.test.tsx | 17 +- LOGISDATA/tests/unit/db.test.ts | 21 +- LOGISDATA/tests/unit/export.test.ts | 46 ++- LOGISDATA/tests/unit/health.test.ts | 43 +++ LOGISDATA/tests/unit/keyboard.test.ts | 50 +++ LOGISDATA/tests/unit/metrics.test.ts | 8 + LOGISDATA/tests/unit/newComponents.test.tsx | 223 ++++++++--- .../tests/unit/sectionComponents.test.tsx | 50 +++ LOGISDATA/tests/unit/simulation.test.ts | 33 +- LOGISDATA/tests/unit/sound.test.ts | 11 +- README.md | 87 +++-- UPGRADE_LOG.md | 349 ++++++++++++++++++ docs/ARCHITECTURE.md | 48 +-- docs/UPGRADE.md | 51 ++- 41 files changed, 1389 insertions(+), 299 deletions(-) create mode 100644 LOGISDATA/src/lib/keyboard.ts create mode 100644 LOGISDATA/src/lib/useNativeDialog.ts create mode 100644 LOGISDATA/tests/unit/health.test.ts create mode 100644 LOGISDATA/tests/unit/keyboard.test.ts create mode 100644 UPGRADE_LOG.md diff --git a/LOGISDATA/.env.example b/LOGISDATA/.env.example index d8e1af3..19f63bb 100644 --- a/LOGISDATA/.env.example +++ b/LOGISDATA/.env.example @@ -9,7 +9,8 @@ NEXT_PUBLIC_SITE_URL=http://localhost:3000 # Version string reported by GET /api/health. -NEXT_PUBLIC_APP_VERSION=3.0.0 +# Optional deployment build identifier; defaults to package.json version. +NEXT_PUBLIC_APP_VERSION=3.1.0 # --------------------------------------------------------------------- # Database (optional). Only needed if you add database-backed features. diff --git a/LOGISDATA/next.config.ts b/LOGISDATA/next.config.ts index 6fa6fe3..5d214d0 100644 --- a/LOGISDATA/next.config.ts +++ b/LOGISDATA/next.config.ts @@ -72,11 +72,8 @@ const nextConfig: NextConfig = { return [ { source: "/(.*)", headers: securityHeaders }, { - // Immutable hashed build assets. - source: "/_next/static/:path*", - headers: [{ key: "Cache-Control", value: "public, max-age=31536000, immutable" }], - }, - { + // Next.js owns the immutable cache policy for hashed `/_next/static` + // assets. Overriding it here is redundant and triggers a build warning. source: "/api/:path*", headers: [{ key: "Cache-Control", value: "no-store, max-age=0" }], }, diff --git a/LOGISDATA/src/app/api/health/route.ts b/LOGISDATA/src/app/api/health/route.ts index 935bbe0..7ddc29c 100644 --- a/LOGISDATA/src/app/api/health/route.ts +++ b/LOGISDATA/src/app/api/health/route.ts @@ -1,4 +1,5 @@ import { sql } from "drizzle-orm"; +import packageMetadata from "../../../../package.json"; import { getDb, isDatabaseConfigured } from "@/db"; export const dynamic = "force-dynamic"; @@ -51,7 +52,9 @@ export async function GET(): Promise { const payload: HealthPayload = { ok: database !== "unavailable", service: "logisdata-control-room", - version: process.env.NEXT_PUBLIC_APP_VERSION ?? "3.0.0", + // Package metadata is the release source of truth. Deployments may + // override it with an immutable build identifier when required. + version: process.env.NEXT_PUBLIC_APP_VERSION?.trim() || packageMetadata.version, database, uptimeSeconds: Math.round(process.uptime()), timestamp: new Date().toISOString(), diff --git a/LOGISDATA/src/app/globals.css b/LOGISDATA/src/app/globals.css index 3edb0ac..632a962 100644 --- a/LOGISDATA/src/app/globals.css +++ b/LOGISDATA/src/app/globals.css @@ -871,6 +871,12 @@ button:focus-visible { .verdict-red { color: var(--red); background: rgba(251, 91, 91, 0.06); } .verdict-green { color: var(--emerald); background: rgba(77, 225, 193, 0.06); } +.table-empty-state { + padding: 28px 16px !important; + color: var(--text-muted); + text-align: center; +} + .table-footnote { padding: 11px 17px; border-top: 1px solid var(--line); @@ -2570,6 +2576,15 @@ html[data-theme="light"] { font-size: 0.68rem; } +.telemetry-disclosure { + margin: 0; + padding: 8px 14px; + border-bottom: 1px solid var(--line); + color: var(--text-muted); + font-size: 0.62rem; + line-height: 1.5; +} + .telemetry-filters { display: flex; align-items: center; @@ -2685,17 +2700,33 @@ html[data-theme="light"] { .inspector-overlay { position: fixed; inset: 0; + width: 100%; + max-width: none; + height: 100dvh; + max-height: none; + margin: 0; + border: 0; background: rgba(4, 12, 20, 0.75); + color: inherit; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); - display: flex; + display: none; align-items: center; justify-content: center; - z-index: 100; padding: 18px; animation: overlay-fade 200ms ease both; } +.calculator-overlay[open], +.inspector-overlay[open] { + display: flex; +} + +.calculator-overlay::backdrop, +.inspector-overlay::backdrop { + background: transparent; +} + @keyframes overlay-fade { from { opacity: 0; } to { opacity: 1; } @@ -2761,6 +2792,16 @@ html[data-theme="light"] { gap: 20px; } +.calculator-disclosure { + margin: 0; + padding: 10px 12px; + border-inline-start: 2px solid var(--amber); + background: var(--surface-soft); + color: var(--text-muted); + font-size: 0.68rem; + line-height: 1.6; +} + .calculator-inputs { display: flex; flex-direction: column; diff --git a/LOGISDATA/src/components/HandoutView.tsx b/LOGISDATA/src/components/HandoutView.tsx index 115d1be..376a68d 100644 --- a/LOGISDATA/src/components/HandoutView.tsx +++ b/LOGISDATA/src/components/HandoutView.tsx @@ -80,7 +80,7 @@ function Handout() { aria-pressed={theme === "light"} > {theme === "dark" ?