All 4 page.tsx files reduced well below 500 LOC (235/181/158/262) by extracting components and hooks into colocated _components/ and _hooks/ subdirectories. Zero behavior changes — logic relocated verbatim. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
64 lines
3.2 KiB
TypeScript
64 lines
3.2 KiB
TypeScript
'use client'
|
|
|
|
import { ExternalLink, Scale } from 'lucide-react'
|
|
import type { CanonicalControl } from './helpers'
|
|
|
|
export function ControlSourceCitation({ ctrl }: { ctrl: CanonicalControl }) {
|
|
if (!ctrl.source_citation) return null
|
|
|
|
const stype = ctrl.source_citation.source_type
|
|
const colorSet = stype === 'law'
|
|
? { bg: 'bg-blue-50 border-blue-200', icon: 'text-blue-600', title: 'text-blue-900', badge: 'bg-blue-100 text-blue-700' }
|
|
: stype === 'guideline'
|
|
? { bg: 'bg-indigo-50 border-indigo-200', icon: 'text-indigo-600', title: 'text-indigo-900', badge: 'bg-indigo-100 text-indigo-700' }
|
|
: { bg: 'bg-teal-50 border-teal-200', icon: 'text-teal-600', title: 'text-teal-900', badge: 'bg-teal-100 text-teal-700' }
|
|
|
|
const sectionTitle = stype === 'law' ? 'Gesetzliche Grundlage'
|
|
: stype === 'guideline' ? 'Behoerdliche Leitlinie'
|
|
: 'Standard / Best Practice'
|
|
|
|
const badgeText = stype === 'law' ? 'Direkte gesetzliche Pflicht'
|
|
: stype === 'guideline' ? 'Aufsichtsbehoerdliche Empfehlung'
|
|
: stype === 'standard' || (!stype && ctrl.license_rule === 2) ? 'Freiwilliger Standard'
|
|
: !stype && ctrl.license_rule === 1 ? 'Noch nicht klassifiziert' : null
|
|
|
|
return (
|
|
<section className={`border rounded-lg p-4 ${colorSet.bg}`}>
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Scale className={`w-4 h-4 ${colorSet.icon}`} />
|
|
<h3 className={`text-sm font-semibold ${colorSet.title}`}>{sectionTitle}</h3>
|
|
{badgeText && <span className={`text-xs px-2 py-0.5 rounded-full ${colorSet.badge}`}>{badgeText}</span>}
|
|
</div>
|
|
<div className="flex items-start gap-3">
|
|
<div className="flex-1">
|
|
{ctrl.source_citation.source ? (
|
|
<p className="text-sm font-medium text-blue-900 mb-1">
|
|
{ctrl.source_citation.source}
|
|
{ctrl.source_citation.article && ` — ${ctrl.source_citation.article}`}
|
|
{ctrl.source_citation.paragraph && ` ${ctrl.source_citation.paragraph}`}
|
|
</p>
|
|
) : ctrl.generation_metadata?.source_regulation ? (
|
|
<p className="text-sm font-medium text-blue-900 mb-1">{String(ctrl.generation_metadata.source_regulation)}</p>
|
|
) : null}
|
|
{ctrl.source_citation.license && <p className="text-xs text-blue-600">Lizenz: {ctrl.source_citation.license}</p>}
|
|
{ctrl.source_citation.license_notice && <p className="text-xs text-blue-600 mt-0.5">{ctrl.source_citation.license_notice}</p>}
|
|
</div>
|
|
{ctrl.source_citation.url && (
|
|
<a href={ctrl.source_citation.url} target="_blank" rel="noopener noreferrer"
|
|
className="flex items-center gap-1 text-xs text-blue-600 hover:text-blue-800 whitespace-nowrap">
|
|
<ExternalLink className="w-3.5 h-3.5" />Quelle
|
|
</a>
|
|
)}
|
|
</div>
|
|
{ctrl.source_original_text && (
|
|
<details className="mt-3">
|
|
<summary className="text-xs text-blue-600 cursor-pointer hover:text-blue-800">Originaltext anzeigen</summary>
|
|
<p className="text-xs text-gray-600 mt-2 p-2 bg-white rounded border border-blue-100 leading-relaxed max-h-40 overflow-y-auto whitespace-pre-wrap">
|
|
{ctrl.source_original_text}
|
|
</p>
|
|
</details>
|
|
)}
|
|
</section>
|
|
)
|
|
}
|