feat(exercise): Übungs-Cockpit nutzt den Modul-Baukasten + Testplan (v1.5.6)
- Ü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) <noreply@anthropic.com>
This commit is contained in:
@@ -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<NodeJS.Timeout | null>(null)
|
||||
const { toast } = useToast()
|
||||
|
||||
// Modul-Baukasten: dieselben eigenen Tabellen-Module wie im Einsatz
|
||||
const [tableModules, setTableModules] = useState<CockpitModule[]>([])
|
||||
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
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground mt-1">Wird automatisch gespeichert.</p>
|
||||
</section>
|
||||
|
||||
{/* Eigene Cockpit-Module (Modul-Baukasten) — z.B. Atemschutz, Kräfte vor Ort */}
|
||||
{projectId && tableModules.map((mod) => (
|
||||
<section key={mod.id}>
|
||||
<h3 className="text-sm font-semibold flex items-center gap-2 mb-3 text-foreground/80">
|
||||
<Blocks className="w-4 h-4 text-blue-600" />
|
||||
{mod.name}
|
||||
</h3>
|
||||
<div className="border rounded-lg bg-white dark:bg-card overflow-hidden">
|
||||
<TableModule projectId={projectId} module={mod} canEdit={canEdit} notifyChanged={notifyModuleChanged} />
|
||||
</div>
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user