2026-04-07 10:21:11 +02:00
|
|
|
import { useState } from 'react'
|
2026-04-07 10:15:13 +02:00
|
|
|
import { FlaskConical } from 'lucide-react'
|
|
|
|
|
import { Link } from 'react-router-dom'
|
2026-04-07 10:21:11 +02:00
|
|
|
import { resolvePilotWidgetsForRender } from '../pilot/widgetRegistry'
|
|
|
|
|
import { loadPilotLayout } from '../pilot/pilotLayoutStorage'
|
|
|
|
|
import PilotVizAdminCard from '../components/pilot/PilotVizAdminCard'
|
2026-04-07 10:15:13 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Pilot: Widget-Schicht (Layer 3b) parallel zum produktiven Dashboard.
|
|
|
|
|
*/
|
|
|
|
|
export default function PilotVizPage() {
|
2026-04-07 10:21:11 +02:00
|
|
|
const [layout, setLayout] = useState(() => loadPilotLayout())
|
|
|
|
|
const widgets = resolvePilotWidgetsForRender(layout)
|
2026-04-07 10:15:13 +02:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div style={{ paddingBottom: 96, textAlign: 'left', maxWidth: 900, margin: '0 auto' }}>
|
|
|
|
|
<div style={{ marginBottom: 20 }}>
|
|
|
|
|
<Link
|
|
|
|
|
to="/settings"
|
|
|
|
|
className="btn btn-secondary"
|
|
|
|
|
style={{ display: 'inline-flex', marginBottom: 12, textDecoration: 'none' }}
|
|
|
|
|
>
|
|
|
|
|
← Einstellungen
|
|
|
|
|
</Link>
|
|
|
|
|
<h1 className="page-title" style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
|
|
|
|
<FlaskConical size={26} color="var(--accent)" />
|
|
|
|
|
Pilot: Visualisierungs-Module
|
|
|
|
|
</h1>
|
|
|
|
|
<p style={{ fontSize: 14, color: 'var(--text2)', lineHeight: 1.6, marginTop: 8 }}>
|
2026-04-07 10:21:11 +02:00
|
|
|
Testumgebung für die Widget-Registry. Konfiguration unten; produktive Übersicht und Verlauf sind unverändert.
|
2026-04-07 10:15:13 +02:00
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-04-07 10:21:11 +02:00
|
|
|
<PilotVizAdminCard layout={layout} onLayoutChange={setLayout} />
|
|
|
|
|
|
|
|
|
|
{widgets.length === 0 ? (
|
|
|
|
|
<div className="card section-gap" style={{ textAlign: 'center', padding: 24 }}>
|
|
|
|
|
<p style={{ fontSize: 14, color: 'var(--text2)', margin: 0 }}>
|
|
|
|
|
Keine Widgets sichtbar. Aktiviere mindestens eines in der <strong>Widget-Konfiguration</strong> oben.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
widgets.map((def) => {
|
|
|
|
|
const { Component } = def
|
|
|
|
|
return (
|
|
|
|
|
<section key={def.id} className="card section-gap" style={{ overflow: 'hidden' }}>
|
|
|
|
|
<div className="card-title">{def.title}</div>
|
|
|
|
|
{def.description && (
|
|
|
|
|
<p style={{ fontSize: 13, color: 'var(--text2)', marginTop: 4, marginBottom: 14, lineHeight: 1.5 }}>
|
|
|
|
|
{def.description}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
<Component />
|
|
|
|
|
</section>
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
)}
|
2026-04-07 10:15:13 +02:00
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|