modcomms/frontend/components/StatusDashboard.tsx
michael 0fdaedc7ff Complete UI design system migration to Barclays brand colors
Updates all remaining frontend components to use the new Barclays
design system color tokens:
- brand-dark-blue → primary-blue (#1A2142)
- brand-accent → active-blue (#006DE3)
- brand-light-blue → cyan-brand (#00AEEF)
- brand-gray → grey-100 (#F6F6F6)

Components updated:
- CampaignDetail and ProofDetailView in Campaigns.tsx
- Projects.tsx (full component migration)
- StatusDashboard.tsx (status tiles and colors)
- CreateProjectModal.tsx (modal styling)
- FeedbackReport.tsx (remaining brand colors)
- Login.tsx and Profile.tsx
- WIPReviewer.tsx and CopyGenAI.tsx
- Header, LoadingVisual, ToggleSwitch
- AssetPreview, ProofPreview, AssetUpload
- ProofTypeManager

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 14:00:13 -06: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>>> = {
'Legal 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-grey-700'
};
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-grey-100 border-grey-300`;
}
}
};
return (
<div className={isHeroVariant ? '' : "mb-12"}>
<h3 className={`text-2xl font-bold text-center mb-8 ${isHeroVariant ? 'text-white' : 'text-primary-blue'}`}>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-cyan-brand' : 'text-active-blue';
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-primary-blue'}`}>{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-grey-700'}`}>
<SpinnerIcon className="h-4 w-4 mr-2 custom-spinner" />
<span>Analyzing...</span>
</div>
) : (
<StatusInfo
status={agentStatus}
isHeroVariant={isHeroVariant}
/>
)}
</div>
</div>
);
})}
</div>
</div>
);
};