import React, { useState, useCallback } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Upload, FileText, AlertTriangle, CheckCircle, Loader2, Info, ChevronRight, Sparkles, Download, ShieldCheck } from 'lucide-react'; import { uploadReverseAuditDocument, uploadGapReportDocument, exportGapReportFromFile, AuditMode } from '../../api/client'; import toast from 'react-hot-toast'; export const ReverseAuditPanel: React.FC = () => { const [isDragging, setIsDragging] = useState(false); const [file, setFile] = useState(null); const [programName, setProgramName] = useState(''); const [auditMode, setAuditMode] = useState('pro'); const [isAuditing, setIsAuditing] = useState(false); const [isExporting, setIsExporting] = useState<'pdf' | 'docx' | null>(null); const [auditResult, setAuditResult] = useState(null); const onDragOver = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(true); }; const onDragLeave = () => { setIsDragging(false); }; const onDrop = useCallback((e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { setFile(e.dataTransfer.files[0]); } }, []); const handleFileChange = (e: React.ChangeEvent) => { if (e.target.files && e.target.files.length > 0) { setFile(e.target.files[0]); } }; const handleAudit = async () => { if (!file) { toast.error("Proszę wybrać plik do audytu."); return; } if (auditMode === 'pro' && !programName.trim()) { toast.error("Tryb Pro wymaga nazwy programu / naboru."); return; } setIsAuditing(true); setAuditResult(null); try { if (auditMode === 'pro') { const data = await uploadGapReportDocument(file, programName.trim()); setAuditResult(data); } else { const data = await uploadReverseAuditDocument(file, programName || undefined); setAuditResult({ ...data, mode: 'llm' }); } toast.success(auditMode === 'pro' ? "Audyt deterministyczny zakończony!" : "Audyt LLM zakończony!"); } catch (error: any) { toast.error(error.response?.data?.detail || "Wystąpił błąd podczas audytu."); } finally { setIsAuditing(false); } }; const handleExport = async (format: 'pdf' | 'docx') => { if (!file || !programName.trim()) { toast.error("Wymagany plik i nazwa programu do eksportu."); return; } setIsExporting(format); try { await exportGapReportFromFile(file, programName.trim(), format); toast.success(`Pobrano raport ${format.toUpperCase()}`); } catch (error: any) { toast.error(error.response?.data?.detail || "Eksport nie powiódł się."); } finally { setIsExporting(null); } }; const renderSeverityIcon = (severity: string) => { switch (severity.toLowerCase()) { case 'critical': return ; case 'high': return ; case 'medium': return ; default: return ; } }; return (

Reverse Audit (Weryfikacja Wniosku)

Prześlij gotowy wniosek (PDF, DOCX lub TXT). Tryb Pro używa deterministycznego audytu luk (snapshot gap audit) bez LLM. Tryb LLM uruchamia GraphRAG + Regulation Engine z wieloperspektywiczną analizą.

setProgramName(e.target.value)} style={{ width: '100%', padding: '0.75rem 1rem', borderRadius: '8px', border: '1px solid var(--border-color)', background: 'var(--bg-primary)', color: 'var(--text-primary)', outline: 'none' }} />
document.getElementById('audit-file-upload')?.click()} >
{file ? file.name : 'Przeciągnij plik tutaj lub kliknij, aby wybrać'}
Obsługiwane formaty: PDF, DOCX, TXT
{auditMode === 'pro' && auditResult && ( <> )}
{auditResult && (

Wyniki Audytu {auditResult.mode === 'pro' && ( PRO )} {auditResult.is_approved ? : }

Ocena ogólna (Score)
75 ? 'var(--accent-green)' : (auditResult.overall_score > 50 ? 'var(--accent-orange)' : 'var(--accent-red)') }}> {auditResult.overall_score} / 100
Wymaga weryfikacji eksperta
{auditResult.human_review_required ? 'TAK' : 'NIE'}
{auditResult.summary && (

{auditResult.summary}

)}

Wykryte luki i błędy ({auditResult.issues?.length || 0}):

{auditResult.issues?.length === 0 ? (
Nie znaleziono żadnych luk względem regulaminu!
) : ( auditResult.issues?.map((issue: any, idx: number) => (
{renderSeverityIcon(issue.severity)}
{issue.category} [{issue.perspective}]
{issue.message}
{issue.rule_citation && (
Cytat z regulaminu: {issue.rule_citation}
)} {issue.recommendation && (
Rekomendacja: {issue.recommendation}
)}
)) )}
)}
); };