import React from 'react'; import type { AgentReview, RagStatus } from '../types'; import { LegalIcon } from './icons/LegalIcon'; import { BrandIcon } from './icons/BrandIcon'; import { ChannelIcon } from './icons/ChannelIcon'; interface PDFReportProps { campaignName: string; proofs: any[]; } /** * Renders inline markdown bold (**text**) as elements for PDF output. */ const renderBoldMarkdownForPDF = (text: string): React.ReactNode[] => { const parts: React.ReactNode[] = []; const regex = /\*\*(.+?)\*\*/g; let lastIndex = 0; let match: RegExpExecArray | null; while ((match = regex.exec(text)) !== null) { if (match.index > lastIndex) { parts.push(text.slice(lastIndex, match.index)); } parts.push({match[1]}); lastIndex = regex.lastIndex; } if (lastIndex < text.length) { parts.push(text.slice(lastIndex)); } return parts; }; const formatFeedbackTextForPDF = (text: string): React.ReactNode => { if (!text) return null; // Normalize HTML tags and bullet characters let normalizedText = text .replace(/<\/li>/gi, '\n') .replace(/<\/ul>/gi, '\n') .replace(/]*>/gi, '') .replace(/]*>/gi, '• ') .replace(/<[^>]+>/g, '') .replace(/\s*•\s*/g, '\n• ') .replace(/\n{2,}/g, '\n') .trim(); const lines = normalizedText.split('\n').filter(line => line.trim()); // Each bullet is an array of lines (to support multi-line Issue/Recommendation) const bulletGroups: string[][] = []; const introLines: string[] = []; lines.forEach(line => { const trimmed = line.trim(); if (trimmed.startsWith('•')) { bulletGroups.push([trimmed.replace(/^•\s*/, '').trim()]); } else if (trimmed) { if (bulletGroups.length === 0) { introLines.push(trimmed); } else { // Continuation line within the current bullet bulletGroups[bulletGroups.length - 1].push(trimmed); } } }); return ( <> {introLines.length > 0 && (

{renderBoldMarkdownForPDF(introLines.join(' '))}

)} {bulletGroups.length > 0 && (
    {bulletGroups.map((group, index) => (
  • {group.map((line, lineIdx) => ( {lineIdx > 0 &&
    } {renderBoldMarkdownForPDF(line)}
    ))}
  • ))}
)} ); }; const RagStatusBadge: React.FC<{ status: RagStatus }> = ({ status }) => { let bgColor = '#E5E7EB'; // Gray for Error let textColor = '#1F2937'; switch (status) { case 'Red': bgColor = '#FEE2E2'; textColor = '#991B1B'; break; case 'Amber': bgColor = '#FEF3C7'; textColor = '#92400E'; break; case 'Green': bgColor = '#D1FAE5'; textColor = '#065F46'; break; } return ( {status} ); }; export const PDFReport: React.FC = ({ campaignName, proofs }) => { const logoUrl = `${window.location.origin}${import.meta.env.BASE_URL}BAR-ModComms-logo-v6.png`; const today = new Date().toLocaleDateString('en-GB', { day: '2-digit', month: 'long', year: 'numeric', }); const isCampaignReport = proofs.length > 1; const singleProofName = !isCampaignReport && proofs.length > 0 ? proofs[0].proofName : ''; return (
{/* --- Cover Page --- */}
Mod Comms AI — In partnership with Barclays

AI Compliance & Brand Report

{isCampaignReport ? 'Campaign-Level Summary' : 'Single Proof Analysis'}

Campaign: {campaignName}

{!isCampaignReport &&

Proof: {singleProofName}

}

Export Date: {today}

{/* --- Table of Contents for Campaign Report --- */} {isCampaignReport && (

Table of Contents

    {proofs.map((proof, index) => (
  • {proof.proofName} - V{proof.versions[0]?.version || 1}
  • ))}
)} {/* --- Proof Report Pages --- */} {proofs.map((proof) => { const version = proof.versions[0]; if (!version) return null; const feedback: AgentReview = version.feedback; const agentReviews = [ { title: 'Risk & Control Agent', review: feedback.legalAgentReview, icon: }, { title: 'Brand Agent', review: feedback.brandAgentReview, icon: }, { title: 'Channel Best Practices Agent', review: feedback.channelBestPracticesAgentReview, icon: }, { title: 'Channel Tech Specs Agent', review: feedback.channelTechSpecsAgentReview, icon: }, ]; return (
{/* Proof Header */}

{proof.proofName} - V{version.version}

{version.workfrontId} • {proof.channel} / {proof.subChannel}

{/* Preview & Summary */}
Proof Preview

Overall Summary

Status: {feedback.overallStatus}

{feedback.overallStatus === 'Requires Manual Legal Review' && (

Financial Promotion Detected:

"{feedback.financialPromotionReason}"

)}
{formatFeedbackTextForPDF(feedback.leadAgentSummary)}
{/* Detailed Agent Feedback */}
{agentReviews.map(({ title, review, icon }) => (

{icon} {title}

{formatFeedbackTextForPDF(review.feedback)}
{review.issues && review.issues.length > 0 && (
Key Actions:
    {review.issues.map((issue, i) =>
  • {issue}
  • )}
)}
))}
); })}
); };