From a15bce87960b2964681a5b0f81d8f2c513d7e2e0 Mon Sep 17 00:00:00 2001 From: michael Date: Thu, 12 Feb 2026 18:09:15 -0600 Subject: [PATCH] Add clickable error modal for failed proof analyses When a proof analysis fails, "Analysis failed." is now a clickable underlined link that opens a modal showing: - The lead agent summary explaining why the analysis failed - Details for each agent that returned an Error status Applied to both Campaigns and Projects views. Co-Authored-By: Claude Opus 4.6 --- frontend/components/Campaigns.tsx | 86 +++++++++++++++++++++++++++++- frontend/components/Projects.tsx | 88 ++++++++++++++++++++++++++++++- 2 files changed, 171 insertions(+), 3 deletions(-) diff --git a/frontend/components/Campaigns.tsx b/frontend/components/Campaigns.tsx index 37c9e0d..2ede821 100755 --- a/frontend/components/Campaigns.tsx +++ b/frontend/components/Campaigns.tsx @@ -893,6 +893,77 @@ const DeleteConfirmationModal: React.FC<{ ); }; +const AnalysisErrorModal: React.FC<{ + isOpen: boolean; + onClose: () => void; + proofName: string; + feedback: AgentReview | null; +}> = ({ isOpen, onClose, proofName, feedback }) => { + if (!isOpen || !feedback) return null; + + const agentEntries: { label: string; review: { ragStatus: string; feedback: string } }[] = [ + { label: 'Legal Agent', review: feedback.legalAgentReview }, + { label: 'Brand Agent', review: feedback.brandAgentReview }, + { label: 'Channel Best Practices Agent', review: feedback.channelBestPracticesAgentReview }, + { label: 'Channel Tech Specs Agent', review: feedback.channelTechSpecsAgentReview }, + ]; + + const failedAgents = agentEntries.filter(a => a.review.ragStatus === 'Error'); + + return ( +
+
e.stopPropagation()} + > +
+
+ +
+
+

Analysis Error

+

{proofName}

+
+
+ + {feedback.leadAgentSummary && ( +
+

Summary

+

{feedback.leadAgentSummary}

+
+ )} + + {failedAgents.length > 0 && ( +
+

Agent Details

+ {failedAgents.map(agent => ( +
+

{agent.label}

+

{agent.review.feedback}

+
+ ))} +
+ )} + +
+ +
+
+
+ ); +}; + const CampaignDeleteConfirmationModal: React.FC<{ isOpen: boolean; onClose: () => void; @@ -958,6 +1029,7 @@ const CampaignDetail: React.FC<{ const [proofToDelete, setProofToDelete] = useState(null); const [proofForUpload, setProofForUpload] = useState(null); const [isExporting, setIsExporting] = useState(false); + const [errorProof, setErrorProof] = useState(null); const fileInputRef = useRef(null); const proofs = campaignProofs[campaignName] || []; @@ -1107,6 +1179,13 @@ const CampaignDetail: React.FC<{ existingProofNames={existingProofNames} /> + setErrorProof(null)} + proofName={errorProof?.proofName || ''} + feedback={errorProof?.versions?.[0]?.feedback || null} + /> +
+
+ + + ); +}; + const DeleteConfirmationModal: React.FC<{ isOpen: boolean; onClose: () => void; @@ -538,6 +609,7 @@ const ProjectDetail: React.FC<{ const [isUploadFormVisible, setIsUploadFormVisible] = useState(false); const [assetToDelete, setAssetToDelete] = useState(null); const [assetForUpload, setAssetForUpload] = useState(null); + const [errorAsset, setErrorAsset] = useState(null); const fileInputRef = useRef(null); const assets = projectAssets[projectName] || []; @@ -585,6 +657,13 @@ const ProjectDetail: React.FC<{ assetName={assetToDelete?.assetName || ''} /> + setErrorAsset(null)} + assetName={errorAsset?.assetName || ''} + feedback={errorAsset?.versions?.[0]?.feedback || null} + /> + {asset.subChannel}
- Analysis failed. +