Pilot 001: Operativ checklista — inte dokument, arbetsverktyg
- 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
This commit is contained in:
@@ -4,6 +4,7 @@ import ArtifactViewer from './pages/ArtifactViewer';
|
|||||||
import MissionUpload from './pages/MissionUpload';
|
import MissionUpload from './pages/MissionUpload';
|
||||||
import FieldConsole from './pages/FieldConsole';
|
import FieldConsole from './pages/FieldConsole';
|
||||||
import HealthDashboard from './pages/HealthDashboard';
|
import HealthDashboard from './pages/HealthDashboard';
|
||||||
|
import PilotChecklist from './pages/PilotChecklist';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
@@ -15,6 +16,7 @@ function App() {
|
|||||||
<Link to="/upload">Mission Upload</Link>
|
<Link to="/upload">Mission Upload</Link>
|
||||||
<Link to="/console">Field Console</Link>
|
<Link to="/console">Field Console</Link>
|
||||||
<Link to="/health">Health</Link>
|
<Link to="/health">Health</Link>
|
||||||
|
<Link to="/pilot">Pilot 001</Link>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -24,6 +26,7 @@ function App() {
|
|||||||
<Route path="/artifact/:id" element={<ArtifactViewer />} />
|
<Route path="/artifact/:id" element={<ArtifactViewer />} />
|
||||||
<Route path="/console" element={<FieldConsole />} />
|
<Route path="/console" element={<FieldConsole />} />
|
||||||
<Route path="/health" element={<HealthDashboard />} />
|
<Route path="/health" element={<HealthDashboard />} />
|
||||||
|
<Route path="/pilot" element={<PilotChecklist />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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<React.SetStateAction<ChecklistItem[]>>, id: string) => {
|
||||||
|
setItems(items.map(item =>
|
||||||
|
item.id === id ? { ...item, done: !item.done } : item
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateNote = (items: ChecklistItem[], setItems: React.Dispatch<React.SetStateAction<ChecklistItem[]>>, 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 (
|
||||||
|
<div>
|
||||||
|
<h2>Pilot 001 Checklist</h2>
|
||||||
|
<p style={{ color: '#666', marginBottom: 20 }}>
|
||||||
|
Mål: Kan vi gå från verklighet till verifierat Decision Case utan manuella genvägar?
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<Section
|
||||||
|
title="Fältfas"
|
||||||
|
progress={progress(fieldItems)}
|
||||||
|
items={fieldItems}
|
||||||
|
onToggle={id => toggleItem(fieldItems, setFieldItems, id)}
|
||||||
|
onNote={(id, notes) => updateNote(fieldItems, setFieldItems, id, notes)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Section
|
||||||
|
title="Teknisk fas"
|
||||||
|
progress={progress(techItems)}
|
||||||
|
items={techItems}
|
||||||
|
onToggle={id => toggleItem(techItems, setTechItems, id)}
|
||||||
|
onNote={(id, notes) => updateNote(techItems, setTechItems, id, notes)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Section
|
||||||
|
title="Beslutsfas"
|
||||||
|
progress={progress(decisionItems)}
|
||||||
|
items={decisionItems}
|
||||||
|
onToggle={id => toggleItem(decisionItems, setDecisionItems, id)}
|
||||||
|
onNote={(id, notes) => updateNote(decisionItems, setDecisionItems, id, notes)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Section
|
||||||
|
title="Utvärdering"
|
||||||
|
progress={progress(reviewItems)}
|
||||||
|
items={reviewItems}
|
||||||
|
onToggle={id => toggleItem(reviewItems, setReviewItems, id)}
|
||||||
|
onNote={(id, notes) => updateNote(reviewItems, setReviewItems, id, notes)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div style={{ marginTop: 20, padding: 16, background: '#f0f0f0', borderRadius: 8 }}>
|
||||||
|
<h3>Golden Mission</h3>
|
||||||
|
<p>Markera första riktiga videon som Golden Mission #0001</p>
|
||||||
|
<button style={{
|
||||||
|
padding: '12px 24px',
|
||||||
|
background: '#ffd700',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: 8,
|
||||||
|
cursor: 'pointer',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
}}>
|
||||||
|
Markera som Golden Mission
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Section({
|
||||||
|
title,
|
||||||
|
progress,
|
||||||
|
items,
|
||||||
|
onToggle,
|
||||||
|
onNote,
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
progress: number;
|
||||||
|
items: ChecklistItem[];
|
||||||
|
onToggle: (id: string) => void;
|
||||||
|
onNote: (id: string, notes: string) => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div style={{ marginBottom: 24 }}>
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
|
||||||
|
<h3 style={{ margin: 0 }}>{title}</h3>
|
||||||
|
<span style={{
|
||||||
|
padding: '4px 12px',
|
||||||
|
background: progress === 100 ? '#32cd32' : '#1e90ff',
|
||||||
|
color: 'white',
|
||||||
|
borderRadius: 12,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
}}>
|
||||||
|
{progress}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'grid', gap: 8 }}>
|
||||||
|
{items.map(item => (
|
||||||
|
<div key={item.id} style={{
|
||||||
|
border: '1px solid #ccc',
|
||||||
|
padding: 12,
|
||||||
|
borderRadius: 8,
|
||||||
|
display: 'grid',
|
||||||
|
gap: 8,
|
||||||
|
}}>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={item.done}
|
||||||
|
onChange={() => onToggle(item.id)}
|
||||||
|
style={{ width: 20, height: 20 }}
|
||||||
|
/>
|
||||||
|
<span style={{
|
||||||
|
textDecoration: item.done ? 'line-through' : 'none',
|
||||||
|
color: item.done ? '#999' : '#333',
|
||||||
|
}}>
|
||||||
|
{item.label}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Anteckningar..."
|
||||||
|
value={item.notes}
|
||||||
|
onChange={e => onNote(item.id, e.target.value)}
|
||||||
|
style={{
|
||||||
|
padding: 8,
|
||||||
|
border: '1px solid #ddd',
|
||||||
|
borderRadius: 4,
|
||||||
|
fontSize: 14,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PilotChecklist;
|
||||||
Reference in New Issue
Block a user