From e02ea21c9346bccb0cf04863195204b2f09a771f Mon Sep 17 00:00:00 2001 From: Pepe Ziberi Date: Wed, 22 Jul 2026 19:53:37 +0200 Subject: [PATCH] =?UTF-8?q?feat(exercise):=20=C3=9Cbungs-Cockpit=20nutzt?= =?UTF-8?q?=20den=20Modul-Baukasten=20+=20Testplan=20(v1.5.6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Übungen zeigen jetzt zusätzlich zu Zielen/Auswertung dieselben eigenen Tabellen-Module wie Einsätze (z.B. Atemschutz, Kräfte vor Ort) - Live-Sync der Modul-Zeilen auch in der Übung (journal-updated Socket) - docs/TESTPLAN.md: strukturierter Handy-/Einsatz-Testplan Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/TESTPLAN.md | 49 ++++++++++++++++++++ package.json | 2 +- src/components/exercise/exercise-cockpit.tsx | 35 ++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 docs/TESTPLAN.md diff --git a/docs/TESTPLAN.md b/docs/TESTPLAN.md new file mode 100644 index 0000000..c1b99ba --- /dev/null +++ b/docs/TESTPLAN.md @@ -0,0 +1,49 @@ +# Handy-/Einsatz-Testplan + +Kurzer, strukturierter Durchlauf nach jedem grösseren Deploy — am besten einmal +am **Handy** und einmal am **Desktop**. Abhaken, was funktioniert. + +## 1. Einsatz anlegen +- [ ] 🔥 **Neu → Neuer Einsatz**: Dialog öffnet, Standort wird automatisch als Ort vorgeschlagen +- [ ] Titel eingeben → **Erstellen** → Karte startet am Einsatzort +- [ ] Kopfzeile zeigt den Einsatz mittig (Status-Punkt rot, Nr, Titel, Ort), Uhr rechts + +## 2. Karte & Symbole (der wichtige Handy-Test) +- [ ] Symbol **antippen** → Hinweis erscheint → **auf Karte tippen** platziert es +- [ ] Mehrere gleiche Symbole nacheinander setzen → Zähler steigt → **Fertig** +- [ ] Symbol antippen (auf der Karte) → drehen/skalieren/löschen +- [ ] Zeichnen: Pfeil/Linie ziehen → Dialog fragt **Normal / Leitung / Rettungsachse** +- [ ] Eigene **GPS-Position** sichtbar (Punkt + Genauigkeit), Karte bleibt am Einsatzort +- [ ] **Vollbild-Button** (oben links) blendet die Browser-Leiste aus + +## 3. Auto-Bearbeitung +- [ ] Ohne „Bearbeitung starten" direkt zeichnen können (Lock wird automatisch übernommen) +- [ ] Zweites Gerät/Person: sieht Änderungen live, Karte ist dort gesperrt +- [ ] Statuszeile zeigt „Sie bearbeiten" + **freigeben** + +## 4. Cockpit-Module (Baukasten) +- [ ] Journal-Tab → **Module** (als Admin): Modul an/aus, Reihenfolge, eigenes Modul erstellen +- [ ] Neues Modul (z.B. Atemschutz) erscheint im Cockpit, Zeilen anlegen/haken/löschen +- [ ] Änderungen live auf zweitem Gerät sichtbar + +## 5. Journal & Rapport +- [ ] Journal-Eintrag erfassen (mit Vorschlags-Leiste), Erledigt-Haken, Korrektur +- [ ] SOMA/Pendenzen bedienen +- [ ] **Rapport** erzeugen → PDF enthält Journal, SOMA, Pendenzen **und die eigenen Module** +- [ ] Rapport per E-Mail / Drucken + +## 6. Übung +- [ ] 🎓 **Neu → Neue Übung** → Übungs-Cockpit mit Zielen + Auswertung +- [ ] Übungsziele mit Status (Erreicht/Teilweise/…), Auswertung speichert automatisch +- [ ] Eigene Module erscheinen auch in der Übung + +## 7. Offline +- [ ] Einsatz öffnen → Toast „Karte offline verfügbar" abwarten +- [ ] Flugmodus an → Karte im Einsatzgebiet bleibt sichtbar, zeichnen möglich +- [ ] Flugmodus aus → Änderungen werden synchronisiert (Statuszeile „Offline" verschwindet) + +## 8. Beenden +- [ ] **Einsatz beenden** (Kopfzeile/Menü) → In-App-Bestätigung → gespeichert & geschlossen + +--- +_Bei Problemen: betroffenen Schritt notieren + ggf. Screenshot, dann gezielt fixen._ diff --git a/package.json b/package.json index defd68a..0846bd4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lageplan", - "version": "1.5.5", + "version": "1.5.6", "description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation", "private": true, "scripts": { diff --git a/src/components/exercise/exercise-cockpit.tsx b/src/components/exercise/exercise-cockpit.tsx index 72f520f..1fffa9c 100644 --- a/src/components/exercise/exercise-cockpit.tsx +++ b/src/components/exercise/exercise-cockpit.tsx @@ -4,6 +4,9 @@ import { useState, useEffect, useRef, useCallback } from 'react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { useToast } from '@/components/ui/use-toast' +import { getSocket } from '@/lib/socket' +import { TableModule } from '@/components/journal/modules/table-module' +import type { CockpitModule } from '@/lib/modules' import { GraduationCap, Plus, @@ -15,6 +18,7 @@ import { Trash2, ClipboardCheck, Loader2, + Blocks, } from 'lucide-react' type GoalStatus = 'OPEN' | 'REACHED' | 'PARTIAL' | 'MISSED' @@ -74,6 +78,24 @@ export function ExerciseCockpit({ projectId, projectTitle, canEdit, initialEvalu const evalDebounce = useRef(null) const { toast } = useToast() + // Modul-Baukasten: dieselben eigenen Tabellen-Module wie im Einsatz + const [tableModules, setTableModules] = useState([]) + useEffect(() => { + fetch('/api/tenant/modules') + .then(r => r.ok ? r.json() : null) + .then(data => { + if (data?.modules) { + setTableModules(data.modules.filter((m: CockpitModule) => m.enabled && m.type === 'table' && m.columns?.length)) + } + }) + .catch(() => {}) + }, []) + + const notifyModuleChanged = useCallback(() => { + if (!projectId) return + try { getSocket().emit('journal-updated', { projectId }) } catch { /* offline */ } + }, [projectId]) + // Ziele laden const loadGoals = useCallback(async () => { if (!projectId) { @@ -299,6 +321,19 @@ export function ExerciseCockpit({ projectId, projectTitle, canEdit, initialEvalu />

Wird automatisch gespeichert.

+ + {/* Eigene Cockpit-Module (Modul-Baukasten) — z.B. Atemschutz, Kräfte vor Ort */} + {projectId && tableModules.map((mod) => ( +
+

+ + {mod.name} +

+
+ +
+
+ ))} )