refactor(admin): split dsfa/[id] and notfallplan page.tsx into colocated components
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>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
'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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user