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>
This commit is contained in:
parent
75b2c6e699
commit
0fdaedc7ff
16 changed files with 208 additions and 208 deletions
|
|
@ -128,7 +128,7 @@ export const AssetPreview: React.FC<AssetPreviewProps> = ({ file, previewUrl, fi
|
|||
style={{ minHeight: '300px', maxHeight: 'calc(100vh - 9rem)' }}
|
||||
>
|
||||
<DocumentIcon className="h-20 w-20 text-gray-400 mb-4" />
|
||||
<p className="text-lg font-semibold text-brand-dark-blue break-all">{displayName}</p>
|
||||
<p className="text-lg font-semibold text-primary-blue break-all">{displayName}</p>
|
||||
<p className="text-sm text-gray-500">{fileType}</p>
|
||||
<p className="text-sm text-gray-500 mt-2">No preview available for this file type.</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export const AssetUpload: React.FC<AssetUploadProps> = ({ onFileUpload, isLoadin
|
|||
onClick={handleClick}
|
||||
disabled={isDisabled}
|
||||
title={isUploadDisabled ? "Please complete all selections above" : "Upload an asset for review"}
|
||||
className="w-full bg-brand-light-blue text-brand-dark-blue font-bold py-3 px-6 rounded-full hover:bg-white transition-all duration-300 disabled:bg-gray-500 disabled:opacity-60 disabled:cursor-not-allowed flex items-center justify-center"
|
||||
className="w-full bg-cyan-brand text-primary-blue font-bold py-3 px-6 rounded-full hover:bg-white transition-all duration-300 disabled:bg-gray-500 disabled:opacity-60 disabled:cursor-not-allowed flex items-center justify-center"
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -1061,7 +1061,7 @@ const CampaignDetail: React.FC<{
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-brand-gray">
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-grey-100">
|
||||
<DeleteConfirmationModal
|
||||
isOpen={!!proofToDelete}
|
||||
onClose={() => setProofToDelete(null)}
|
||||
|
|
@ -1082,15 +1082,15 @@ const CampaignDetail: React.FC<{
|
|||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={onBack}
|
||||
className="p-2 text-gray-500 rounded-full hover:bg-gray-200 hover:text-brand-dark-blue transition-colors duration-200"
|
||||
className="p-2 text-grey-700 rounded-full hover:bg-grey-300 hover:text-primary-blue transition-colors duration-200"
|
||||
title="Back to campaigns"
|
||||
aria-label="Back to campaigns list"
|
||||
>
|
||||
<ArrowLeftIcon className="h-6 w-6" />
|
||||
</button>
|
||||
<div>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-brand-dark-blue">{campaignName}</h1>
|
||||
<p className="text-base lg:text-lg text-gray-600 mt-1">Proof overview and compliance status.</p>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-primary-blue">{campaignName}</h1>
|
||||
<p className="text-base lg:text-lg text-grey-900 mt-1">Proof overview and compliance status.</p>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
@ -1112,71 +1112,71 @@ const CampaignDetail: React.FC<{
|
|||
<button
|
||||
onClick={() => handleExportPDF(proofs.filter(p => p.status === 'completed'), `${campaignName} - Campaign Report`)}
|
||||
disabled={isExporting || proofs.filter(p => p.status === 'completed').length === 0}
|
||||
className="flex items-center gap-2 bg-white text-brand-dark-blue font-semibold py-2 px-4 rounded-lg border border-brand-dark-blue hover:bg-brand-gray transition-colors duration-300 disabled:bg-gray-300 disabled:text-gray-500 disabled:border-gray-300 disabled:cursor-wait"
|
||||
className="flex items-center gap-2 bg-white text-active-blue font-semibold py-2 px-4 rounded-full border-2 border-active-blue hover:bg-active-blue hover:text-white transition-colors duration-300 disabled:bg-grey-300 disabled:text-grey-700 disabled:border-grey-300 disabled:cursor-wait"
|
||||
>
|
||||
{isExporting ? <SpinnerIcon className="h-5 w-5 custom-spinner" /> : <ExportIcon className="h-5 w-5" />}
|
||||
{isExporting ? 'Exporting...' : 'Export Campaign Report'}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsUploadFormVisible(true)}
|
||||
className="flex items-center gap-2 bg-brand-accent text-white font-semibold py-2 px-4 rounded-lg hover:bg-brand-dark-blue transition-colors duration-300"
|
||||
className="flex items-center gap-2 bg-active-blue text-white font-semibold py-2 px-4 rounded-full hover:bg-active-blue/90 transition-colors duration-300"
|
||||
>
|
||||
<PlusIcon className="h-5 w-5" />
|
||||
Upload New Proof
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-lg shadow-md overflow-hidden border border-gray-200">
|
||||
<div className="bg-white rounded-[10px] shadow-md overflow-hidden border border-grey-300">
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-gray-50">
|
||||
<table className="min-w-full divide-y divide-grey-300">
|
||||
<thead className="bg-lime">
|
||||
<tr>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Proof Name</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Workfront #</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Channel</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Sub-Channel</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Proof Type</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Overall Status</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Proof Name</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Workfront #</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Channel</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Sub-Channel</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Proof Type</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Overall Status</th>
|
||||
<th scope="col" className="relative px-6 py-3"><span className="sr-only">Actions</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
<tbody className="bg-white divide-y divide-grey-300">
|
||||
{proofs.map((proof, index) => {
|
||||
if (proof.status === 'analyzing') {
|
||||
return (
|
||||
<tr key={proof.tempId} className="bg-gray-50 opacity-80">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">{proof.proofName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 italic">Pending</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{proof.channel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{proof.subChannel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{proof.proofType || 'N/A'}</td>
|
||||
<tr key={proof.tempId} className="bg-grey-100 opacity-80">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-primary-blue">{proof.proofName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-grey-700 italic">Pending</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{proof.channel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{proof.subChannel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{proof.proofType || 'N/A'}</td>
|
||||
<td className="px-6 py-4" colSpan={2}>
|
||||
{proof.analysisProgress ?
|
||||
<LoadingCell progress={proof.analysisProgress} /> :
|
||||
{proof.analysisProgress ?
|
||||
<LoadingCell progress={proof.analysisProgress} /> :
|
||||
<div className="flex justify-center items-center h-full">
|
||||
<SpinnerIcon className="h-5 w-5 text-brand-accent custom-spinner" />
|
||||
<span className="ml-2 text-sm text-gray-600">Preparing...</span>
|
||||
<SpinnerIcon className="h-5 w-5 text-active-blue custom-spinner" />
|
||||
<span className="ml-2 text-sm text-grey-900">Preparing...</span>
|
||||
</div>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (proof.status === 'error') {
|
||||
return (
|
||||
<tr key={proof.tempId} className="bg-red-50">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">{proof.proofName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 italic">Failed</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{proof.channel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{proof.subChannel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{proof.proofType || 'N/A'}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-red-700 font-semibold" colSpan={2}>
|
||||
<tr key={proof.tempId} className="bg-error-light">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-primary-blue">{proof.proofName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-grey-700 italic">Failed</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{proof.channel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{proof.subChannel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{proof.proofType || 'N/A'}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-error font-semibold" colSpan={2}>
|
||||
<div className="flex items-center justify-between">
|
||||
<span>Analysis failed.</span>
|
||||
<button
|
||||
<button
|
||||
onClick={() => onRetryAnalysis(campaignName, proof.tempId)}
|
||||
className="flex items-center gap-1.5 text-xs font-semibold text-brand-accent hover:text-brand-dark-blue whitespace-nowrap px-3 py-1.5 rounded-full bg-brand-accent/10 hover:bg-brand-accent/20 transition-colors"
|
||||
className="flex items-center gap-1.5 text-xs font-semibold text-active-blue hover:text-primary-blue whitespace-nowrap px-3 py-1.5 rounded-full bg-active-blue/10 hover:bg-active-blue/20 transition-colors"
|
||||
>
|
||||
<ArrowPathIcon className="h-4 w-4" />
|
||||
Retry
|
||||
|
|
@ -1194,23 +1194,23 @@ const CampaignDetail: React.FC<{
|
|||
if (!latestVersion) return null; // Should not happen for completed proofs
|
||||
|
||||
return (
|
||||
<tr
|
||||
<tr
|
||||
key={latestVersion.workfrontId || index}
|
||||
className={isClickable ? "hover:bg-gray-100 cursor-pointer" : ""}
|
||||
className={`${index % 2 === 0 ? 'bg-white' : 'bg-grey-100'} ${isClickable ? "hover:bg-info-light cursor-pointer" : ""}`}
|
||||
onClick={() => isClickable && onSelectProof(proof)}
|
||||
>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-primary-blue">
|
||||
{proof.proofName}
|
||||
{isVersioned && (
|
||||
<span className="ml-2 bg-gray-200 text-gray-700 text-xs font-bold px-2 py-0.5 rounded-full">
|
||||
<span className="ml-2 bg-grey-300 text-black-title text-xs font-bold px-2 py-0.5 rounded-full">
|
||||
V{latestVersion.version}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{latestVersion.workfrontId}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{proof.channel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{proof.subChannel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{proof.proofType || 'N/A'}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{latestVersion.workfrontId}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{proof.channel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{proof.subChannel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{proof.proofType || 'N/A'}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm">
|
||||
<OverallStatusBadge status={latestVersion.overallStatus} />
|
||||
</td>
|
||||
|
|
@ -1218,7 +1218,7 @@ const CampaignDetail: React.FC<{
|
|||
<div className="flex items-center justify-end gap-1">
|
||||
<button
|
||||
onClick={(e) => handleNewVersionClick(e, proof)}
|
||||
className="p-2 text-gray-400 rounded-full hover:bg-blue-100 hover:text-blue-600 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
className="p-2 text-grey-700 rounded-full hover:bg-info-light hover:text-active-blue transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
title={`Upload new version for ${proof.proofName}`}
|
||||
disabled={isUploading || isExporting}
|
||||
>
|
||||
|
|
@ -1230,7 +1230,7 @@ const CampaignDetail: React.FC<{
|
|||
handleExportPDF([proof], `${campaignName} - ${proof.proofName} Report`);
|
||||
}}
|
||||
disabled={isExporting}
|
||||
className="p-2 text-gray-400 rounded-full hover:bg-green-100 hover:text-green-600 transition-colors disabled:opacity-50 disabled:cursor-wait"
|
||||
className="p-2 text-grey-700 rounded-full hover:bg-success-light hover:text-success transition-colors disabled:opacity-50 disabled:cursor-wait"
|
||||
title={`Export PDF for ${proof.proofName}`}
|
||||
>
|
||||
<PDFIcon className="h-5 w-5" />
|
||||
|
|
@ -1241,7 +1241,7 @@ const CampaignDetail: React.FC<{
|
|||
setProofToDelete(proof);
|
||||
}}
|
||||
disabled={isExporting}
|
||||
className="p-2 text-gray-400 rounded-full hover:bg-red-100 hover:text-red-600 transition-colors disabled:opacity-50"
|
||||
className="p-2 text-grey-700 rounded-full hover:bg-error-light hover:text-error transition-colors disabled:opacity-50"
|
||||
title={`Delete ${proof.proofName}`}
|
||||
>
|
||||
<TrashIcon className="h-5 w-5" />
|
||||
|
|
@ -1450,26 +1450,26 @@ const ProofDetailView: React.FC<{
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-brand-gray">
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-grey-100">
|
||||
<header className="mb-8">
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={onBack}
|
||||
className="p-2 text-gray-500 rounded-full hover:bg-gray-200 hover:text-brand-dark-blue transition-colors duration-200"
|
||||
className="p-2 text-grey-700 rounded-full hover:bg-grey-300 hover:text-primary-blue transition-colors duration-200"
|
||||
title="Back to campaign details"
|
||||
aria-label="Back to campaign details"
|
||||
>
|
||||
<ArrowLeftIcon className="h-6 w-6" />
|
||||
</button>
|
||||
<div>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-brand-dark-blue">{proof.proofName}</h1>
|
||||
<div className="flex items-center gap-2 mt-2 text-sm text-gray-500 font-medium">
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-primary-blue">{proof.proofName}</h1>
|
||||
<div className="flex items-center gap-2 mt-2 text-sm text-grey-700 font-medium">
|
||||
<span>{proof.channel}</span>
|
||||
<span className="text-gray-300">•</span>
|
||||
<span className="text-grey-300">•</span>
|
||||
<span>{proof.subChannel}</span>
|
||||
{proof.proofType && (
|
||||
<>
|
||||
<span className="text-gray-300">•</span>
|
||||
<span className="text-grey-300">•</span>
|
||||
<span>{proof.proofType}</span>
|
||||
</>
|
||||
)}
|
||||
|
|
@ -1482,7 +1482,7 @@ const ProofDetailView: React.FC<{
|
|||
<div className="lg:col-span-1">
|
||||
<div className="sticky top-8 flex flex-col gap-y-6">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-brand-dark-blue mb-4">
|
||||
<h2 className="text-2xl font-bold text-primary-blue mb-4">
|
||||
Proof Preview
|
||||
</h2>
|
||||
<ProofPreview
|
||||
|
|
@ -1494,14 +1494,14 @@ const ProofDetailView: React.FC<{
|
|||
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-3 gap-2">
|
||||
<h3 className="text-xl font-bold text-brand-dark-blue flex items-center gap-2">
|
||||
<HistoryIcon className="h-6 w-6 text-brand-accent"/>
|
||||
<h3 className="text-xl font-bold text-primary-blue flex items-center gap-2">
|
||||
<HistoryIcon className="h-6 w-6 text-active-blue"/>
|
||||
Version History
|
||||
</h3>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
onClick={handleDownload}
|
||||
className="flex items-center gap-2 text-sm bg-brand-accent text-white font-semibold py-1.5 px-3 rounded-lg border border-transparent hover:bg-brand-dark-blue transition-colors duration-200"
|
||||
className="flex items-center gap-2 text-sm bg-active-blue text-white font-semibold py-1.5 px-3 rounded-full border border-transparent hover:bg-active-blue/90 transition-colors duration-200"
|
||||
title={`Download Version ${selectedVersion.version}`}
|
||||
>
|
||||
<DownloadIcon className="h-4 w-4" />
|
||||
|
|
@ -1510,7 +1510,7 @@ const ProofDetailView: React.FC<{
|
|||
<button
|
||||
onClick={handleDownloadReport}
|
||||
disabled={isExporting}
|
||||
className="flex items-center gap-2 text-sm bg-white text-brand-accent font-semibold py-1.5 px-3 rounded-lg border border-brand-accent hover:bg-brand-accent/10 transition-colors duration-200 disabled:bg-gray-200 disabled:text-gray-500 disabled:cursor-wait"
|
||||
className="flex items-center gap-2 text-sm bg-white text-active-blue font-semibold py-1.5 px-3 rounded-full border-2 border-active-blue hover:bg-active-blue hover:text-white transition-colors duration-200 disabled:bg-grey-300 disabled:text-grey-700 disabled:border-grey-300 disabled:cursor-wait"
|
||||
title={`Download Report for Version ${selectedVersion.version}`}
|
||||
>
|
||||
{isExporting ? (
|
||||
|
|
@ -1528,7 +1528,7 @@ const ProofDetailView: React.FC<{
|
|||
<button
|
||||
onClick={handleUploadClick}
|
||||
disabled={isUploadingNewVersion}
|
||||
className="flex items-center gap-2 text-sm bg-white text-brand-accent font-semibold py-1.5 px-3 rounded-lg border border-brand-accent hover:bg-brand-accent/10 transition-colors duration-200 disabled:bg-gray-200 disabled:text-gray-500 disabled:cursor-wait"
|
||||
className="flex items-center gap-2 text-sm bg-white text-active-blue font-semibold py-1.5 px-3 rounded-full border-2 border-active-blue hover:bg-active-blue hover:text-white transition-colors duration-200 disabled:bg-grey-300 disabled:text-grey-700 disabled:border-grey-300 disabled:cursor-wait"
|
||||
title="Upload a new version of this proof"
|
||||
>
|
||||
{isUploadingNewVersion ? (
|
||||
|
|
@ -1557,20 +1557,20 @@ const ProofDetailView: React.FC<{
|
|||
{versions.map((version: any, index: number) => {
|
||||
const isActive = index === selectedVersionIndex;
|
||||
return (
|
||||
<button
|
||||
<button
|
||||
key={version.version}
|
||||
onClick={() => setSelectedVersionIndex(index)}
|
||||
className={`w-full text-left p-3 rounded-lg border-2 transition-all ${
|
||||
isActive
|
||||
? 'bg-brand-accent/10 border-brand-accent shadow-sm'
|
||||
: 'bg-white border-gray-200 hover:border-brand-accent/50 hover:bg-gray-50'
|
||||
className={`w-full text-left p-3 rounded-[10px] border-2 transition-all ${
|
||||
isActive
|
||||
? 'bg-info-light border-active-blue shadow-sm'
|
||||
: 'bg-white border-grey-300 hover:border-active-blue/50 hover:bg-grey-100'
|
||||
}`}
|
||||
>
|
||||
<div className="flex justify-between items-center">
|
||||
<p className={`font-bold ${isActive ? 'text-brand-dark-blue' : 'text-gray-800'}`}>Version {version.version}</p>
|
||||
<p className="text-xs text-gray-500">{version.timestamp}</p>
|
||||
<p className={`font-bold ${isActive ? 'text-primary-blue' : 'text-black-title'}`}>Version {version.version}</p>
|
||||
<p className="text-xs text-grey-700">{version.timestamp}</p>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 mt-1">Workfront ID: {version.workfrontId}</p>
|
||||
<p className="text-sm text-grey-900 mt-1">Workfront ID: {version.workfrontId}</p>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
|
|
@ -1580,11 +1580,11 @@ const ProofDetailView: React.FC<{
|
|||
</div>
|
||||
<div className="mt-12 lg:mt-0 lg:col-span-2">
|
||||
{selectedVersion.isIdenticalFile && (
|
||||
<div className="mb-6 bg-amber-50 border border-amber-200 rounded-lg p-4 flex items-start gap-3">
|
||||
<ExclamationTriangleIcon className="w-5 h-5 text-amber-600 flex-shrink-0 mt-0.5" />
|
||||
<div className="mb-6 bg-warning-light border border-warning rounded-[10px] p-4 flex items-start gap-3">
|
||||
<ExclamationTriangleIcon className="w-5 h-5 text-warning flex-shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<p className="font-semibold text-amber-800">Identical File Detected</p>
|
||||
<p className="text-sm text-amber-700 mt-1">
|
||||
<p className="font-semibold text-black-title">Identical File Detected</p>
|
||||
<p className="text-sm text-grey-900 mt-1">
|
||||
This file is exactly the same as the previous version.
|
||||
The analysis results shown are from the new analysis,
|
||||
but no changes were made to the creative.
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ export const CopyGenAI: React.FC = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-full bg-brand-gray">
|
||||
<div className="flex h-full bg-grey-100">
|
||||
{/* Conversation History Sidebar */}
|
||||
<aside className="w-80 flex-shrink-0 bg-gray-100 border-r border-gray-200 flex flex-col">
|
||||
<div className="p-4 border-b border-gray-200">
|
||||
<button className="w-full flex items-center justify-center gap-2 bg-brand-accent text-white font-semibold py-2.5 px-4 rounded-lg hover:bg-brand-dark-blue transition-colors duration-300">
|
||||
<button className="w-full flex items-center justify-center gap-2 bg-active-blue text-white font-semibold py-2.5 px-4 rounded-lg hover:bg-primary-blue transition-colors duration-300">
|
||||
<PlusIcon className="h-5 w-5" />
|
||||
Start new conversation
|
||||
</button>
|
||||
|
|
@ -41,7 +41,7 @@ export const CopyGenAI: React.FC = () => {
|
|||
onClick={() => setActiveConversationId(convo.id)}
|
||||
className={`w-full flex items-center gap-3 px-3 py-2.5 text-left text-sm font-medium rounded-md transition-colors duration-200 ${
|
||||
activeConversationId === convo.id
|
||||
? 'bg-brand-accent/10 text-brand-accent'
|
||||
? 'bg-active-blue/10 text-active-blue'
|
||||
: 'text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
|
|
@ -71,7 +71,7 @@ export const CopyGenAI: React.FC = () => {
|
|||
{/* Message Display */}
|
||||
<div className="flex-1 flex flex-col items-center justify-center p-8">
|
||||
<div className="text-center">
|
||||
<h1 className="text-3xl font-bold text-brand-dark-blue">CopyGenAI</h1>
|
||||
<h1 className="text-3xl font-bold text-primary-blue">CopyGenAI</h1>
|
||||
<p className="mt-2 text-gray-600">How can I help you today?</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -89,13 +89,13 @@ export const CopyGenAI: React.FC = () => {
|
|||
handleSendMessage(e);
|
||||
}
|
||||
}}
|
||||
className="w-full p-3 pr-14 border border-gray-300 rounded-lg resize-none focus:ring-2 focus:ring-brand-accent focus:border-brand-accent transition"
|
||||
className="w-full p-3 pr-14 border border-gray-300 rounded-lg resize-none focus:ring-2 focus:ring-active-blue focus:border-active-blue transition"
|
||||
placeholder="Type your message here..."
|
||||
rows={1}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="absolute right-3 top-1/2 -translate-y-1/2 p-2 rounded-full text-white bg-brand-accent hover:bg-brand-dark-blue disabled:bg-gray-400 transition-colors"
|
||||
className="absolute right-3 top-1/2 -translate-y-1/2 p-2 rounded-full text-white bg-active-blue hover:bg-primary-blue disabled:bg-gray-400 transition-colors"
|
||||
disabled={!message.trim()}
|
||||
aria-label="Send message"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -55,14 +55,14 @@ export const CreateProjectModal: React.FC<CreateProjectModalProps> = ({ isOpen,
|
|||
setError("Workfront Project ID must be in the format '#WF_12345'");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
setError(null);
|
||||
onAddProject({ name, workfrontId, clientLead });
|
||||
onClose();
|
||||
};
|
||||
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
|
||||
const isFormInvalid = !name.trim() || !workfrontId.trim() || !clientLead.trim();
|
||||
|
||||
return (
|
||||
|
|
@ -73,69 +73,69 @@ export const CreateProjectModal: React.FC<CreateProjectModalProps> = ({ isOpen,
|
|||
role="dialog"
|
||||
>
|
||||
<div
|
||||
className="bg-white rounded-lg shadow-xl p-6 sm:p-8 w-full max-w-lg transform transition-all"
|
||||
className="bg-white rounded-[10px] shadow-xl p-6 sm:p-8 w-full max-w-lg transform transition-all"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<h2 className="text-2xl font-bold text-brand-dark-blue">Create New Project</h2>
|
||||
<button onClick={onClose} className="p-1 rounded-full text-gray-500 hover:bg-gray-200 hover:text-gray-800 transition-colors">
|
||||
<h2 className="text-2xl font-bold text-primary-blue">Create New Project</h2>
|
||||
<button onClick={onClose} className="p-1 rounded-full text-grey-700 hover:bg-grey-100 hover:text-black-title transition-colors">
|
||||
<XIcon className="h-6 w-6" />
|
||||
</button>
|
||||
</div>
|
||||
<form onSubmit={handleSubmit} noValidate>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label htmlFor="project-name" className="block text-sm font-medium text-gray-700">Project Name</label>
|
||||
<label htmlFor="project-name" className="block text-sm font-medium text-black-title">Project Name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="project-name"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
className="mt-1 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-brand-accent focus:border-brand-accent transition bg-white text-gray-900"
|
||||
className="mt-1 block w-full p-2 border-2 border-grey-700 rounded-[10px] shadow-sm focus:ring-active-blue focus:border-active-blue transition bg-white text-black-title"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="workfront-id" className="block text-sm font-medium text-gray-700">Workfront Project ID</label>
|
||||
<label htmlFor="workfront-id" className="block text-sm font-medium text-black-title">Workfront Project ID</label>
|
||||
<input
|
||||
type="text"
|
||||
id="workfront-id"
|
||||
value={workfrontId}
|
||||
onChange={handleWorkfrontIdChange}
|
||||
className={`mt-1 block w-full p-2 border rounded-md shadow-sm focus:ring-brand-accent focus:border-brand-accent transition bg-white text-gray-900 placeholder:text-gray-400 ${error ? 'border-red-500 focus:border-red-500 focus:ring-red-500' : 'border-gray-300'}`}
|
||||
className={`mt-1 block w-full p-2 border-2 rounded-[10px] shadow-sm focus:ring-active-blue focus:border-active-blue transition bg-white text-black-title placeholder:text-grey-700 ${error ? 'border-error focus:border-error focus:ring-error' : 'border-grey-700'}`}
|
||||
placeholder="#WF_12345"
|
||||
required
|
||||
aria-invalid={!!error}
|
||||
aria-describedby="workfront-id-error"
|
||||
/>
|
||||
{error && <p id="workfront-id-error" className="mt-1 text-sm text-red-600">{error}</p>}
|
||||
{error && <p id="workfront-id-error" className="mt-1 text-sm text-error">{error}</p>}
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="client-lead" className="block text-sm font-medium text-gray-700">Client Lead</label>
|
||||
<label htmlFor="client-lead" className="block text-sm font-medium text-black-title">Client Lead</label>
|
||||
<input
|
||||
type="text"
|
||||
id="client-lead"
|
||||
value={clientLead}
|
||||
onChange={(e) => setClientLead(e.target.value)}
|
||||
className="mt-1 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-brand-accent focus:border-brand-accent transition bg-white text-gray-900"
|
||||
className="mt-1 block w-full p-2 border-2 border-grey-700 rounded-[10px] shadow-sm focus:ring-active-blue focus:border-active-blue transition bg-white text-black-title"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700">Agency</label>
|
||||
<label className="block text-sm font-medium text-black-title">Agency</label>
|
||||
<input
|
||||
type="text"
|
||||
value="OLIVER Agency"
|
||||
className="mt-1 block w-full p-2 border border-gray-300 rounded-md shadow-sm bg-gray-100 text-gray-600 cursor-not-allowed"
|
||||
className="mt-1 block w-full p-2 border-2 border-grey-300 rounded-[10px] shadow-sm bg-grey-100 text-grey-900 cursor-not-allowed"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700">Agency Lead</label>
|
||||
<label className="block text-sm font-medium text-black-title">Agency Lead</label>
|
||||
<input
|
||||
type="text"
|
||||
value="Steve O'Donoghue"
|
||||
className="mt-1 block w-full p-2 border border-gray-300 rounded-md shadow-sm bg-gray-100 text-gray-600 cursor-not-allowed"
|
||||
className="mt-1 block w-full p-2 border-2 border-grey-300 rounded-[10px] shadow-sm bg-grey-100 text-grey-900 cursor-not-allowed"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -144,13 +144,13 @@ export const CreateProjectModal: React.FC<CreateProjectModalProps> = ({ isOpen,
|
|||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="bg-gray-200 text-gray-800 font-semibold py-2 px-4 rounded-md hover:bg-gray-300 transition-colors duration-300"
|
||||
className="border-2 border-active-blue text-active-blue font-semibold py-2 px-6 rounded-full hover:bg-active-blue hover:text-white transition-colors duration-300"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-brand-accent text-white font-semibold py-2 px-4 rounded-md hover:bg-brand-dark-blue transition-colors duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||||
className="bg-active-blue text-white font-semibold py-2 px-6 rounded-full hover:bg-active-blue/90 transition-colors duration-300 disabled:bg-grey-700 disabled:cursor-not-allowed"
|
||||
disabled={isFormInvalid || !!error}
|
||||
>
|
||||
Create Project
|
||||
|
|
@ -160,4 +160,4 @@ export const CreateProjectModal: React.FC<CreateProjectModalProps> = ({ isOpen,
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -202,8 +202,8 @@ const FlagIssueModal: React.FC<{
|
|||
>
|
||||
<div className="flex justify-between items-start mb-6">
|
||||
<div>
|
||||
<h3 className="text-2xl font-bold text-brand-dark-blue">Flag Feedback</h3>
|
||||
<p className="text-slate-500 text-sm mt-1">Reporting incorrect feedback from <span className="font-semibold text-brand-accent">{agentName}</span></p>
|
||||
<h3 className="text-2xl font-bold text-primary-blue">Flag Feedback</h3>
|
||||
<p className="text-slate-500 text-sm mt-1">Reporting incorrect feedback from <span className="font-semibold text-active-blue">{agentName}</span></p>
|
||||
</div>
|
||||
<button onClick={onClose} className="p-2 rounded-full hover:bg-slate-100 text-slate-400 hover:text-slate-600 transition-colors">
|
||||
<XIcon className="h-6 w-6" />
|
||||
|
|
@ -491,7 +491,7 @@ const SubReviewCard: React.FC<{
|
|||
{issue.status === 'actionable' ? (
|
||||
<button
|
||||
onClick={() => handleOpenModal(actualIndex)}
|
||||
className="flex-shrink-0 opacity-0 group-hover/issue:opacity-100 focus:opacity-100 text-xs font-semibold text-brand-accent hover:text-brand-dark-blue bg-brand-light-blue/10 hover:bg-brand-light-blue/20 px-2.5 py-1 rounded-lg transition-all"
|
||||
className="flex-shrink-0 opacity-0 group-hover/issue:opacity-100 focus:opacity-100 text-xs font-semibold text-active-blue hover:text-primary-blue bg-cyan-brand/10 hover:bg-cyan-brand/20 px-2.5 py-1 rounded-lg transition-all"
|
||||
>
|
||||
Mark Resolved
|
||||
</button>
|
||||
|
|
@ -506,7 +506,7 @@ const SubReviewCard: React.FC<{
|
|||
</span>
|
||||
<button
|
||||
onClick={() => handleReopen(actualIndex)}
|
||||
className="text-xs font-semibold text-slate-400 hover:text-brand-dark-blue bg-slate-100 hover:bg-slate-200 px-2.5 py-1 rounded-lg transition-all"
|
||||
className="text-xs font-semibold text-slate-400 hover:text-primary-blue bg-slate-100 hover:bg-slate-200 px-2.5 py-1 rounded-lg transition-all"
|
||||
>
|
||||
Re-open
|
||||
</button>
|
||||
|
|
@ -566,7 +566,7 @@ const SubReviewCard: React.FC<{
|
|||
{issue.status === 'actionable' ? (
|
||||
<button
|
||||
onClick={() => handleOpenModal(actualIndex)}
|
||||
className="flex-shrink-0 opacity-0 group-hover/issue:opacity-100 focus:opacity-100 text-xs font-semibold text-brand-accent hover:text-brand-dark-blue bg-brand-light-blue/10 hover:bg-brand-light-blue/20 px-2.5 py-1 rounded-lg transition-all"
|
||||
className="flex-shrink-0 opacity-0 group-hover/issue:opacity-100 focus:opacity-100 text-xs font-semibold text-active-blue hover:text-primary-blue bg-cyan-brand/10 hover:bg-cyan-brand/20 px-2.5 py-1 rounded-lg transition-all"
|
||||
>
|
||||
Mark Resolved
|
||||
</button>
|
||||
|
|
@ -581,7 +581,7 @@ const SubReviewCard: React.FC<{
|
|||
</span>
|
||||
<button
|
||||
onClick={() => handleReopen(actualIndex)}
|
||||
className="text-xs font-semibold text-slate-400 hover:text-brand-dark-blue bg-slate-100 hover:bg-slate-200 px-2.5 py-1 rounded-lg transition-all"
|
||||
className="text-xs font-semibold text-slate-400 hover:text-primary-blue bg-slate-100 hover:bg-slate-200 px-2.5 py-1 rounded-lg transition-all"
|
||||
>
|
||||
Re-open
|
||||
</button>
|
||||
|
|
@ -627,7 +627,7 @@ const SubReviewCard: React.FC<{
|
|||
{issue.status === 'actionable' ? (
|
||||
<button
|
||||
onClick={() => handleOpenModal(index)}
|
||||
className="flex-shrink-0 opacity-0 group-hover/issue:opacity-100 focus:opacity-100 text-xs font-semibold text-brand-accent hover:text-brand-dark-blue bg-brand-light-blue/10 hover:bg-brand-light-blue/20 px-2.5 py-1 rounded-lg transition-all"
|
||||
className="flex-shrink-0 opacity-0 group-hover/issue:opacity-100 focus:opacity-100 text-xs font-semibold text-active-blue hover:text-primary-blue bg-cyan-brand/10 hover:bg-cyan-brand/20 px-2.5 py-1 rounded-lg transition-all"
|
||||
>
|
||||
Mark Resolved
|
||||
</button>
|
||||
|
|
@ -642,7 +642,7 @@ const SubReviewCard: React.FC<{
|
|||
</span>
|
||||
<button
|
||||
onClick={() => handleReopen(index)}
|
||||
className="text-xs font-semibold text-slate-400 hover:text-brand-dark-blue bg-slate-100 hover:bg-slate-200 px-2.5 py-1 rounded-lg transition-all"
|
||||
className="text-xs font-semibold text-slate-400 hover:text-primary-blue bg-slate-100 hover:bg-slate-200 px-2.5 py-1 rounded-lg transition-all"
|
||||
>
|
||||
Re-open
|
||||
</button>
|
||||
|
|
@ -670,8 +670,8 @@ const SubReviewCard: React.FC<{
|
|||
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 themeStyles = 'from-sky-50 to-white border-sky-100 text-primary-blue';
|
||||
let iconBg = 'bg-sky-100 text-active-blue';
|
||||
let icon = <InformationCircleIcon className="h-8 w-8" />;
|
||||
let blobColor = 'bg-sky-400';
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import { EagleIcon } from './icons/EagleIcon';
|
|||
|
||||
export const Header: React.FC = () => {
|
||||
return (
|
||||
<header className="bg-brand-dark-blue p-4 shadow-md">
|
||||
<header className="bg-primary-blue p-4 shadow-md">
|
||||
<div className="max-w-7xl mx-auto flex items-center">
|
||||
<EagleIcon className="h-10 w-10 text-brand-light-blue" />
|
||||
<EagleIcon className="h-10 w-10 text-cyan-brand" />
|
||||
<h1 className="text-xl sm:text-2xl font-bold text-white ml-3">
|
||||
AI Proof Reviewer
|
||||
</h1>
|
||||
|
|
|
|||
|
|
@ -6,15 +6,15 @@ export const LoadingVisual: React.FC = () => {
|
|||
<div className="flex flex-col items-center justify-center text-center py-20 px-6 min-h-[600px]">
|
||||
<div className="relative flex items-center justify-center w-48 h-48">
|
||||
{/* Pulsing circles */}
|
||||
<div className="absolute w-full h-full rounded-full bg-brand-accent/20 animate-slow-ping"></div>
|
||||
<div className="absolute w-3/4 h-3/4 rounded-full bg-brand-accent/30 animate-slow-ping [animation-delay:-1s]"></div>
|
||||
<div className="absolute w-full h-full rounded-full bg-active-blue/20 animate-slow-ping"></div>
|
||||
<div className="absolute w-3/4 h-3/4 rounded-full bg-active-blue/30 animate-slow-ping [animation-delay:-1s]"></div>
|
||||
|
||||
{/* Central Icon */}
|
||||
<div className="relative bg-white backdrop-blur-sm rounded-full p-6 border border-gray-200 shadow-lg flex items-center justify-center w-28 h-28">
|
||||
<BarclaysLogo className="h-16 w-16 text-brand-accent" />
|
||||
<BarclaysLogo className="h-16 w-16 text-active-blue" />
|
||||
</div>
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-brand-dark-blue mt-12">
|
||||
<h2 className="text-2xl font-bold text-primary-blue mt-12">
|
||||
Finalizing your report...
|
||||
</h2>
|
||||
<p className="text-gray-500 mt-2 max-w-md">
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ const SupportModal: React.FC<{
|
|||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<h3 className="text-xl font-bold text-brand-dark-blue">Contact Support</h3>
|
||||
<h3 className="text-xl font-bold text-primary-blue">Contact Support</h3>
|
||||
<button onClick={onClose} className="-mt-2 -mr-2 p-2 rounded-full hover:bg-gray-200 transition-colors">
|
||||
<XIcon className="h-6 w-6 text-gray-600" />
|
||||
</button>
|
||||
|
|
@ -78,7 +78,7 @@ const SupportModal: React.FC<{
|
|||
<textarea
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
className="w-full p-3 border border-gray-300 rounded-md focus:ring-2 focus:ring-brand-accent focus:border-brand-accent transition"
|
||||
className="w-full p-3 border border-gray-300 rounded-md focus:ring-2 focus:ring-active-blue focus:border-active-blue transition"
|
||||
rows={5}
|
||||
placeholder="Type your message here..."
|
||||
required
|
||||
|
|
@ -95,7 +95,7 @@ const SupportModal: React.FC<{
|
|||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-brand-accent text-white font-semibold py-2 px-4 rounded-md hover:bg-brand-dark-blue transition-colors duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
className="bg-active-blue text-white font-semibold py-2 px-4 rounded-md hover:bg-primary-blue transition-colors duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
disabled={!query.trim() || isSubmitting}
|
||||
>
|
||||
{isSubmitting ? (
|
||||
|
|
@ -163,10 +163,10 @@ export const Login: React.FC = () => {
|
|||
{/* Modern Glassy Background */}
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
{/* Top Left Blob */}
|
||||
<div className="absolute -top-[20%] -left-[10%] w-[70%] h-[70%] rounded-full bg-gradient-to-br from-brand-accent/30 to-purple-600/30 blur-[120px] animate-pulse" style={{ animationDuration: '8s' }}></div>
|
||||
<div className="absolute -top-[20%] -left-[10%] w-[70%] h-[70%] rounded-full bg-gradient-to-br from-active-blue/30 to-purple-600/30 blur-[120px] animate-pulse" style={{ animationDuration: '8s' }}></div>
|
||||
|
||||
{/* Bottom Right Blob */}
|
||||
<div className="absolute -bottom-[20%] -right-[10%] w-[70%] h-[70%] rounded-full bg-gradient-to-tl from-brand-light-blue/30 to-emerald-500/30 blur-[120px] animate-pulse" style={{ animationDuration: '10s', animationDelay: '1s' }}></div>
|
||||
<div className="absolute -bottom-[20%] -right-[10%] w-[70%] h-[70%] rounded-full bg-gradient-to-tl from-cyan-brand/30 to-emerald-500/30 blur-[120px] animate-pulse" style={{ animationDuration: '10s', animationDelay: '1s' }}></div>
|
||||
|
||||
{/* Noise Texture */}
|
||||
<div className="absolute inset-0 bg-[url('https://grainy-gradients.vercel.app/noise.svg')] opacity-20 mix-blend-soft-light"></div>
|
||||
|
|
@ -175,10 +175,10 @@ export const Login: React.FC = () => {
|
|||
{/* Login Card */}
|
||||
<div className="relative z-10 bg-white/90 backdrop-blur-xl p-8 sm:p-12 shadow-2xl rounded-3xl w-full max-w-md flex flex-col items-center text-center border border-white/50 ring-1 ring-white/50">
|
||||
<div className="mb-8 transform transition-transform hover:scale-105 duration-300">
|
||||
<BarclaysLogo className="h-12 w-auto text-brand-dark-blue" />
|
||||
<BarclaysLogo className="h-12 w-auto text-primary-blue" />
|
||||
</div>
|
||||
|
||||
<h1 className="text-3xl font-extrabold text-brand-dark-blue mb-2 tracking-tight">Mod Comms</h1>
|
||||
<h1 className="text-3xl font-extrabold text-primary-blue mb-2 tracking-tight">Mod Comms</h1>
|
||||
<p className="text-slate-500 mb-8 font-medium">Proof Review & Compliance Platform</p>
|
||||
|
||||
<div className="w-full space-y-6">
|
||||
|
|
@ -204,7 +204,7 @@ export const Login: React.FC = () => {
|
|||
className="w-full flex items-center justify-center gap-3 bg-white hover:bg-gray-50 text-slate-700 font-bold py-4 px-6 rounded-xl border border-gray-200 shadow-lg shadow-gray-200/50 hover:shadow-xl hover:border-gray-300 transition-all duration-300 group disabled:opacity-70 disabled:cursor-wait transform hover:-translate-y-0.5"
|
||||
>
|
||||
{isLoggingIn ? (
|
||||
<svg className="animate-spin h-5 w-5 text-brand-accent" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<svg className="animate-spin h-5 w-5 text-active-blue" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
|
|
@ -221,7 +221,7 @@ export const Login: React.FC = () => {
|
|||
<button
|
||||
type="button"
|
||||
onClick={() => setIsSupportModalOpen(true)}
|
||||
className="text-sm text-slate-500 hover:text-brand-accent transition-colors font-medium"
|
||||
className="text-sm text-slate-500 hover:text-active-blue transition-colors font-medium"
|
||||
>
|
||||
Having trouble signing in? Contact Support
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -73,15 +73,15 @@ export const Profile: React.FC<ProfileProps> = ({ onLogout, msalInstance }) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-brand-gray">
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-grey-100">
|
||||
<header className="mb-8">
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-brand-dark-blue">Your Profile</h1>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-primary-blue">Your Profile</h1>
|
||||
<p className="text-base lg:text-lg text-gray-600 mt-1">View your account details and manage settings.</p>
|
||||
</header>
|
||||
|
||||
<div className="max-w-3xl">
|
||||
<section className="bg-white rounded-lg shadow-md p-6 sm:p-8 border border-gray-200">
|
||||
<h2 className="text-2xl font-bold text-brand-dark-blue mb-6">Account Information</h2>
|
||||
<h2 className="text-2xl font-bold text-primary-blue mb-6">Account Information</h2>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-x-8 gap-y-5">
|
||||
{Object.entries(userDetails).map(([key, value]) => (
|
||||
<div key={key}>
|
||||
|
|
@ -111,7 +111,7 @@ export const Profile: React.FC<ProfileProps> = ({ onLogout, msalInstance }) => {
|
|||
|
||||
{isQuestionFormVisible && (
|
||||
<section className="mt-8 bg-white rounded-lg shadow-md p-6 sm:p-8 border border-gray-200">
|
||||
<h2 className="text-2xl font-bold text-brand-dark-blue mb-4">Ask a Question</h2>
|
||||
<h2 className="text-2xl font-bold text-primary-blue mb-4">Ask a Question</h2>
|
||||
<form onSubmit={handleSubmitQuestion}>
|
||||
<p className="text-gray-600 mb-4">Your question will be sent to the OLIVER Agency support team.</p>
|
||||
{submitStatus && (
|
||||
|
|
@ -122,7 +122,7 @@ export const Profile: React.FC<ProfileProps> = ({ onLogout, msalInstance }) => {
|
|||
<textarea
|
||||
value={question}
|
||||
onChange={(e) => setQuestion(e.target.value)}
|
||||
className="w-full p-3 border border-gray-300 rounded-md focus:ring-2 focus:ring-brand-accent focus:border-brand-accent transition"
|
||||
className="w-full p-3 border border-gray-300 rounded-md focus:ring-2 focus:ring-active-blue focus:border-active-blue transition"
|
||||
placeholder="Type your question here..."
|
||||
rows={5}
|
||||
required
|
||||
|
|
@ -131,7 +131,7 @@ export const Profile: React.FC<ProfileProps> = ({ onLogout, msalInstance }) => {
|
|||
<div className="mt-4 flex justify-end">
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-brand-accent text-white font-semibold py-2 px-5 rounded-md hover:bg-brand-dark-blue transition-colors duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
className="bg-active-blue text-white font-semibold py-2 px-5 rounded-md hover:bg-primary-blue transition-colors duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed flex items-center gap-2"
|
||||
disabled={!question.trim() || isSubmitting}
|
||||
>
|
||||
{isSubmitting ? (
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ const ProjectList: React.FC<{
|
|||
const filteredProjects = showCompleted ? projects : projects.filter(p => p.status !== 'Completed');
|
||||
|
||||
const getStatusSelectClasses = (status: string) => {
|
||||
let baseClasses = 'w-full text-center px-2.5 py-0.5 text-xs font-semibold rounded-full border border-transparent focus:outline-none focus:ring-2 focus:ring-brand-accent appearance-none cursor-pointer';
|
||||
let baseClasses = 'w-full text-center px-2.5 py-0.5 text-xs font-semibold rounded-full border border-transparent focus:outline-none focus:ring-2 focus:ring-active-blue appearance-none cursor-pointer';
|
||||
let colorClasses = '';
|
||||
switch (status) {
|
||||
case 'In Progress':
|
||||
|
|
@ -225,11 +225,11 @@ const ProjectList: React.FC<{
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-brand-gray">
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-grey-100">
|
||||
<header className="mb-8">
|
||||
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
|
||||
<div>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-brand-dark-blue">Projects</h1>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-primary-blue">Projects</h1>
|
||||
<p className="text-base lg:text-lg text-gray-600 mt-1">Manage your campaigns and asset collections.</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
|
|
@ -239,7 +239,7 @@ const ProjectList: React.FC<{
|
|||
</div>
|
||||
<button
|
||||
onClick={onOpenModal}
|
||||
className="flex items-center gap-2 bg-brand-accent text-white font-semibold py-2 px-4 rounded-lg hover:bg-brand-dark-blue transition-colors duration-300"
|
||||
className="flex items-center gap-2 bg-active-blue text-white font-semibold py-2 px-4 rounded-lg hover:bg-primary-blue transition-colors duration-300"
|
||||
>
|
||||
<PlusIcon className="h-5 w-5" />
|
||||
Create New Project
|
||||
|
|
@ -266,7 +266,7 @@ const ProjectList: React.FC<{
|
|||
{filteredProjects.map((project) => {
|
||||
return (
|
||||
<tr key={project.name} className="hover:bg-gray-100 cursor-pointer" onClick={() => onSelectProject(project.name)}>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">{project.name}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-primary-blue">{project.name}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{project.assets}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm w-40">
|
||||
<div className="relative">
|
||||
|
|
@ -345,11 +345,11 @@ const ProjectAssetUpload: React.FC<{
|
|||
|
||||
return (
|
||||
<section className="bg-white rounded-lg shadow-md p-6 border border-gray-200 mb-8">
|
||||
<h2 className="text-xl font-bold text-brand-dark-blue mb-4">Upload New Asset</h2>
|
||||
<h2 className="text-xl font-bold text-primary-blue mb-4">Upload New Asset</h2>
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div>
|
||||
<label htmlFor="asset-name" className="flex items-center text-sm font-medium text-gray-700 mb-1">
|
||||
<DocumentIcon className="h-5 w-5 mr-2 text-brand-accent shrink-0" />
|
||||
<DocumentIcon className="h-5 w-5 mr-2 text-active-blue shrink-0" />
|
||||
Asset Name
|
||||
</label>
|
||||
<input
|
||||
|
|
@ -359,7 +359,7 @@ const ProjectAssetUpload: React.FC<{
|
|||
onChange={(e) => setAssetName(e.target.value)}
|
||||
placeholder="e.g., Q4 Hero Instagram Post"
|
||||
disabled={isLoading}
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 px-3 text-gray-900 focus:outline-none focus:ring-2 focus:ring-brand-accent disabled:bg-gray-100"
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 px-3 text-gray-900 focus:outline-none focus:ring-2 focus:ring-active-blue disabled:bg-gray-100"
|
||||
required
|
||||
/>
|
||||
{isNewVersion && (
|
||||
|
|
@ -372,7 +372,7 @@ const ProjectAssetUpload: React.FC<{
|
|||
{/* Channel Dropdown */}
|
||||
<div>
|
||||
<label htmlFor="asset-channel" className="flex items-center text-sm font-medium text-gray-700 mb-1">
|
||||
<ChannelIcon className="h-5 w-5 mr-2 text-brand-accent shrink-0" />
|
||||
<ChannelIcon className="h-5 w-5 mr-2 text-active-blue shrink-0" />
|
||||
Channel
|
||||
</label>
|
||||
<div className="relative">
|
||||
|
|
@ -381,7 +381,7 @@ const ProjectAssetUpload: React.FC<{
|
|||
value={channel}
|
||||
onChange={(e) => setChannel(e.target.value)}
|
||||
disabled={isLoading}
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 pl-3 pr-10 text-gray-900 focus:outline-none focus:ring-2 focus:ring-brand-accent appearance-none disabled:bg-gray-100"
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 pl-3 pr-10 text-gray-900 focus:outline-none focus:ring-2 focus:ring-active-blue appearance-none disabled:bg-gray-100"
|
||||
required
|
||||
>
|
||||
<option value="" disabled>Select Channel</option>
|
||||
|
|
@ -395,7 +395,7 @@ const ProjectAssetUpload: React.FC<{
|
|||
{/* Sub-Channel Dropdown */}
|
||||
<div>
|
||||
<label htmlFor="asset-sub-channel" className="flex items-center text-sm font-medium text-gray-700 mb-1">
|
||||
<TagIcon className="h-5 w-5 mr-2 text-brand-accent shrink-0" />
|
||||
<TagIcon className="h-5 w-5 mr-2 text-active-blue shrink-0" />
|
||||
Sub-Channel
|
||||
</label>
|
||||
<div className="relative">
|
||||
|
|
@ -404,7 +404,7 @@ const ProjectAssetUpload: React.FC<{
|
|||
value={subChannel}
|
||||
onChange={(e) => setSubChannel(e.target.value)}
|
||||
disabled={isLoading || !channel}
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 pl-3 pr-10 text-gray-900 focus:outline-none focus:ring-2 focus:ring-brand-accent appearance-none disabled:bg-gray-100 disabled:text-gray-400"
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 pl-3 pr-10 text-gray-900 focus:outline-none focus:ring-2 focus:ring-active-blue appearance-none disabled:bg-gray-100 disabled:text-gray-400"
|
||||
required
|
||||
>
|
||||
<option value="" disabled>Select Sub-Channel</option>
|
||||
|
|
@ -423,13 +423,13 @@ const ProjectAssetUpload: React.FC<{
|
|||
<div className="space-y-1 text-center">
|
||||
<UploadIcon className="mx-auto h-12 w-12 text-gray-400" />
|
||||
<div className="flex text-sm text-gray-600">
|
||||
<label htmlFor="file-upload" className="relative cursor-pointer bg-white rounded-md font-medium text-brand-accent hover:text-brand-dark-blue focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-brand-accent">
|
||||
<label htmlFor="file-upload" className="relative cursor-pointer bg-white rounded-md font-medium text-active-blue hover:text-primary-blue focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-active-blue">
|
||||
<span>Upload a file</span>
|
||||
<input id="file-upload" name="file-upload" type="file" className="sr-only" ref={fileInputRef} onChange={handleFileChange} disabled={isLoading} accept="image/png, image/jpeg, image/webp, image/gif, video/mp4, application/pdf" />
|
||||
</label>
|
||||
<p className="pl-1">or drag and drop</p>
|
||||
</div>
|
||||
{file ? <p className="text-sm font-semibold text-brand-dark-blue mt-2">{file.name}</p> : <p className="text-xs text-gray-500">PNG, JPG, GIF, WEBP, MP4, PDF</p>}
|
||||
{file ? <p className="text-sm font-semibold text-primary-blue mt-2">{file.name}</p> : <p className="text-xs text-gray-500">PNG, JPG, GIF, WEBP, MP4, PDF</p>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -438,7 +438,7 @@ const ProjectAssetUpload: React.FC<{
|
|||
<button type="button" onClick={onCancel} disabled={isLoading} className="bg-gray-200 text-gray-800 font-semibold py-2.5 px-5 rounded-lg hover:bg-gray-300 transition-colors duration-300 disabled:opacity-50">
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit" disabled={isSubmitDisabled} className="flex items-center justify-center bg-brand-accent text-white font-bold py-2.5 px-5 rounded-lg hover:bg-brand-dark-blue transition-all duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed">
|
||||
<button type="submit" disabled={isSubmitDisabled} className="flex items-center justify-center bg-active-blue text-white font-bold py-2.5 px-5 rounded-lg hover:bg-primary-blue transition-all duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed">
|
||||
{isLoading ? (
|
||||
<>
|
||||
<svg className="animate-spin -ml-1 mr-3 h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
|
|
@ -472,7 +472,7 @@ const LoadingCell: React.FC<{ progress: { completed: number; total: number } }>
|
|||
<div className="flex flex-col items-center justify-center h-full px-2 text-center w-full">
|
||||
<div className="w-full bg-gray-200 rounded-full h-1.5 mb-1.5">
|
||||
<div
|
||||
className="bg-brand-accent h-1.5 rounded-full"
|
||||
className="bg-active-blue h-1.5 rounded-full"
|
||||
style={{ width: `${percent}%`, transition: 'width 0.3s ease-in-out' }}
|
||||
></div>
|
||||
</div>
|
||||
|
|
@ -500,7 +500,7 @@ const DeleteConfirmationModal: React.FC<{
|
|||
className="bg-white rounded-lg shadow-xl p-6 sm:p-8 w-full max-w-md transform transition-all"
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
<h3 className="text-xl font-bold text-brand-dark-blue">Confirm Deletion</h3>
|
||||
<h3 className="text-xl font-bold text-primary-blue">Confirm Deletion</h3>
|
||||
<p className="text-gray-600 my-4">
|
||||
Are you sure you want to permanently delete the asset "{assetName}"? This action cannot be undone.
|
||||
</p>
|
||||
|
|
@ -577,7 +577,7 @@ const ProjectDetail: React.FC<{
|
|||
|
||||
|
||||
return (
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-brand-gray">
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-grey-100">
|
||||
<DeleteConfirmationModal
|
||||
isOpen={!!assetToDelete}
|
||||
onClose={() => setAssetToDelete(null)}
|
||||
|
|
@ -598,14 +598,14 @@ const ProjectDetail: React.FC<{
|
|||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={onBack}
|
||||
className="p-2 text-gray-500 rounded-full hover:bg-gray-200 hover:text-brand-dark-blue transition-colors duration-200"
|
||||
className="p-2 text-gray-500 rounded-full hover:bg-gray-200 hover:text-primary-blue transition-colors duration-200"
|
||||
title="Back to projects"
|
||||
aria-label="Back to projects list"
|
||||
>
|
||||
<ArrowLeftIcon className="h-6 w-6" />
|
||||
</button>
|
||||
<div>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-brand-dark-blue">{projectName}</h1>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-primary-blue">{projectName}</h1>
|
||||
<p className="text-base lg:text-lg text-gray-600 mt-1">Asset overview and compliance status.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -629,14 +629,14 @@ const ProjectDetail: React.FC<{
|
|||
<div className="mb-6 flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => console.log('Download all assets clicked')}
|
||||
className="flex items-center gap-2 bg-white text-brand-accent font-semibold py-2 px-4 rounded-lg border border-brand-accent hover:bg-brand-accent/10 transition-colors duration-300"
|
||||
className="flex items-center gap-2 bg-white text-active-blue font-semibold py-2 px-4 rounded-lg border border-active-blue hover:bg-active-blue/10 transition-colors duration-300"
|
||||
>
|
||||
<DownloadIcon className="h-5 w-5" />
|
||||
Download All Assets
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setIsUploadFormVisible(true)}
|
||||
className="flex items-center gap-2 bg-brand-accent text-white font-semibold py-2 px-4 rounded-lg hover:bg-brand-dark-blue transition-colors duration-300"
|
||||
className="flex items-center gap-2 bg-active-blue text-white font-semibold py-2 px-4 rounded-lg hover:bg-primary-blue transition-colors duration-300"
|
||||
>
|
||||
<PlusIcon className="h-5 w-5" />
|
||||
Upload New Asset
|
||||
|
|
@ -661,7 +661,7 @@ const ProjectDetail: React.FC<{
|
|||
if (asset.status === 'analyzing') {
|
||||
return (
|
||||
<tr key={asset.tempId} className="bg-gray-50 opacity-80">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">{asset.assetName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-primary-blue">{asset.assetName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 italic">Pending</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{asset.channel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{asset.subChannel}</td>
|
||||
|
|
@ -669,7 +669,7 @@ const ProjectDetail: React.FC<{
|
|||
{asset.analysisProgress ?
|
||||
<LoadingCell progress={asset.analysisProgress} /> :
|
||||
<div className="flex justify-center items-center h-full">
|
||||
<SpinnerIcon className="h-5 w-5 text-brand-accent custom-spinner" />
|
||||
<SpinnerIcon className="h-5 w-5 text-active-blue custom-spinner" />
|
||||
<span className="ml-2 text-sm text-gray-600">Preparing...</span>
|
||||
</div>
|
||||
}
|
||||
|
|
@ -681,7 +681,7 @@ const ProjectDetail: React.FC<{
|
|||
if (asset.status === 'error') {
|
||||
return (
|
||||
<tr key={asset.tempId} className="bg-red-50">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">{asset.assetName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-primary-blue">{asset.assetName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 italic">Failed</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{asset.channel}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{asset.subChannel}</td>
|
||||
|
|
@ -690,7 +690,7 @@ const ProjectDetail: React.FC<{
|
|||
<span>Analysis failed.</span>
|
||||
<button
|
||||
onClick={() => onRetryAnalysis(projectName, asset.tempId)}
|
||||
className="flex items-center gap-1.5 text-xs font-semibold text-brand-accent hover:text-brand-dark-blue whitespace-nowrap px-3 py-1.5 rounded-full bg-brand-accent/10 hover:bg-brand-accent/20 transition-colors"
|
||||
className="flex items-center gap-1.5 text-xs font-semibold text-active-blue hover:text-primary-blue whitespace-nowrap px-3 py-1.5 rounded-full bg-active-blue/10 hover:bg-active-blue/20 transition-colors"
|
||||
>
|
||||
<ArrowPathIcon className="h-4 w-4" />
|
||||
Retry
|
||||
|
|
@ -713,7 +713,7 @@ const ProjectDetail: React.FC<{
|
|||
className={isClickable ? "hover:bg-gray-100 cursor-pointer" : ""}
|
||||
onClick={() => isClickable && onSelectAsset(asset)}
|
||||
>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-primary-blue">
|
||||
{asset.assetName}
|
||||
{isVersioned && (
|
||||
<span className="ml-2 bg-gray-200 text-gray-700 text-xs font-bold px-2 py-0.5 rounded-full">
|
||||
|
|
@ -839,19 +839,19 @@ const AssetDetailView: React.FC<{
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-brand-gray">
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-grey-100">
|
||||
<header className="mb-8">
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={onBack}
|
||||
className="p-2 text-gray-500 rounded-full hover:bg-gray-200 hover:text-brand-dark-blue transition-colors duration-200"
|
||||
className="p-2 text-gray-500 rounded-full hover:bg-gray-200 hover:text-primary-blue transition-colors duration-200"
|
||||
title="Back to project details"
|
||||
aria-label="Back to project details"
|
||||
>
|
||||
<ArrowLeftIcon className="h-6 w-6" />
|
||||
</button>
|
||||
<div>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-brand-dark-blue">{asset.assetName}</h1>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-primary-blue">{asset.assetName}</h1>
|
||||
<p className="text-base lg:text-lg text-gray-600 mt-1">Detailed AI feedback report.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -861,7 +861,7 @@ const AssetDetailView: React.FC<{
|
|||
<div className="lg:col-span-1">
|
||||
<div className="sticky top-8 flex flex-col gap-y-6">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-brand-dark-blue mb-4">
|
||||
<h2 className="text-2xl font-bold text-primary-blue mb-4">
|
||||
Asset Preview
|
||||
</h2>
|
||||
<AssetPreview
|
||||
|
|
@ -872,14 +872,14 @@ const AssetDetailView: React.FC<{
|
|||
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-3 gap-2">
|
||||
<h3 className="text-xl font-bold text-brand-dark-blue flex items-center gap-2">
|
||||
<HistoryIcon className="h-6 w-6 text-brand-accent"/>
|
||||
<h3 className="text-xl font-bold text-primary-blue flex items-center gap-2">
|
||||
<HistoryIcon className="h-6 w-6 text-active-blue"/>
|
||||
Version History
|
||||
</h3>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
onClick={() => console.log('Download version clicked')}
|
||||
className="flex items-center gap-2 text-sm bg-brand-accent text-white font-semibold py-1.5 px-3 rounded-lg border border-transparent hover:bg-brand-dark-blue transition-colors duration-200"
|
||||
className="flex items-center gap-2 text-sm bg-active-blue text-white font-semibold py-1.5 px-3 rounded-lg border border-transparent hover:bg-primary-blue transition-colors duration-200"
|
||||
title={`Download Version ${selectedVersion.version}`}
|
||||
>
|
||||
<DownloadIcon className="h-4 w-4" />
|
||||
|
|
@ -888,7 +888,7 @@ const AssetDetailView: React.FC<{
|
|||
<button
|
||||
onClick={handleUploadClick}
|
||||
disabled={isUploadingNewVersion}
|
||||
className="flex items-center gap-2 text-sm bg-white text-brand-accent font-semibold py-1.5 px-3 rounded-lg border border-brand-accent hover:bg-brand-accent/10 transition-colors duration-200 disabled:bg-gray-200 disabled:text-gray-500 disabled:cursor-wait"
|
||||
className="flex items-center gap-2 text-sm bg-white text-active-blue font-semibold py-1.5 px-3 rounded-lg border border-active-blue hover:bg-active-blue/10 transition-colors duration-200 disabled:bg-gray-200 disabled:text-gray-500 disabled:cursor-wait"
|
||||
title="Upload a new version of this asset"
|
||||
>
|
||||
{isUploadingNewVersion ? (
|
||||
|
|
@ -922,12 +922,12 @@ const AssetDetailView: React.FC<{
|
|||
onClick={() => setSelectedVersionIndex(index)}
|
||||
className={`w-full text-left p-3 rounded-lg border-2 transition-all ${
|
||||
isActive
|
||||
? 'bg-brand-accent/10 border-brand-accent shadow-sm'
|
||||
: 'bg-white border-gray-200 hover:border-brand-accent/50 hover:bg-gray-50'
|
||||
? 'bg-active-blue/10 border-active-blue shadow-sm'
|
||||
: 'bg-white border-gray-200 hover:border-active-blue/50 hover:bg-gray-50'
|
||||
}`}
|
||||
>
|
||||
<div className="flex justify-between items-center">
|
||||
<p className={`font-bold ${isActive ? 'text-brand-dark-blue' : 'text-gray-800'}`}>Version {version.version}</p>
|
||||
<p className={`font-bold ${isActive ? 'text-primary-blue' : 'text-gray-800'}`}>Version {version.version}</p>
|
||||
<p className="text-xs text-gray-500">{version.timestamp}</p>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 mt-1">Workfront ID: {version.workfrontId}</p>
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ export const ProofPreview: React.FC<ProofPreviewProps> = ({ file, previewUrl, fi
|
|||
style={{ minHeight: '300px', maxHeight: 'calc(100vh - 9rem)' }}
|
||||
>
|
||||
<DocumentIcon className="h-20 w-20 text-gray-400 mb-4" />
|
||||
<p className="text-lg font-semibold text-brand-dark-blue break-all">{displayName}</p>
|
||||
<p className="text-lg font-semibold text-primary-blue break-all">{displayName}</p>
|
||||
<p className="text-sm text-gray-500">{fileType}</p>
|
||||
<p className="text-sm text-gray-500 mt-2">No preview available for this file type.</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ export const ProofTypeManager: React.FC<ProofTypeManagerProps> = ({
|
|||
|
||||
return (
|
||||
<div className="bg-white rounded-lg shadow-md p-6 border border-gray-200 flex flex-col h-full">
|
||||
<h2 className="text-xl font-bold text-brand-dark-blue mb-2">Proof Type Manager</h2>
|
||||
<h2 className="text-xl font-bold text-primary-blue mb-2">Proof Type Manager</h2>
|
||||
<p className="text-sm text-gray-500 mb-4">Assign and manage specific proof types for each sub-channel.</p>
|
||||
|
||||
<div className="mb-4">
|
||||
|
|
@ -51,7 +51,7 @@ export const ProofTypeManager: React.FC<ProofTypeManagerProps> = ({
|
|||
id="subchannel-select"
|
||||
value={selectedSubChannel}
|
||||
onChange={(e) => setSelectedSubChannel(e.target.value)}
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 pl-3 pr-10 text-gray-900 focus:outline-none focus:ring-2 focus:ring-brand-accent appearance-none disabled:bg-gray-100"
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 pl-3 pr-10 text-gray-900 focus:outline-none focus:ring-2 focus:ring-active-blue appearance-none disabled:bg-gray-100"
|
||||
disabled={disabled}
|
||||
>
|
||||
{subChannels.map(sc => (
|
||||
|
|
@ -70,12 +70,12 @@ export const ProofTypeManager: React.FC<ProofTypeManagerProps> = ({
|
|||
value={newItem}
|
||||
onChange={(e) => setNewItem(e.target.value)}
|
||||
placeholder="New Proof Type..."
|
||||
className="flex-grow p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-brand-accent focus:border-brand-accent transition disabled:bg-gray-100 disabled:cursor-not-allowed"
|
||||
className="flex-grow p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-active-blue focus:border-active-blue transition disabled:bg-gray-100 disabled:cursor-not-allowed"
|
||||
disabled={disabled || !selectedSubChannel}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-brand-accent text-white font-semibold py-2 px-4 rounded-md hover:bg-brand-dark-blue transition-colors duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||||
className="bg-active-blue text-white font-semibold py-2 px-4 rounded-md hover:bg-primary-blue transition-colors duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||||
disabled={!newItem.trim() || disabled || !selectedSubChannel}
|
||||
>
|
||||
Add
|
||||
|
|
|
|||
|
|
@ -27,15 +27,15 @@ const agentIcons: Record<AgentName, React.FC<React.SVGProps<SVGSVGElement>>> = {
|
|||
|
||||
const StatusInfo: React.FC<StatusInfoProps> = ({ status, isHeroVariant = false }) => {
|
||||
const colors = isHeroVariant ? {
|
||||
complete: 'text-green-300',
|
||||
issues: 'text-yellow-300',
|
||||
error: 'text-red-300',
|
||||
pending: 'text-gray-400'
|
||||
complete: 'text-success-light',
|
||||
issues: 'text-warning-light',
|
||||
error: 'text-error-light',
|
||||
pending: 'text-grey-300'
|
||||
} : {
|
||||
complete: 'text-green-600',
|
||||
issues: 'text-yellow-600',
|
||||
error: 'text-red-600',
|
||||
pending: 'text-gray-500'
|
||||
complete: 'text-success',
|
||||
issues: 'text-warning',
|
||||
error: 'text-error',
|
||||
pending: 'text-grey-700'
|
||||
};
|
||||
|
||||
switch (status) {
|
||||
|
|
@ -56,17 +56,17 @@ export const StatusDashboard: React.FC<StatusDashboardProps> = ({ status, varian
|
|||
const isHeroVariant = variant === 'hero';
|
||||
|
||||
const getTileClassName = (agentStatus: AgentStatus, isHero: boolean): string => {
|
||||
const baseClasses = 'rounded-lg flex flex-col text-center transition-colors duration-500 ease-in-out';
|
||||
|
||||
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-green-400/20`;
|
||||
return `${heroBase} bg-success/20`;
|
||||
case 'issues-found':
|
||||
return `${heroBase} bg-yellow-400/20`;
|
||||
return `${heroBase} bg-warning/20`;
|
||||
case 'error':
|
||||
return `${heroBase} bg-red-400/20`;
|
||||
return `${heroBase} bg-error/20`;
|
||||
default: // 'pending' or 'in-progress'
|
||||
return `${heroBase} bg-white/10`;
|
||||
}
|
||||
|
|
@ -74,24 +74,24 @@ export const StatusDashboard: React.FC<StatusDashboardProps> = ({ status, varian
|
|||
const defaultBase = `${baseClasses} p-6 shadow-lg border`;
|
||||
switch (agentStatus) {
|
||||
case 'complete':
|
||||
return `${defaultBase} bg-green-50 border-green-200`;
|
||||
return `${defaultBase} bg-success-light border-success`;
|
||||
case 'issues-found':
|
||||
return `${defaultBase} bg-yellow-50 border-yellow-200`;
|
||||
return `${defaultBase} bg-warning-light border-warning`;
|
||||
case 'error':
|
||||
return `${defaultBase} bg-red-50 border-red-200`;
|
||||
return `${defaultBase} bg-error-light border-error`;
|
||||
default: // 'pending' or 'in-progress'
|
||||
return `${defaultBase} bg-gray-50 border-gray-200`;
|
||||
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-brand-dark-blue'}`}>Review Progress</h3>
|
||||
<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-brand-light-blue' : 'text-brand-accent';
|
||||
const iconColor = isHeroVariant ? 'text-cyan-brand' : 'text-active-blue';
|
||||
const Icon = agentIcons[agentName];
|
||||
|
||||
return (
|
||||
|
|
@ -100,11 +100,11 @@ export const StatusDashboard: React.FC<StatusDashboardProps> = ({ status, varian
|
|||
<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-brand-dark-blue'}`}>{agentName}</h4>
|
||||
<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-gray-500'}`}>
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ export const ToggleSwitch: React.FC<ToggleSwitchProps> = ({ enabled, onChange })
|
|||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={`relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-brand-accent focus:ring-offset-2 ${
|
||||
enabled ? 'bg-brand-accent' : 'bg-gray-300'
|
||||
className={`relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-active-blue focus:ring-offset-2 ${
|
||||
enabled ? 'bg-active-blue' : 'bg-gray-300'
|
||||
}`}
|
||||
role="switch"
|
||||
aria-checked={enabled}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ const ConfirmationComponent: React.FC<{
|
|||
<select
|
||||
value={channel}
|
||||
onChange={e => setChannel(e.target.value)}
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 px-3 text-gray-900 focus:outline-none focus:ring-2 focus:ring-brand-accent appearance-none"
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 px-3 text-gray-900 focus:outline-none focus:ring-2 focus:ring-active-blue appearance-none"
|
||||
>
|
||||
<option value="" disabled>Select Channel</option>
|
||||
{availableChannels.map(opt => <option key={opt} value={opt}>{opt}</option>)}
|
||||
|
|
@ -91,7 +91,7 @@ const ConfirmationComponent: React.FC<{
|
|||
value={subChannel}
|
||||
onChange={e => setSubChannel(e.target.value)}
|
||||
disabled={!channel}
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 px-3 text-gray-900 focus:outline-none focus:ring-2 focus:ring-brand-accent appearance-none disabled:bg-gray-100"
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 px-3 text-gray-900 focus:outline-none focus:ring-2 focus:ring-active-blue appearance-none disabled:bg-gray-100"
|
||||
>
|
||||
<option value="" disabled>Select Sub-Channel</option>
|
||||
{availableSubChannels.map(opt => <option key={opt} value={opt}>{opt}</option>)}
|
||||
|
|
@ -104,7 +104,7 @@ const ConfirmationComponent: React.FC<{
|
|||
<select
|
||||
value={proofType}
|
||||
onChange={e => setProofType(e.target.value)}
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 px-3 text-gray-900 focus:outline-none focus:ring-2 focus:ring-brand-accent appearance-none"
|
||||
className="w-full bg-white border border-gray-300 rounded-md py-2 px-3 text-gray-900 focus:outline-none focus:ring-2 focus:ring-active-blue appearance-none"
|
||||
>
|
||||
<option value="" disabled>Select Proof Type</option>
|
||||
{availableProofTypes.map(opt => <option key={opt} value={opt}>{opt}</option>)}
|
||||
|
|
@ -115,7 +115,7 @@ const ConfirmationComponent: React.FC<{
|
|||
<button
|
||||
onClick={handleSubmit}
|
||||
disabled={isSubmitDisabled}
|
||||
className="w-full bg-brand-accent text-white font-bold py-2 px-4 rounded-md hover:bg-brand-dark-blue transition-colors disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||||
className="w-full bg-active-blue text-white font-bold py-2 px-4 rounded-md hover:bg-primary-blue transition-colors disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||||
>
|
||||
Confirm & Analyze
|
||||
</button>
|
||||
|
|
@ -127,12 +127,12 @@ const ConfirmationComponent: React.FC<{
|
|||
const MessageBubble: React.FC<{ sender: 'user' | 'agent'; children: React.ReactNode }> = ({ sender, children }) => {
|
||||
const isUser = sender === 'user';
|
||||
const bubbleClasses = isUser
|
||||
? 'bg-brand-accent text-white'
|
||||
? 'bg-active-blue text-white'
|
||||
: 'bg-white text-gray-800 border border-gray-200';
|
||||
const alignmentClasses = isUser ? 'items-end' : 'items-start';
|
||||
const avatar = isUser
|
||||
? <div className="w-8 h-8 rounded-full bg-brand-dark-blue flex items-center justify-center ring-2 ring-white"><UserIcon className="h-5 w-5 text-white"/></div>
|
||||
: <div className="w-8 h-8 rounded-full bg-brand-light-blue flex items-center justify-center ring-2 ring-white"><LeadAgentIcon className="h-5 w-5 text-brand-dark-blue"/></div>;
|
||||
? <div className="w-8 h-8 rounded-full bg-primary-blue flex items-center justify-center ring-2 ring-white"><UserIcon className="h-5 w-5 text-white"/></div>
|
||||
: <div className="w-8 h-8 rounded-full bg-cyan-brand flex items-center justify-center ring-2 ring-white"><LeadAgentIcon className="h-5 w-5 text-primary-blue"/></div>;
|
||||
|
||||
const isConfirmation = React.isValidElement(children) && children.type === ConfirmationComponent;
|
||||
|
||||
|
|
@ -247,9 +247,9 @@ export const WIPReviewer: React.FC<WIPReviewerProps> = ({ dropdownOptions, msalI
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full bg-brand-gray">
|
||||
<div className="flex flex-col h-full bg-grey-100">
|
||||
<header className="p-4 border-b border-gray-200 bg-white/80 backdrop-blur-sm flex-shrink-0">
|
||||
<h1 className="text-xl font-bold text-brand-dark-blue text-center">WIP Reviewer</h1>
|
||||
<h1 className="text-xl font-bold text-primary-blue text-center">WIP Reviewer</h1>
|
||||
</header>
|
||||
|
||||
{/* Message Display Area */}
|
||||
|
|
@ -303,7 +303,7 @@ export const WIPReviewer: React.FC<WIPReviewerProps> = ({ dropdownOptions, msalI
|
|||
type="button"
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
disabled={isLoading}
|
||||
className="p-2 text-gray-500 hover:text-brand-accent rounded-full transition-colors disabled:opacity-50"
|
||||
className="p-2 text-gray-500 hover:text-active-blue rounded-full transition-colors disabled:opacity-50"
|
||||
aria-label="Attach file"
|
||||
>
|
||||
<PaperClipIcon className="h-6 w-6"/>
|
||||
|
|
@ -317,14 +317,14 @@ export const WIPReviewer: React.FC<WIPReviewerProps> = ({ dropdownOptions, msalI
|
|||
handleSendMessage(e);
|
||||
}
|
||||
}}
|
||||
className="w-full p-2.5 mx-2 border border-gray-300 rounded-lg resize-none focus:ring-2 focus:ring-brand-accent focus:border-brand-accent transition"
|
||||
className="w-full p-2.5 mx-2 border border-gray-300 rounded-lg resize-none focus:ring-2 focus:ring-active-blue focus:border-active-blue transition"
|
||||
placeholder="Type your message..."
|
||||
rows={1}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="p-2.5 rounded-full text-white bg-brand-accent hover:bg-brand-dark-blue disabled:bg-gray-400 transition-colors"
|
||||
className="p-2.5 rounded-full text-white bg-active-blue hover:bg-primary-blue disabled:bg-gray-400 transition-colors"
|
||||
disabled={!userInput.trim() || isLoading}
|
||||
aria-label="Send message"
|
||||
>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue