dsfa/[id]/page.tsx (1893 LOC -> 350 LOC) split into 9 components: Section1-5Editor, SDMCoverageOverview, RAGSearchPanel, AddRiskModal, AddMitigationModal. Page is now a thin orchestrator. notfallplan/page.tsx (1890 LOC -> 435 LOC) split into 8 modules: types.ts, ConfigTab, IncidentsTab, TemplatesTab, ExercisesTab, Modals, ApiSections. All under the 500-line hard cap. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
74 lines
2.3 KiB
TypeScript
74 lines
2.3 KiB
TypeScript
'use client'
|
|
|
|
import React, { useState } from 'react'
|
|
import type { MeldeTemplate } from './types'
|
|
|
|
export function TemplatesTab({
|
|
templates,
|
|
setTemplates,
|
|
onSave,
|
|
}: {
|
|
templates: MeldeTemplate[]
|
|
setTemplates: React.Dispatch<React.SetStateAction<MeldeTemplate[]>>
|
|
onSave?: (template: MeldeTemplate) => Promise<void>
|
|
}) {
|
|
const [saving, setSaving] = useState<string | null>(null)
|
|
|
|
async function handleSave(template: MeldeTemplate) {
|
|
if (!onSave) return
|
|
setSaving(template.id)
|
|
try {
|
|
await onSave(template)
|
|
} finally {
|
|
setSaving(null)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div>
|
|
<h3 className="text-lg font-semibold">Melde-Templates</h3>
|
|
<p className="text-sm text-gray-500">
|
|
Vorlagen fuer Meldungen an die Aufsichtsbehoerde (Art. 33) und Benachrichtigung Betroffener (Art. 34).
|
|
</p>
|
|
</div>
|
|
|
|
{templates.map(template => (
|
|
<div key={template.id} className="bg-white rounded-lg border p-6">
|
|
<div className="flex items-center justify-between mb-3">
|
|
<div className="flex items-center gap-2">
|
|
<span className={`px-2 py-1 rounded text-xs font-bold ${
|
|
template.type === 'art33'
|
|
? 'bg-blue-100 text-blue-800'
|
|
: 'bg-purple-100 text-purple-800'
|
|
}`}>
|
|
{template.type === 'art33' ? 'Art. 33' : 'Art. 34'}
|
|
</span>
|
|
<h4 className="font-medium">{template.title}</h4>
|
|
</div>
|
|
{onSave && (
|
|
<button
|
|
onClick={() => handleSave(template)}
|
|
disabled={saving === template.id}
|
|
className="px-3 py-1 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50"
|
|
>
|
|
{saving === template.id ? 'Gespeichert...' : 'Speichern'}
|
|
</button>
|
|
)}
|
|
</div>
|
|
<textarea
|
|
value={template.content}
|
|
onChange={e => {
|
|
setTemplates(prev => prev.map(t =>
|
|
t.id === template.id ? { ...t, content: e.target.value } : t
|
|
))
|
|
}}
|
|
rows={12}
|
|
className="w-full border rounded px-3 py-2 text-sm font-mono"
|
|
/>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|