import React, { useState, useEffect } from 'react'; import ReactMarkdown from 'react-markdown'; import { Sparkles, Printer, FileDown, RefreshCw, Layers, ShieldCheck, ShieldAlert, AlertTriangle, History, Save } from 'lucide-react'; import { compileFinalDocument, auditFinalDocument, getProjectVersions, createProjectVersion, exportProjectPDF, exportProjectDOCX } from '../../api/client'; import toast from 'react-hot-toast'; interface FinalDocumentPanelProps { project: any; onUpdate: () => void; } const FinalDocumentPanel: React.FC = ({ project, onUpdate }) => { const [isCompiling, setIsCompiling] = useState(false); const [isAuditing, setIsAuditing] = useState(false); const [isCreatingVersion, setIsCreatingVersion] = useState(false); const [approvedOnly, setApprovedOnly] = useState(false); const [showAuditDetails, setShowAuditDetails] = useState(false); const [acceptedAI, setAcceptedAI] = useState(false); const auditPanelRef = React.useRef(null); const [versions, setVersions] = useState([]); const loadVersions = async () => { try { const data = await getProjectVersions(project.id); setVersions(data); } catch (err) { console.error("Failed to load versions", err); } }; useEffect(() => { loadVersions(); }, [project.id]); const formatDate = (dateStr: string) => { return new Intl.DateTimeFormat('pl-PL', { day: 'numeric', month: 'long', year: 'numeric', hour: '2-digit', minute: '2-digit' }).format(new Date(dateStr)); }; const handleCreateVersion = async () => { try { if (!window.confirm("Czy chcesz zapisać obecną wersję wniosku jako nową migawkę?")) return; const title = prompt("Podaj nazwę dla tej wersji (opcjonalnie):"); if (title === null) return; // cancelled setIsCreatingVersion(true); toast.loading("Zapisywanie wersji...", { id: "version" }); const result = await createProjectVersion(project.id, title); if (result && result.version_number) { toast.success(`Wersja V${result.version_number} została zapisana pomyślnie.`, { id: "version" }); } else { toast.success(`Wersja została zapisana pomyślnie.`, { id: "version" }); } loadVersions(); } catch (error: any) { let errMsg = "Błąd podczas zapisu wersji."; if (error.response?.data?.detail) { const detail = error.response.data.detail; errMsg = typeof detail === 'string' ? detail : (detail.message || JSON.stringify(detail)); } toast.error(errMsg, { id: "version" }); } finally { setIsCreatingVersion(false); } }; const handleDownloadVers = async (type: 'pdf' | 'docx', v: any) => { toast(`Pobierasz wersję V${v.version_number} z ${formatDate(v.created_at).split(',')[0]}`, { icon: '⬇️' }); try { if (type === 'pdf') { await exportProjectPDF(project.id, v.id); } else { await exportProjectDOCX(project.id, false, v.id); } } catch (e: any) { alert(e.message); } }; const handleAudit = async () => { try { setIsAuditing(true); toast.loading("Przeprowadzanie weryfikacji krzyżowej (Audyt)...", { id: "audit" }); await auditFinalDocument(project.id); toast.success("Audyt zakończony.", { id: "audit" }); setShowAuditDetails(true); setTimeout(() => { auditPanelRef.current?.scrollIntoView({ behavior: 'smooth' }); }, 100); onUpdate(); } catch (error: any) { let errMsg = "Błąd podczas audytu wniosku."; if (error.response?.data?.detail) { const detail = error.response.data.detail; errMsg = typeof detail === 'string' ? detail : (detail.message || JSON.stringify(detail)); } toast.error(errMsg, { id: "audit" }); } finally { setIsAuditing(false); } }; const handleCompile = async () => { try { setIsCompiling(true); toast.loading("Kompilowanie i redagowanie wniosku...", { id: "compile" }); const result = await compileFinalDocument(project.id, approvedOnly); toast.success(`Wniosek gotowy! Połączono ${result.sections_used} sekcji. Pamiętaj o weryfikacji przez Audytor.`, { id: "compile" }); onUpdate(); // Odśwież dane w nadrzędnym widoku } catch (error: any) { let errMsg = "Błąd podczas kompilacji lub audytu wniosku."; if (error.response?.data?.detail) { const detail = error.response.data.detail; errMsg = typeof detail === 'string' ? detail : (detail.message || JSON.stringify(detail)); } toast.error(errMsg, { id: "compile" }); } finally { setIsCompiling(false); } }; const handlePrint = () => { window.print(); }; const handleDownloadTxt = () => { if (!project.final_document_markdown) return; const blob = new Blob([project.final_document_markdown], { type: 'text/markdown;charset=utf-8' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `Wniosek_${project.title.replace(/\s+/g, '_')}.md`; a.click(); URL.revokeObjectURL(url); }; return (

Gotowy Wniosek

Połącz wszystkie sekcje robocze, przepuść przez korektorę redaktorską LLM i wyeksportuj swój wniosek.

{project.final_document_markdown && ( <> )}

Historia Wersji

{versions.map((v, idx) => (
V{v.version_number} {idx === 0 && Bieżąca}
{formatDate(v.created_at)}
{v.title &&
"{v.title}"
}
))} {versions.length === 0 &&
Brak zapisanych wersji.
}
{/* PANEL AUDYTU */} {!project.final_document_audit_result && project.final_document_markdown && (

Dokument niezweryfikowany Audytorem - Zwiększone ryzyko odrzucenia

)} {project.final_document_audit_result && (
= 80 ? 'rgba(34, 197, 94, 0.05)' : (project.final_document_audit_result.overall_score >= 60 ? 'rgba(234, 179, 8, 0.05)' : 'rgba(239, 68, 68, 0.05)'), border: `1px solid ${project.final_document_audit_result.overall_score >= 80 ? 'rgba(34,197,94,0.2)' : (project.final_document_audit_result.overall_score >= 60 ? 'rgba(234,179,8,0.2)' : 'rgba(239,68,68,0.2)')}` }}>
{project.final_document_audit_result.overall_score >= 80 ? ( ) : ( = 60 ? "#eab308" : "#ef4444"} /> )}

Audyt Zgodności Wniosku: {project.final_document_audit_result.overall_score >= 80 ? "Niski poziom ryzyka odrzucenia wniosku. Dokument jest dobrze przygotowany." : (project.final_document_audit_result.overall_score >= 60 ? "Średnie ryzyko. Zalecamy wprowadzenie poprawek zgodnie z poniższymi rekomendacjami przed złożeniem." : "Wysokie ryzyko odrzucenia. Silnie zalecamy wprowadzenie zmian. Eksport możliwy wyłącznie na własne ryzyko.")}

= 80 ? '#22c55e' : (project.final_document_audit_result.overall_score >= 60 ? '#eab308' : '#ef4444'), color: 'white', padding: '0.25rem 0.75rem', borderRadius: '20px', fontSize: '0.85rem', fontWeight: 600 }}> {project.final_document_audit_result.overall_score} / 100
{project.final_document_audit_result.issues?.length > 0 && (
{(!showAuditDetails && project.final_document_audit_result.overall_score >= 80) ? ( ) : (
{project.final_document_audit_result.issues.map((issue: any, idx: number) => (
{issue.category}

{issue.message}

{issue.rule_citation && (
Podstawa / Reguła: {issue.rule_citation}
)} {issue.recommendation && (
Rekomendacja: {issue.recommendation}
)}
))} {project.final_document_audit_result.overall_score < 60 && ( )}
)}
)}
* Audyt jest wsparciem AI. Ostateczna odpowiedzialność za treść wniosku spoczywa na użytkowniku.
)} {project.final_document_markdown ? (

Podgląd wygenerowanego wniosku. Ostatnia generacja: {new Date(project.final_document_generated_at).toLocaleString('pl-PL')}

{project.final_document_markdown}
Wygenerowano przy wsparciu AI
Ten dokument został częściowo utworzony przez sztuczną inteligencję na podstawie regulaminów urzędowych. Wiedza systemu aktualna na: 12 kwietnia 2026.
Zawsze zweryfikuj treść samodzielnie przed złożeniem wniosku do instytucji publicznej.
) : (

Brak wygenerowanego wniosku

Kliknij na przycisk powyżej, aby scalić części i przygotować dokument.

)}
); }; export default FinalDocumentPanel;