From 4edc1d89a7eb5711314fcb2ce7e0f4df0eb1cb3d Mon Sep 17 00:00:00 2001 From: Bernt Date: Thu, 2 Jul 2026 16:34:49 +0000 Subject: [PATCH] =?UTF-8?q?Pilot=20001:=20Operativ=20checklista=20?= =?UTF-8?q?=E2=80=94=20inte=20dokument,=20arbetsverktyg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fältfas: område, varför, infrastruktur, förväntade objekt, tid, problem - Teknisk fas: session, mission, artifacts, upload, metadata, explorer, viewer - Beslutsfas: rätt observation, evidens, beslut, varför inte - Utvärdering: tid, osäkerhet, automation, värde, nästa steg - Golden Mission-knapp för att markera #0001 Mål: Kan vi gå från verklighet till verifierat Decision Case utan manuella genvägar? Stoppregel: Ingen ny arkitektur förrän Pilot 001 genomfört. Next: Starta Pilot 001 — film, upload, verifiera --- packages/ui/src/App.tsx | 3 + packages/ui/src/pages/PilotChecklist.tsx | 204 +++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 packages/ui/src/pages/PilotChecklist.tsx diff --git a/packages/ui/src/App.tsx b/packages/ui/src/App.tsx index 8cd786bca..f81ba4196 100644 --- a/packages/ui/src/App.tsx +++ b/packages/ui/src/App.tsx @@ -4,6 +4,7 @@ import ArtifactViewer from './pages/ArtifactViewer'; import MissionUpload from './pages/MissionUpload'; import FieldConsole from './pages/FieldConsole'; import HealthDashboard from './pages/HealthDashboard'; +import PilotChecklist from './pages/PilotChecklist'; function App() { return ( @@ -15,6 +16,7 @@ function App() { Mission Upload Field Console Health + Pilot 001 @@ -24,6 +26,7 @@ function App() { } /> } /> } /> + } /> ); diff --git a/packages/ui/src/pages/PilotChecklist.tsx b/packages/ui/src/pages/PilotChecklist.tsx new file mode 100644 index 000000000..ea66259d2 --- /dev/null +++ b/packages/ui/src/pages/PilotChecklist.tsx @@ -0,0 +1,204 @@ +/** + * Pilot Checklist + * + * Operativ checklista för fältarbete. + * Inte ett dokument — ett arbetsverktyg. + * + * Pilot 001 Mål: + * Kan vi gå från verklighet till verifierat Decision Case utan manuella genvägar? + */ + +import { useState } from 'react'; + +interface ChecklistItem { + id: string; + label: string; + done: boolean; + notes: string; +} + +const INITIAL_FIELD_ITEMS: ChecklistItem[] = [ + { id: 'area', label: 'Område besökt', done: false, notes: '' }, + { id: 'why', label: 'Varför valdes området?', done: false, notes: '' }, + { id: 'infra', label: 'Typ av infrastruktur observerad', done: false, notes: '' }, + { id: 'expected', label: 'Förväntade objekt', done: false, notes: '' }, + { id: 'duration', label: 'Tid för datainsamling', done: false, notes: '' }, + { id: 'bad', label: 'Vad fungerade dåligt?', done: false, notes: '' }, + { id: 'missing', label: 'Vad saknades i appen?', done: false, notes: '' }, +]; + +const INITIAL_TECH_ITEMS: ChecklistItem[] = [ + { id: 'session', label: 'Field Session skapad', done: false, notes: '' }, + { id: 'mission', label: 'Mission skapad', done: false, notes: '' }, + { id: 'artifacts', label: 'Artifacts registrerade', done: false, notes: '' }, + { id: 'upload', label: 'Upload fungerade', done: false, notes: '' }, + { id: 'metadata', label: 'Metadata extraherad', done: false, notes: '' }, + { id: 'explorer', label: 'Dataset Explorer visar mission', done: false, notes: '' }, + { id: 'viewer', label: 'Artifact Viewer visar detaljer', done: false, notes: '' }, +]; + +const INITIAL_DECISION_ITEMS: ChecklistItem[] = [ + { id: 'observation', label: 'Systemet gav rätt observation', done: false, notes: '' }, + { id: 'evidence', label: 'Tillräcklig evidens fanns', done: false, notes: '' }, + { id: 'decision', label: 'Beslut kunde fattas', done: false, notes: '' }, + { id: 'why-not', label: 'Om inte — varför?', done: false, notes: '' }, +]; + +const INITIAL_REVIEW_ITEMS: ChecklistItem[] = [ + { id: 'time', label: 'Vad tog längst tid?', done: false, notes: '' }, + { id: 'uncertain', label: 'Var blev vi osäkra?', done: false, notes: '' }, + { id: 'auto', label: 'Vilket moment borde automatiseras?', done: false, notes: '' }, + { id: 'value', label: 'Vilket steg skapade mest värde?', done: false, notes: '' }, + { id: 'next', label: 'Vad bygger vi härnäst?', done: false, notes: '' }, +]; + +function PilotChecklist() { + const [fieldItems, setFieldItems] = useState(INITIAL_FIELD_ITEMS); + const [techItems, setTechItems] = useState(INITIAL_TECH_ITEMS); + const [decisionItems, setDecisionItems] = useState(INITIAL_DECISION_ITEMS); + const [reviewItems, setReviewItems] = useState(INITIAL_REVIEW_ITEMS); + + const toggleItem = (items: ChecklistItem[], setItems: React.Dispatch>, id: string) => { + setItems(items.map(item => + item.id === id ? { ...item, done: !item.done } : item + )); + }; + + const updateNote = (items: ChecklistItem[], setItems: React.Dispatch>, id: string, notes: string) => { + setItems(items.map(item => + item.id === id ? { ...item, notes } : item + )); + }; + + const progress = (items: ChecklistItem[]) => + Math.round((items.filter(i => i.done).length / items.length) * 100); + + return ( +
+

Pilot 001 Checklist

+

+ Mål: Kan vi gå från verklighet till verifierat Decision Case utan manuella genvägar? +

+ +
toggleItem(fieldItems, setFieldItems, id)} + onNote={(id, notes) => updateNote(fieldItems, setFieldItems, id, notes)} + /> + +
toggleItem(techItems, setTechItems, id)} + onNote={(id, notes) => updateNote(techItems, setTechItems, id, notes)} + /> + +
toggleItem(decisionItems, setDecisionItems, id)} + onNote={(id, notes) => updateNote(decisionItems, setDecisionItems, id, notes)} + /> + +
toggleItem(reviewItems, setReviewItems, id)} + onNote={(id, notes) => updateNote(reviewItems, setReviewItems, id, notes)} + /> + +
+

Golden Mission

+

Markera första riktiga videon som Golden Mission #0001

+ +
+
+ ); +} + +function Section({ + title, + progress, + items, + onToggle, + onNote, +}: { + title: string; + progress: number; + items: ChecklistItem[]; + onToggle: (id: string) => void; + onNote: (id: string, notes: string) => void; +}) { + return ( +
+
+

{title}

+ + {progress}% + +
+ +
+ {items.map(item => ( +
+
+ onToggle(item.id)} + style={{ width: 20, height: 20 }} + /> + + {item.label} + +
+ onNote(item.id, e.target.value)} + style={{ + padding: 8, + border: '1px solid #ddd', + borderRadius: 4, + fontSize: 14, + }} + /> +
+ ))} +
+
+ ); +} + +export default PilotChecklist;