feat(ui): redesign GeoIntel as Atlas Workbench
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-19 14:24:54 +02:00
parent ea27873dce
commit 87345f1a8c
19 changed files with 1817 additions and 631 deletions
+5 -5
View File
@@ -1868,8 +1868,8 @@ export function MapWorkspace({
<header className="geo-explorer-header">
<div>
<p className="eyebrow">{activeScopeLabel} · geografische verkenner</p>
<h2>Wat bevindt zich in dit gebied?</h2>
<p>Kies een datathema, teken een rechthoek en lees de beschikbare gegevens meteen uit.</p>
<h2>Gebied analyseren</h2>
<p>Kies een thema, teken een rechthoek en lees de beschikbare gegevens.</p>
</div>
<div className="geo-analysis-mode" role="tablist" aria-label="Analyseperiode">
<button
@@ -1932,8 +1932,8 @@ export function MapWorkspace({
<div className="geo-panel-heading">
<span>1</span>
<div>
<h3>Kies een datathema</h3>
<p>Dit zijn databronnen, geen AI-modellen.</p>
<h3>Thema</h3>
<p>Kies welke gegevens u wilt meten.</p>
</div>
</div>
<div className="geo-loaded-scope" aria-label="Ingeladen regiobereik">
@@ -2307,7 +2307,7 @@ export function MapWorkspace({
<div className="geo-panel-heading">
<span>3</span>
<div>
<h3>Resultaten</h3>
<h3>Inzichten</h3>
<p>Alleen gemeten gegevens uit beschikbare bronnen.</p>
</div>
</div>
@@ -0,0 +1,90 @@
import {
Activity,
Bot,
Database,
Download,
Map,
ScanSearch,
Settings,
ShieldCheck,
type LucideIcon,
} from 'lucide-react'
import type { WorkspaceKey } from '../overview/OverviewWorkspace'
export interface WorkspaceNavigationItem {
key: WorkspaceKey
label: string
description: string
}
export interface WorkspaceNavigationGroup {
label: string
keys: WorkspaceKey[]
}
interface WorkbenchNavigationProps {
activeWorkspace: WorkspaceKey
groups: WorkspaceNavigationGroup[]
items: WorkspaceNavigationItem[]
onSelect: (workspace: WorkspaceKey) => void
}
const workspaceIcons: Record<WorkspaceKey, LucideIcon> = {
map: Map,
data: Database,
assistant: Bot,
analysis: ShieldCheck,
ai: ScanSearch,
exports: Download,
overview: Activity,
system: Settings,
}
export function WorkbenchNavigation({
activeWorkspace,
groups,
items,
onSelect,
}: WorkbenchNavigationProps): JSX.Element {
return (
<aside className="workbench-sidebar" aria-label="Navigatie van de werkruimte">
<div className="sidebar-brand" aria-label="GeoIntel">
<span className="brand-mark" aria-hidden="true">GI</span>
<span className="sidebar-brand-copy">
<strong>GeoIntel</strong>
<small>Atlas Workbench</small>
</span>
</div>
<nav aria-label="Hoofdonderdelen">
{groups.map((group) => (
<div className="nav-group" key={group.label}>
<p className="nav-section-label">{group.label}</p>
{group.keys.map((key) => {
const item = items.find((candidate) => candidate.key === key)
if (!item) {
return null
}
const Icon = workspaceIcons[item.key]
return (
<button
key={item.key}
type="button"
className={item.key === activeWorkspace ? 'nav-item nav-item-active' : 'nav-item'}
onClick={() => onSelect(item.key)}
aria-current={item.key === activeWorkspace ? 'page' : undefined}
aria-label={`Open ${item.label}: ${item.description}`}
title={item.description}
data-testid={`workspace-nav-${item.key}`}
>
<Icon className="nav-item-icon" aria-hidden="true" strokeWidth={1.8} />
<span>{item.label}</span>
</button>
)
})}
</div>
))}
</nav>
</aside>
)
}