Files
breakpilot-compliance/admin-compliance/app/sdk/agent/_components/AgentPflichtTable.tsx
T
Benjamin Admin 3f23a64d5f feat(agent): Impressum-Tab auf Haupt-Engine + Profil/§36-Fixes
Ergebnis-Tab rendert jetzt result.results (Haupt-Doc-Check) statt des
abweichenden v3-Agenten — BMW korrekt statt False Positives:
- DocResultView: ein Dokument als Pflichtangaben-Tabelle (Label + gefundener
  Text + 3-Tier-Status), KEINE MC-IDs. ComplianceResultTabs speist Tabs aus
  result.results; ChecklistView-Bausteine exportiert + wiederverwendet.
- profile_extractor: Firmenname/Rechtsform = fruehester Treffer + ausge-
  schriebene Formen (Aktiengesellschaft) -> BMW AG statt "juris GmbH".
- 36 VSBG (MC-010): reines b2c -> POSSIBLY_APPLICABLE (Pruef-Hinweis) statt
  MEDIUM-FAIL; hart nur bei ecommerce. possibly_hint pro MC.
- McCoverage traegt label + found (Snippet); mc_possibly-Aggregat.
- AgentFindingCard/Methodik: interne check_id/mc_id nicht mehr angezeigt.

Tests: test_four_status (16) + Frontend-Vitest gruen; CI-Suite 206, v3/GT
unveraendert. Nur eigene Dateien (geteilter Tree).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-10 23:44:01 +02:00

83 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
/**
* AgentPflichtTable — die geprüften Pflichtangaben als menschliche Tabelle:
* Status-Icon + Feldname + tatsächlich gefundener Text. Ersetzt die alte
* MC-ID-Liste.
*
* WICHTIG: zeigt NIE die mc_id (Reverse-Engineering-Schutz der MC-Bibliothek)
* — nur das menschliche `label`. Generisch für jeden Agenten verwendbar.
*/
import React from 'react'
import type { McCoverage } from './_agentTypes'
const DISP: Record<string, { icon: string; text: string; color: string }> = {
ok: { icon: '✓', text: 'vorhanden', color: '#16a34a' },
high: { icon: '✗', text: 'fehlt', color: '#dc2626' },
medium: { icon: '✗', text: 'fehlt', color: '#d97706' },
low: { icon: '✗', text: 'fehlt', color: '#2563eb' },
possibly_applicable: { icon: '?', text: 'zu prüfen', color: '#ca8a04' },
insufficient_evidence: { icon: '?', text: 'unklar', color: '#64748b' },
na: { icon: '', text: 'nicht anwendbar', color: '#94a3b8' },
skipped: { icon: '', text: 'nicht geprüft', color: '#cbd5e1' },
}
// Reihenfolge: Probleme zuerst, dann erfüllt, dann n/a.
const RANK: Record<string, number> = {
high: 0, medium: 1, low: 2, possibly_applicable: 3,
insufficient_evidence: 4, ok: 5, na: 6, skipped: 7,
}
export function AgentPflichtTable({ coverage }: { coverage: McCoverage[] }) {
if (!coverage?.length) return null
const rows = [...coverage].sort(
(a, b) => (RANK[a.status] ?? 9) - (RANK[b.status] ?? 9),
)
const count = (s: string) => coverage.filter(c => c.status === s).length
const ok = count('ok')
const fehlt = count('high') + count('medium') + count('low')
const pruefen = count('possibly_applicable') + count('insufficient_evidence')
const na = count('na') + count('skipped')
return (
<div className="border rounded overflow-hidden">
<div className="px-3 py-2 text-xs font-semibold uppercase text-gray-700 border-b bg-slate-50">
Pflichtangaben <span className="text-green-700">{ok} vorhanden</span>
{fehlt > 0 && <> · <span className="text-red-600">{fehlt} fehlt</span></>}
{pruefen > 0 && (
<> · <span className="text-yellow-700">{pruefen} zu prüfen</span></>
)}
{na > 0 && <> · <span className="text-gray-400">{na} n/a</span></>}
</div>
<div className="divide-y divide-gray-100">
{rows.map((c, i) => {
const d = DISP[c.status] || DISP.skipped
return (
<div key={i} className="flex items-start gap-2 px-3 py-1.5 text-xs">
<span
className="font-bold w-4 text-center shrink-0"
style={{ color: d.color }}
aria-label={d.text}
>
{d.icon}
</span>
<span className="font-medium text-gray-800 w-52 shrink-0">
{c.label || 'Angabe'}
</span>
<span className="text-gray-500 flex-1 min-w-0 break-words">
{c.status === 'ok' ? (
<span className="italic">{c.found || 'vorhanden'}</span>
) : (
<span style={{ color: d.color }}>{d.text}</span>
)}
</span>
</div>
)
})}
</div>
</div>
)
}