import React, { useState, useEffect } from 'react';
import type { AgentReview, SubReview, RagStatus, OverallStatus } from '../types';
import { CheckCircleIcon, ExclamationTriangleIcon, InformationCircleIcon } from './icons/StatusIcons';
import { FlagIcon } from './icons/FlagIcon';
import { XIcon } from './icons/XIcon';
import { BugIcon } from './icons/BugIcon';
import { ExportIcon } from './icons/ExportIcon';
import { LegalIcon } from './icons/LegalIcon';
const RagStatusBadge: React.FC<{ status: RagStatus; isLarge?: boolean }> = ({ status, isLarge = false }) => {
let colorClasses = '';
let iconColor = '';
switch (status) {
case 'Red':
colorClasses = 'bg-red-50 border-red-200 text-red-800 shadow-red-100';
iconColor = 'text-red-600';
break;
case 'Amber':
colorClasses = 'bg-amber-50 border-amber-200 text-amber-800 shadow-amber-100';
iconColor = 'text-amber-600';
break;
case 'Green':
colorClasses = 'bg-emerald-50 border-emerald-200 text-emerald-800 shadow-emerald-100';
iconColor = 'text-emerald-600';
break;
case 'Error':
colorClasses = 'bg-slate-50 border-slate-200 text-slate-700 shadow-slate-100';
iconColor = 'text-slate-500';
break;
}
const sizeClasses = isLarge ? 'px-4 py-1.5 text-sm rounded-xl border shadow-sm' : 'px-2.5 py-1 text-xs rounded-lg border shadow-sm';
return (
{status === 'Red' && }
{status === 'Amber' && }
{status === 'Green' && }
{status === 'Error' && }
{status}
);
};
const ResolveIssueModal: React.FC<{
isOpen: boolean;
onClose: () => void;
onSubmit: (reason: string) => void;
issueText: string;
}> = ({ isOpen, onClose, onSubmit, issueText }) => {
if (!isOpen) return null;
const [reason, setReason] = useState('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (reason.trim()) {
onSubmit(reason);
}
};
return (
e.stopPropagation()}
>
Resolve Issue
Please provide a reason for manually resolving this issue.
"{issueText}"
);
};
const FlagIssueModal: React.FC<{
isOpen: boolean;
onClose: () => void;
onSubmit: (comments: string) => void;
agentName: string;
}> = ({ isOpen, onClose, onSubmit, agentName }) => {
if (!isOpen) return null;
const [comments, setComments] = useState('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSubmit(comments);
};
return (
e.stopPropagation()}
>
Flag Feedback
Reporting incorrect feedback from {agentName}
);
};
const SubReviewCard: React.FC<{
title: string;
review: SubReview;
onFlag: () => void;
onResolve: (issueText: string, reason: string) => void;
}> = ({ title, review, onFlag, onResolve }) => {
interface IssueState {
text: string;
status: 'actionable' | 'resolved';
reason?: string;
}
const [issues, setIssues] = useState([]);
const [currentStatus, setCurrentStatus] = useState(review.ragStatus);
const [isModalOpen, setIsModalOpen] = useState(false);
const [activeIssueIndex, setActiveIssueIndex] = useState(null);
useEffect(() => {
setIssues(review.issues.map(text => ({ text, status: 'actionable', reason: undefined })));
setCurrentStatus(review.ragStatus);
}, [review]);
useEffect(() => {
if (review.ragStatus === 'Error') {
setCurrentStatus('Error');
return;
}
if (issues.length > 0 && issues.every(issue => issue.status === 'resolved')) {
setCurrentStatus('Green');
} else if (issues.some(issue => issue.status === 'actionable')) {
setCurrentStatus(review.ragStatus);
}
}, [issues, review.ragStatus]);
const handleOpenModal = (index: number) => {
setActiveIssueIndex(index);
setIsModalOpen(true);
};
const handleCloseModal = () => {
setIsModalOpen(false);
setActiveIssueIndex(null);
};
const handleResolve = (reason: string) => {
if (activeIssueIndex === null) return;
const issueText = issues[activeIssueIndex].text;
setIssues(currentIssues =>
currentIssues.map((issue, index) =>
index === activeIssueIndex
? { ...issue, status: 'resolved', reason }
: issue
)
);
onResolve(issueText, reason);
handleCloseModal();
};
const handleReopen = (indexToReopen: number) => {
setIssues(currentIssues =>
currentIssues.map((issue, index) =>
index === indexToReopen
? { ...issue, status: 'actionable', reason: undefined }
: issue
)
);
};
// Determine styles based on status
let containerStyles = 'bg-white border-slate-100';
let gradientOverlay = 'from-slate-50/50 to-white';
let headerColor = 'text-slate-800';
let issueIconColor = 'text-slate-400';
let issueIcon = ;
if (currentStatus === 'Green') {
containerStyles = 'bg-white border-emerald-100 hover:border-emerald-200';
gradientOverlay = 'from-emerald-50/40 to-white';
headerColor = 'text-emerald-900';
} else if (currentStatus === 'Amber') {
containerStyles = 'bg-white border-amber-100 hover:border-amber-200';
gradientOverlay = 'from-amber-50/40 to-white';
headerColor = 'text-amber-900';
issueIconColor = 'text-amber-500';
issueIcon = ;
} else if (currentStatus === 'Red') {
containerStyles = 'bg-white border-red-100 hover:border-red-200';
gradientOverlay = 'from-red-50/40 to-white';
headerColor = 'text-red-900';
issueIconColor = 'text-red-500';
issueIcon = ;
}
return (
<>
{/* Subtle gradient background */}
{review.feedback}
{currentStatus !== 'Error' && issues.length > 0 && (
Actionable Issues
{issues.map((issue, index) => (
-
{issue.status === 'actionable' ? (
issueIcon
) : (
)}
{issue.text}
{issue.status === 'actionable' ? (
) : (
Reason for resolution:
"{issue.reason}"
)}
))}
)}
{currentStatus !== 'Error' && issues.length === 0 && (
No actionable issues found.
)}
>
);
};
const LeadAgentSummary: React.FC<{ status: OverallStatus, summary: string, onFlag: () => void; }> = ({ status, summary, onFlag }) => {
const isPassed = status === 'Passed';
let themeStyles = 'from-sky-50 to-white border-sky-100 text-brand-dark-blue';
let iconBg = 'bg-sky-100 text-brand-accent';
let icon = ;
let blobColor = 'bg-sky-400';
if (status === 'Passed') {
themeStyles = 'from-emerald-50 to-white border-emerald-200 text-emerald-900';
iconBg = 'bg-emerald-100 text-emerald-600';
icon = ;
blobColor = 'bg-emerald-400';
} else if (status === 'Failed') {
themeStyles = 'from-rose-50 to-white border-rose-200 text-rose-900';
iconBg = 'bg-rose-100 text-rose-600';
icon = ;
blobColor = 'bg-rose-400';
}
if (status === 'Requires Manual Legal Review') return null;
return (
{/* Abstract decorative blob */}
{icon}
Overall Status: {status}
{summary}
);
};
const FinancialPromotionSummary: React.FC<{ reason: string; summary: string }> = ({ reason, summary }) => {
const [exportStatus, setExportStatus] = useState('Export for Legal');
const handleExport = () => {
const textToCopy = `## Financial Promotion Review Required ##\n\nReason for Flag:\n${reason}\n\n## AI Agent Summary ##\n${summary}`.trim();
navigator.clipboard.writeText(textToCopy).then(() => {
setExportStatus('Copied!');
setTimeout(() => setExportStatus('Export for Legal'), 2000);
}).catch(err => {
console.error('Failed to copy text: ', err);
setExportStatus('Failed');
setTimeout(() => setExportStatus('Export for Legal'), 2000);
});
};
return (
Financial Promotion Detected
This proof has been identified as a financial promotion and requires a separate, manual review from the Barclays legal team.
Reason Identified
"{reason}"
);
};
export const FeedbackReport: React.FC<{
feedback: AgentReview;
onFlagSubmit: (agentName: string, comments: string) => void;
onResolveSubmit: (agentName: string, issueText: string, reason: string) => void;
}> = ({ feedback, onFlagSubmit, onResolveSubmit }) => {
const [flagModalState, setFlagModalState] = useState<{ isOpen: boolean; agentName: string }>({
isOpen: false,
agentName: '',
});
const handleOpenFlagModal = (agentName: string) => {
setFlagModalState({ isOpen: true, agentName });
};
const handleCloseFlagModal = () => {
setFlagModalState({ isOpen: false, agentName: '' });
};
const handleSubmitFlag = (comments: string) => {
onFlagSubmit(flagModalState.agentName, comments);
alert(`Thank you for your feedback on the ${flagModalState.agentName}'s review. This has been logged for auditing.`);
handleCloseFlagModal();
};
const agentReviews = [
{ title: 'Legal Agent', review: feedback.legalAgentReview },
{ title: 'Brand Agent', review: feedback.brandAgentReview },
{ title: 'Tone Agent', review: feedback.toneAgentReview },
{ title: 'Channel Agent', review: feedback.channelAgentReview },
];
const isFinancialPromotion = feedback.overallStatus === 'Requires Manual Legal Review';
return (
{isFinancialPromotion ? (
) : (
handleOpenFlagModal('Lead Agent')}
/>
)}
{agentReviews.map(({ title, review }) => (
handleOpenFlagModal(title)}
onResolve={(issueText, reason) => onResolveSubmit(title, issueText, reason)}
/>
))}
);
};