Files
breakpilot-compliance/admin-compliance/app/sdk/control-library/components/ControlSourceCitation.tsx
Sharang Parnerkar 083792dfd7 refactor(admin): split control-library, iace/mitigations, iace/components, controls pages
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>
2026-04-17 12:24:58 +02:00

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>
)
}