diff --git a/frontend/App.tsx b/frontend/App.tsx index e44b88e..5d1234c 100755 --- a/frontend/App.tsx +++ b/frontend/App.tsx @@ -819,6 +819,7 @@ const App: React.FC = () => { onFlagSubmit={handleFlagSubmit} onResolveSubmit={handleResolveSubmit} flaggedItems={flaggedItems} + resolvedItems={resolvedItems} />; case 'WIP Reviewer': return ; diff --git a/frontend/components/Campaigns.tsx b/frontend/components/Campaigns.tsx index f5d70ae..4cc785d 100755 --- a/frontend/components/Campaigns.tsx +++ b/frontend/components/Campaigns.tsx @@ -1353,7 +1353,8 @@ const ProofDetailView: React.FC<{ onFlagSubmit: (flagData: Omit) => void; onResolveSubmit: (resolveData: Omit) => void; flaggedItems: FlaggedItem[]; -}> = ({ campaignName, proof, onBack, onNewVersionUpload, isUploadingNewVersion, onFlagSubmit, onResolveSubmit, flaggedItems }) => { + resolvedItems: ResolvedItem[]; +}> = ({ campaignName, proof, onBack, onNewVersionUpload, isUploadingNewVersion, onFlagSubmit, onResolveSubmit, flaggedItems, resolvedItems }) => { const getInitialVersionIndex = () => { if (proof.initialVersion && proof.versions) { @@ -1682,6 +1683,7 @@ const ProofDetailView: React.FC<{ onFlagSubmit={handleFlagSubmitWrapper} onResolveSubmit={handleResolveSubmitWrapper} flaggedItems={flaggedItems} + resolvedItems={resolvedItems} proofName={proof.proofName} version={selectedVersion.version} /> @@ -1711,6 +1713,7 @@ interface CampaignsProps { onFlagSubmit: (flagData: Omit) => void; onResolveSubmit: (resolveData: Omit) => void; flaggedItems: FlaggedItem[]; + resolvedItems: ResolvedItem[]; } export const Campaigns: React.FC = ({ @@ -1732,6 +1735,7 @@ export const Campaigns: React.FC = ({ onFlagSubmit, onResolveSubmit, flaggedItems, + resolvedItems, }) => { const [isModalOpen, setIsModalOpen] = useState(false); @@ -1761,6 +1765,7 @@ export const Campaigns: React.FC = ({ onFlagSubmit={onFlagSubmit} onResolveSubmit={onResolveSubmit} flaggedItems={flaggedItems} + resolvedItems={resolvedItems} />; } diff --git a/frontend/components/FeedbackReport.tsx b/frontend/components/FeedbackReport.tsx index db52190..ba35a26 100755 --- a/frontend/components/FeedbackReport.tsx +++ b/frontend/components/FeedbackReport.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import type { AgentReview, SubReview, RagStatus, OverallStatus, FlaggedItem } from '../types'; +import type { AgentReview, SubReview, RagStatus, OverallStatus, FlaggedItem, ResolvedItem } from '../types'; import { CheckCircleIcon, ExclamationTriangleIcon, InformationCircleIcon } from './icons/StatusIcons'; import { FlagIcon } from './icons/FlagIcon'; import { XIcon } from './icons/XIcon'; @@ -273,7 +273,8 @@ const SubReviewCard: React.FC<{ onFlag: () => void; onResolve: (issueText: string, reason: string) => void; isFlagged?: boolean; -}> = ({ title, review, onFlag, onResolve, isFlagged }) => { + resolvedItems?: ResolvedItem[]; +}> = ({ title, review, onFlag, onResolve, isFlagged, resolvedItems = [] }) => { interface IssueState { text: string; status: 'actionable' | 'resolved'; @@ -292,27 +293,43 @@ const SubReviewCard: React.FC<{ const [newCollapsed, setNewCollapsed] = useState(false); useEffect(() => { + const findResolution = (text: string): ResolvedItem | undefined => + resolvedItems.find(r => r.issue === text); + if (hasRevisionData(review)) { // Revision mode: populate from outstandingIssues and newIssues - const outstandingIssues: IssueState[] = (review.outstandingIssues || []).map(text => ({ - text, - status: 'actionable', - reason: undefined, - category: 'outstanding' as const - })); - const newIssues: IssueState[] = (review.newIssues || []).map(text => ({ - text, - status: 'actionable', - reason: undefined, - category: 'new' as const - })); + const outstandingIssues: IssueState[] = (review.outstandingIssues || []).map(text => { + const match = findResolution(text); + return { + text, + status: match ? 'resolved' as const : 'actionable' as const, + reason: match?.resolution, + category: 'outstanding' as const + }; + }); + const newIssues: IssueState[] = (review.newIssues || []).map(text => { + const match = findResolution(text); + return { + text, + status: match ? 'resolved' as const : 'actionable' as const, + reason: match?.resolution, + category: 'new' as const + }; + }); setIssues([...outstandingIssues, ...newIssues]); } else { // Original mode: use review.issues - setIssues(review.issues.map(text => ({ text, status: 'actionable', reason: undefined }))); + setIssues(review.issues.map(text => { + const match = findResolution(text); + return { + text, + status: match ? 'resolved' as const : 'actionable' as const, + reason: match?.resolution + }; + })); } setCurrentStatus(review.ragStatus); - }, [review]); + }, [review, resolvedItems]); useEffect(() => { if (review.ragStatus === 'Error') { @@ -793,15 +810,20 @@ export const FeedbackReport: React.FC<{ onFlagSubmit: (agentName: string, comments: string) => void; onResolveSubmit: (agentName: string, issueText: string, reason: string) => void; flaggedItems?: FlaggedItem[]; + resolvedItems?: ResolvedItem[]; proofName?: string; version?: number; -}> = ({ feedback, onFlagSubmit, onResolveSubmit, flaggedItems = [], proofName, version }) => { +}> = ({ feedback, onFlagSubmit, onResolveSubmit, flaggedItems = [], resolvedItems = [], proofName, version }) => { const flaggedAgents = new Set( flaggedItems .filter(f => f.proofName === proofName && f.version === version) .map(f => f.agentFlagged) ); + const filteredResolvedItems = resolvedItems.filter( + r => r.proofName === proofName && r.version === version + ); + const [flagModalState, setFlagModalState] = useState<{ isOpen: boolean; agentName: string }>({ isOpen: false, agentName: '', @@ -861,6 +883,7 @@ export const FeedbackReport: React.FC<{ onFlag={() => handleOpenFlagModal(title)} onResolve={(issueText, reason) => onResolveSubmit(title, issueText, reason)} isFlagged={flaggedAgents.has(title)} + resolvedItems={filteredResolvedItems.filter(r => r.agent === title)} /> ))}