From eedee83b497386efafc13398aa2e8340f48cc850 Mon Sep 17 00:00:00 2001 From: Benjamin Sutter Date: Sun, 24 May 2026 01:18:49 +0200 Subject: [PATCH] =?UTF-8?q?refactor:=20extract=20SignalSourcesSection=20fr?= =?UTF-8?q?om=20FutureAvailabilityContextPanel=20(314=20=E2=86=92=20227=20?= =?UTF-8?q?lines)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- .../FutureAvailabilityContextPanel.tsx | 108 ++-------------- .../match-detail/SignalSourcesSection.tsx | 117 ++++++++++++++++++ 2 files changed, 127 insertions(+), 98 deletions(-) create mode 100644 src/components/match-detail/SignalSourcesSection.tsx diff --git a/src/components/match-detail/FutureAvailabilityContextPanel.tsx b/src/components/match-detail/FutureAvailabilityContextPanel.tsx index 19c0432..7e529c8 100644 --- a/src/components/match-detail/FutureAvailabilityContextPanel.tsx +++ b/src/components/match-detail/FutureAvailabilityContextPanel.tsx @@ -1,11 +1,9 @@ -import { Box, Button, Chip, Divider, LinearProgress, Paper, Typography } from '@mui/material' +import { Box, Chip, Divider, LinearProgress, Paper, Typography } from '@mui/material' import { AlertTriangle, Calendar, CheckCircle2, Clock, - ExternalLink, - Globe, ShieldCheck, Sparkles, TrendingUp, @@ -14,7 +12,8 @@ import { import type { Match } from '../../domain/match' import type { FutureSignal } from '../../domain/futureSignal' import { SIGNAL_TYPE_LABELS, SIGNAL_ACTION, SOURCE_META } from './futureAvailabilityConstants' -import { CREDIBILITY_META, SENSITIVITY_META, RISK_META, ageLabel, domainLabel } from './futureAvailabilityContextUtils' +import { CREDIBILITY_META, SENSITIVITY_META, RISK_META, ageLabel } from './futureAvailabilityContextUtils' +import { SignalSourcesSection } from './SignalSourcesSection' interface Props { match: Match @@ -197,100 +196,13 @@ export function FutureAvailabilityContextPanel({ match: _match, signal }: Props) {/* ── 7. Quellen & Belege ───────────────────────────────────────────── */} - - - - Quellen & Belege - - - {/* Primary source metadata — always shown */} - - {sourceMeta && ( - - {sourceMeta.icon} - {sourceMeta.label} - - )} - {credMeta && ( - - - {credMeta.label} - - )} - {signal.source.publishedAt && ( - - - - {new Date(signal.source.publishedAt).toLocaleDateString('de-CH', { day: '2-digit', month: 'long', year: 'numeric' })} - - - )} - - - {/* Verified contract special box */} - {isVerifiedContract && ( - - - - Vertragsende aus internem ERP bestätigt - - - - Verwaltung hat Marktfreigabe erteilt - - - )} - - {/* All source URLs */} - {allSourceUrls.length > 0 ? ( - - {allSourceUrls.map((url, i) => ( - - ))} - - ) : ( - - - Kein direkter Quellenlink verfügbar — Signal basiert auf aggregierten {sourceMeta?.label ?? 'Marktdaten'}. - - - )} - - {/* Evidence extraction date */} - {signal.evidence?.extractedAt && ( - - - - Daten extrahiert: {new Date(signal.evidence.extractedAt).toLocaleDateString('de-CH', { day: '2-digit', month: 'short', year: 'numeric' })} - - - )} - - {/* Evidence summary */} - {signal.evidence?.summary && ( - - Evidenz-Zusammenfassung - {signal.evidence.summary} - - )} - + {/* ── Footer ──────────────────────────────────────────────────────────── */} diff --git a/src/components/match-detail/SignalSourcesSection.tsx b/src/components/match-detail/SignalSourcesSection.tsx new file mode 100644 index 0000000..4905520 --- /dev/null +++ b/src/components/match-detail/SignalSourcesSection.tsx @@ -0,0 +1,117 @@ +import { Box, Button, Typography } from '@mui/material' +import { Calendar, Clock, ExternalLink, Globe, ShieldCheck } from 'lucide-react' +import type { FutureSignal } from '../../domain/futureSignal' +import { domainLabel } from './futureAvailabilityContextUtils' + +interface SignalSourcesSectionProps { + sourceMeta: { label: string; icon: React.ReactNode; badge?: string; description?: string } | null + credMeta: { label: string; color: string } | null + isVerifiedContract: boolean + allSourceUrls: string[] + signal: FutureSignal +} + +export function SignalSourcesSection({ + sourceMeta, + credMeta, + isVerifiedContract, + allSourceUrls, + signal, +}: SignalSourcesSectionProps) { + return ( + + + + Quellen & Belege + + + {/* Primary source metadata — always shown */} + + {sourceMeta && ( + + {sourceMeta.icon} + {sourceMeta.label} + + )} + {credMeta && ( + + + {credMeta.label} + + )} + {signal.source.publishedAt && ( + + + + {new Date(signal.source.publishedAt).toLocaleDateString('de-CH', { day: '2-digit', month: 'long', year: 'numeric' })} + + + )} + + + {/* Verified contract special box */} + {isVerifiedContract && ( + + + + Vertragsende aus internem ERP bestätigt + + + + Verwaltung hat Marktfreigabe erteilt + + + )} + + {/* All source URLs */} + {allSourceUrls.length > 0 ? ( + + {allSourceUrls.map((url, i) => ( + + ))} + + ) : ( + + + Kein direkter Quellenlink verfügbar — Signal basiert auf aggregierten {sourceMeta?.label ?? 'Marktdaten'}. + + + )} + + {/* Evidence extraction date */} + {signal.evidence?.extractedAt && ( + + + + Daten extrahiert: {new Date(signal.evidence.extractedAt).toLocaleDateString('de-CH', { day: '2-digit', month: 'short', year: 'numeric' })} + + + )} + + {/* Evidence summary */} + {signal.evidence?.summary && ( + + Evidenz-Zusammenfassung + {signal.evidence.summary} + + )} + + ) +}