modcomms/frontend/components/StatusDashboard.tsx
Vadym Samoilenko aeab7d3b18 Rename Legal Agent to Risk & Control Agent across frontend and backend
Updates all display labels (PDF report, campaign page, Knowledge Base card, analytics, status dashboard, checks overview) and aligns internal agent name in backend. Adds migration 010 to update the knowledge base display_name in production DB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 15:10:32 +01:00

124 lines
No EOL
5.6 KiB
TypeScript
Executable file

import React from 'react';
import type { ReviewStatus, AgentName, AgentStatus } from '../types';
import { AGENT_NAMES } from '../constants';
import { LegalIcon } from './icons/LegalIcon';
import { BrandIcon } from './icons/BrandIcon';
import { CheckCircleIcon, ExclamationTriangleIcon, InformationCircleIcon } from './icons/StatusIcons';
import { ChannelIcon } from './icons/ChannelIcon';
import { SpinnerIcon } from './icons/SpinnerIcon';
interface StatusDashboardProps {
status: ReviewStatus;
variant?: 'default' | 'hero';
}
interface StatusInfoProps {
status: string;
isHeroVariant?: boolean;
}
// FIX: Storing components instead of instantiated elements to avoid React.cloneElement type issues.
const agentIcons: Record<AgentName, React.FC<React.SVGProps<SVGSVGElement>>> = {
'Risk & Control Agent': LegalIcon,
'Brand Agent': BrandIcon,
'Channel Best Practices Agent': ChannelIcon,
'Channel Tech Specs Agent': ChannelIcon,
};
const StatusInfo: React.FC<StatusInfoProps> = ({ status, isHeroVariant = false }) => {
const colors = isHeroVariant ? {
complete: 'text-success-light',
issues: 'text-warning-light',
error: 'text-error-light',
pending: 'text-grey-300'
} : {
complete: 'text-success',
issues: 'text-warning',
error: 'text-error',
pending: 'text-oliver-black/60'
};
switch (status) {
case 'complete':
return <div className={`flex items-center ${colors.complete}`}><CheckCircleIcon className="h-5 w-5 mr-2" /> Pass</div>;
case 'issues-found':
return <div className={`flex items-center ${colors.issues}`}><ExclamationTriangleIcon className="h-5 w-5 mr-2" /> Issues Found</div>;
case 'error':
return <div className={`flex items-center ${colors.error}`}><InformationCircleIcon className="h-5 w-5 mr-2" /> Error</div>;
default:
return <div className={`flex items-center ${colors.pending}`}><InformationCircleIcon className="h-5 w-5 mr-2" /> Pending</div>;
}
};
export const StatusDashboard: React.FC<StatusDashboardProps> = ({ status, variant = 'default' }) => {
if (Object.keys(status).length === 0) return null;
const isHeroVariant = variant === 'hero';
const getTileClassName = (agentStatus: AgentStatus, isHero: boolean): string => {
const baseClasses = 'rounded-[10px] flex flex-col text-center transition-colors duration-500 ease-in-out';
if (isHero) {
const heroBase = `${baseClasses} p-4`;
switch (agentStatus) {
case 'complete':
return `${heroBase} bg-success/20`;
case 'issues-found':
return `${heroBase} bg-warning/20`;
case 'error':
return `${heroBase} bg-error/20`;
default: // 'pending' or 'in-progress'
return `${heroBase} bg-white/10`;
}
} else {
const defaultBase = `${baseClasses} p-6 shadow-lg border`;
switch (agentStatus) {
case 'complete':
return `${defaultBase} bg-success-light border-success`;
case 'issues-found':
return `${defaultBase} bg-warning-light border-warning`;
case 'error':
return `${defaultBase} bg-error-light border-error`;
default: // 'pending' or 'in-progress'
return `${defaultBase} bg-oliver-grey border-grey-300`;
}
}
};
return (
<div className={isHeroVariant ? '' : "mb-12"}>
<h3 className={`text-2xl font-bold text-center mb-8 ${isHeroVariant ? 'text-white' : 'text-oliver-black'}`}>Review Progress</h3>
<div className={`grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 ${isHeroVariant ? 'gap-4' : 'gap-6'}`}>
{AGENT_NAMES.map((agentName) => {
const agentStatus = status[agentName] || 'pending';
const iconColor = isHeroVariant ? 'text-oliver-azure' : 'text-oliver-azure';
const Icon = agentIcons[agentName];
return (
<div key={agentName} className={getTileClassName(agentStatus, isHeroVariant)}>
<div className="flex-grow flex flex-col items-center justify-center">
<div className="mb-3 h-8 w-8 flex items-center justify-center">
<Icon className={`h-8 w-8 ${iconColor}`} />
</div>
<h4 className={`text-base font-bold ${isHeroVariant ? 'text-white' : 'text-oliver-black'}`}>{agentName}</h4>
</div>
<div className="font-semibold text-xs mt-2 h-6 flex items-center justify-center">
{agentStatus === 'in-progress' ? (
<div className={`flex items-center ${isHeroVariant ? 'text-white/80' : 'text-oliver-black/60'}`}>
<SpinnerIcon className="h-4 w-4 mr-2 custom-spinner" />
<span>Analysing...</span>
</div>
) : (
<StatusInfo
status={agentStatus}
isHeroVariant={isHeroVariant}
/>
)}
</div>
</div>
);
})}
</div>
</div>
);
};