Implement Barclays design system UI update
- Update Tailwind config with new color tokens (primary-blue, active-blue, electric-violet, lime, grey-100/300/700/900, success, warning, error) - Add Inter font from Google Fonts as Barclays Effra alternative - Update Sidebar with primary-blue background and white active state - Update Hero with electric-violet accent and pill-shaped buttons - Update all tables with lime (#C3FB5A) header backgrounds - Implement alternating row colors (white/grey-100) on tables - Update status badges: In Progress (amber), Completed (green) - Update tabs with active-blue underline styling - Apply 10px border radius to cards and containers - Update button styling to pill-shaped with active-blue - Update input/dropdown borders to grey-700 with 2px - Update selected state highlighting to info-light (#E7F0FB) - Update FeedbackReport RAG status colors to new design system Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e5a841716e
commit
532d7541d6
11 changed files with 369 additions and 338 deletions
|
|
@ -854,9 +854,9 @@ const App: React.FC = () => {
|
|||
// Show loading spinner during MSAL authentication interactions
|
||||
if (inProgress !== InteractionStatus.None) {
|
||||
return (
|
||||
<div className="fixed inset-0 bg-[#0f172a] flex items-center justify-center">
|
||||
<div className="fixed inset-0 bg-primary-blue flex items-center justify-center">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<svg className="animate-spin h-12 w-12 text-brand-accent" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<svg className="animate-spin h-12 w-12 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>
|
||||
|
|
@ -871,7 +871,7 @@ const App: React.FC = () => {
|
|||
}
|
||||
|
||||
// Determine background color based on view to avoid grey bar on Home view
|
||||
const mainBgColor = currentView === 'Home' ? 'bg-white' : 'bg-brand-gray';
|
||||
const mainBgColor = currentView === 'Home' ? 'bg-white' : 'bg-grey-100';
|
||||
|
||||
// Get user info from MSAL for sidebar display
|
||||
const userInfo = getUserInfo(msalInstance);
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ const StableLine = () => <svg xmlns="http://www.w3.org/2000/svg" fill="none" vie
|
|||
|
||||
const TrendIndicator: React.FC<{ trend: 'up' | 'down' | 'stable' }> = ({ trend }) => {
|
||||
if (trend === 'up') {
|
||||
return <div className="flex items-center gap-1.5 text-green-600"><UpArrow/> Improving</div>;
|
||||
return <div className="flex items-center gap-1.5 text-success"><UpArrow/> Improving</div>;
|
||||
}
|
||||
if (trend === 'down') {
|
||||
return <div className="flex items-center gap-1.5 text-red-600"><DownArrow/> Declining</div>;
|
||||
return <div className="flex items-center gap-1.5 text-error"><DownArrow/> Declining</div>;
|
||||
}
|
||||
return <div className="flex items-center gap-1.5 text-gray-500"><StableLine/> Stable</div>;
|
||||
return <div className="flex items-center gap-1.5 text-grey-700"><StableLine/> Stable</div>;
|
||||
};
|
||||
|
||||
export const Analytics: React.FC = () => {
|
||||
|
|
@ -65,10 +65,10 @@ export const Analytics: 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">
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-brand-dark-blue">Performance Analytics</h1>
|
||||
<p className="text-base lg:text-lg text-gray-600 mt-1">Overall usage and performance statistics for the tool.</p>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-primary-blue">Performance Analytics</h1>
|
||||
<p className="text-base lg:text-lg text-primary-blue mt-1">Overall usage and performance statistics for the tool.</p>
|
||||
</header>
|
||||
|
||||
{/* Stats Cards */}
|
||||
|
|
@ -77,13 +77,13 @@ export const Analytics: React.FC = () => {
|
|||
{stats.map((stat) => {
|
||||
const Icon = stat.icon;
|
||||
return (
|
||||
<div key={stat.name} className="bg-white rounded-lg shadow-md p-6 flex items-start border border-gray-200 transition-all hover:shadow-xl hover:border-brand-accent">
|
||||
<div className="p-3 rounded-full bg-brand-light-blue/20 text-brand-accent mr-4 flex-shrink-0">
|
||||
<Icon className="h-7 w-7" />
|
||||
<div key={stat.name} className="bg-grey-100 rounded-[10px] p-6 flex items-start border-2 border-grey-300 transition-all hover:shadow-lg hover:border-active-blue">
|
||||
<div className="p-3 rounded-full bg-white text-black-title mr-4 flex-shrink-0">
|
||||
<Icon className="h-9 w-9" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-500">{stat.name}</p>
|
||||
<p className="text-3xl font-bold text-brand-dark-blue mt-1">{stat.value}</p>
|
||||
<p className="text-sm font-medium text-grey-900">{stat.name}</p>
|
||||
<p className="text-3xl font-bold text-black-title mt-1">{stat.value}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -93,45 +93,45 @@ export const Analytics: React.FC = () => {
|
|||
|
||||
{/* AI Performance Summary */}
|
||||
<section className="mt-10">
|
||||
<h2 className="text-2xl font-bold text-brand-dark-blue mb-4">AI Performance Summary</h2>
|
||||
<div className="bg-blue-50 border-l-4 border-brand-accent text-brand-dark-blue p-6 rounded-r-lg shadow-md flex items-start gap-4">
|
||||
<h2 className="text-2xl font-bold text-primary-blue mb-4">AI Performance Summary</h2>
|
||||
<div className="bg-white border-2 border-electric-violet text-black-title p-6 rounded-[10px] shadow-md flex items-start gap-4">
|
||||
<div className="flex-shrink-0">
|
||||
<LightbulbIcon className="h-7 w-7 text-brand-accent" />
|
||||
<LightbulbIcon className="h-7 w-7 text-electric-violet" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-semibold">Key Insight (Last 7 Days):</p>
|
||||
<p className="mt-1">
|
||||
<p className="font-semibold text-primary-blue">Key Insight (Last 7 Days):</p>
|
||||
<p className="mt-1 text-black-title">
|
||||
A sharp decline in Best Practice adherence has been noted, primarily driven by proofs from the <strong>Barclays Q4 Social</strong> campaign. The Brand Guardian agent also shows a declining performance trend, suggesting a potential need for updated brand guideline training or proof review.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
{/* Agent Performance Table */}
|
||||
<section className="mt-10">
|
||||
<h2 className="text-2xl font-bold text-brand-dark-blue mb-4">Agent Performance (Last 7 Days)</h2>
|
||||
<div className="bg-white rounded-lg shadow-md overflow-hidden border border-gray-200">
|
||||
<h2 className="text-2xl font-bold text-primary-blue mb-4">Agent Performance (Last 7 Days)</h2>
|
||||
<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">
|
||||
<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">Agent Name</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Pass Rate</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Avg. Issues per Proof</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Performance Trend</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Agent Name</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Pass Rate</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Avg. Issues per Proof</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Performance Trend</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{agentPerformance.map((agent) => (
|
||||
<tr key={agent.name} className="hover:bg-gray-50">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">{agent.name}</td>
|
||||
<td className={`px-6 py-4 whitespace-nowrap text-sm font-semibold`}>
|
||||
<tbody className="divide-y divide-grey-300">
|
||||
{agentPerformance.map((agent, index) => (
|
||||
<tr key={agent.name} className={index % 2 === 0 ? 'bg-white' : 'bg-grey-100'}>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-black-title">{agent.name}</td>
|
||||
<td className={`px-6 py-4 whitespace-nowrap text-sm font-semibold text-black-title`}>
|
||||
<div className="flex items-center">
|
||||
<span className={`h-2.5 w-2.5 rounded-full mr-3 ${agent.passRate >= 80 ? 'bg-green-500' : agent.passRate < 70 ? 'bg-red-500' : 'bg-yellow-500'}`}></span>
|
||||
<span className={`h-2.5 w-2.5 rounded-full mr-3 ${agent.passRate >= 80 ? 'bg-success' : agent.passRate < 70 ? 'bg-error' : 'bg-warning'}`}></span>
|
||||
{agent.passRate}%
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{agent.avgIssues}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{agent.avgIssues}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
|
||||
<TrendIndicator trend={agent.trend as 'up' | 'down' | 'stable'} />
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -22,41 +22,41 @@ const formatDate = (isoString: string) => {
|
|||
|
||||
const FlagsTable: React.FC<{ items: FlaggedItem[], onNavigate: AuditingProps['onNavigate'] }> = ({ items, onNavigate }) => (
|
||||
<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">
|
||||
<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">Proof Version</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Submitter</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Submit Agency</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Agent Flagged</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">User Comments</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Date</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">Proof Version</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Submitter</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Submit Agency</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Agent Flagged</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">User Comments</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{items.length > 0 ? items.map((item) => (
|
||||
<tbody className="divide-y divide-grey-300">
|
||||
{items.length > 0 ? items.map((item, index) => (
|
||||
<tr
|
||||
key={item.id}
|
||||
className="hover:bg-gray-100 cursor-pointer"
|
||||
className={`hover:bg-info-light cursor-pointer ${index % 2 === 0 ? 'bg-white' : 'bg-grey-100'}`}
|
||||
onClick={() => onNavigate(item)}
|
||||
title={`Click to view Version ${item.version} of ${item.proofName}`}
|
||||
>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">{item.proofName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">Version {item.version}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{item.submitter}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{item.submitAgency}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{item.agentFlagged}</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-700">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-black-title">{item.proofName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">Version {item.version}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{item.submitter}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{item.submitAgency}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{item.agentFlagged}</td>
|
||||
<td className="px-6 py-4 text-sm text-black-title">
|
||||
<div className="max-w-xs break-words" title={item.comments}>
|
||||
{item.comments || <span className="italic text-gray-400">No comment</span>}
|
||||
{item.comments || <span className="italic text-grey-700">No comment</span>}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{formatDate(item.timestamp)}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{formatDate(item.timestamp)}</td>
|
||||
</tr>
|
||||
)) : (
|
||||
<tr>
|
||||
<td colSpan={7} className="text-center py-10 text-gray-500">
|
||||
<td colSpan={7} className="text-center py-10 text-grey-700">
|
||||
There are currently no flagged items to audit.
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -68,43 +68,43 @@ const FlagsTable: React.FC<{ items: FlaggedItem[], onNavigate: AuditingProps['on
|
|||
|
||||
const ResolutionsTable: React.FC<{ items: ResolvedItem[], onNavigate: AuditingProps['onNavigate'] }> = ({ items, onNavigate }) => (
|
||||
<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">
|
||||
<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">Proof Version</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Submitter</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Submit Agency</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Agent</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Agent Issue</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">User Comments</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Date</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">Proof Version</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Submitter</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Submit Agency</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Agent</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Agent Issue</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">User Comments</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{items.length > 0 ? items.map((item) => (
|
||||
<tbody className="divide-y divide-grey-300">
|
||||
{items.length > 0 ? items.map((item, index) => (
|
||||
<tr
|
||||
key={item.id}
|
||||
className="hover:bg-gray-100 cursor-pointer"
|
||||
className={`hover:bg-info-light cursor-pointer ${index % 2 === 0 ? 'bg-white' : 'bg-grey-100'}`}
|
||||
onClick={() => onNavigate(item)}
|
||||
title={`Click to view Version ${item.version} of ${item.proofName}`}
|
||||
>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">{item.proofName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">Version {item.version}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{item.submitter}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{item.submitAgency}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{item.agent}</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-700">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-black-title">{item.proofName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">Version {item.version}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{item.submitter}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{item.submitAgency}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{item.agent}</td>
|
||||
<td className="px-6 py-4 text-sm text-black-title">
|
||||
<div className="max-w-xs break-words" title={item.issue}>{item.issue}</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-700">
|
||||
<td className="px-6 py-4 text-sm text-black-title">
|
||||
<div className="max-w-xs break-words" title={item.resolution}>{item.resolution}</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{formatDate(item.timestamp)}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{formatDate(item.timestamp)}</td>
|
||||
</tr>
|
||||
)) : (
|
||||
<tr>
|
||||
<td colSpan={8} className="text-center py-10 text-gray-500">
|
||||
<td colSpan={8} className="text-center py-10 text-grey-700">
|
||||
There are currently no resolved items to audit.
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -116,39 +116,39 @@ const ResolutionsTable: React.FC<{ items: ResolvedItem[], onNavigate: AuditingPr
|
|||
|
||||
const ErrorsTable: React.FC<{ items: ErrorItem[], onNavigate: AuditingProps['onNavigate'] }> = ({ items, onNavigate }) => (
|
||||
<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">
|
||||
<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">Proof Version</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Submitter</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Submit Agency</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Error Summary</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Date</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">Proof Version</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Submitter</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Submit Agency</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Error Summary</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{items.length > 0 ? items.map((item) => (
|
||||
<tbody className="divide-y divide-grey-300">
|
||||
{items.length > 0 ? items.map((item, index) => (
|
||||
<tr
|
||||
key={item.id}
|
||||
className="hover:bg-gray-100 cursor-pointer"
|
||||
className={`hover:bg-info-light cursor-pointer ${index % 2 === 0 ? 'bg-white' : 'bg-grey-100'}`}
|
||||
onClick={() => onNavigate(item)}
|
||||
title={`Click to view Version ${item.version} of ${item.proofName}`}
|
||||
>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">{item.proofName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">Version {item.version}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{item.submitter}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{item.submitAgency}</td>
|
||||
<td className="px-6 py-4 text-sm text-gray-700">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-black-title">{item.proofName}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">Version {item.version}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{item.submitter}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{item.submitAgency}</td>
|
||||
<td className="px-6 py-4 text-sm text-black-title">
|
||||
<div className="max-w-md break-words" title={item.errorSummary}>
|
||||
{item.errorSummary}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{formatDate(item.timestamp)}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{formatDate(item.timestamp)}</td>
|
||||
</tr>
|
||||
)) : (
|
||||
<tr>
|
||||
<td colSpan={6} className="text-center py-10 text-gray-500">
|
||||
<td colSpan={6} className="text-center py-10 text-grey-700">
|
||||
There are currently no analysis errors to audit.
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -163,20 +163,20 @@ export const Auditing: React.FC<AuditingProps> = ({ flaggedItems, resolvedItems,
|
|||
const [activeTab, setActiveTab] = useState<'Flags' | 'Resolutions' | 'Errors'>('Flags');
|
||||
|
||||
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">Auditing</h1>
|
||||
<p className="text-base lg:text-lg text-gray-600 mt-1">Review and investigate all user-flagged feedback.</p>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-primary-blue">Auditing</h1>
|
||||
<p className="text-base lg:text-lg text-primary-blue mt-1">Review and investigate all user-flagged feedback.</p>
|
||||
</header>
|
||||
|
||||
<div className="mb-6 border-b border-gray-200">
|
||||
<div className="mb-6 border-b border-grey-300">
|
||||
<nav className="-mb-px flex space-x-6" aria-label="Tabs">
|
||||
<button
|
||||
onClick={() => setActiveTab('Flags')}
|
||||
className={`whitespace-nowrap py-3 px-1 border-b-2 font-semibold text-sm transition-colors ${
|
||||
activeTab === 'Flags'
|
||||
? 'border-brand-accent text-brand-accent'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
||||
? 'border-active-blue text-active-blue'
|
||||
: 'border-transparent text-black-title hover:text-active-blue hover:border-grey-300'
|
||||
}`}
|
||||
aria-current={activeTab === 'Flags' ? 'page' : undefined}
|
||||
>
|
||||
|
|
@ -186,8 +186,8 @@ export const Auditing: React.FC<AuditingProps> = ({ flaggedItems, resolvedItems,
|
|||
onClick={() => setActiveTab('Resolutions')}
|
||||
className={`whitespace-nowrap py-3 px-1 border-b-2 font-semibold text-sm transition-colors ${
|
||||
activeTab === 'Resolutions'
|
||||
? 'border-brand-accent text-brand-accent'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
||||
? 'border-active-blue text-active-blue'
|
||||
: 'border-transparent text-black-title hover:text-active-blue hover:border-grey-300'
|
||||
}`}
|
||||
aria-current={activeTab === 'Resolutions' ? 'page' : undefined}
|
||||
>
|
||||
|
|
@ -197,8 +197,8 @@ export const Auditing: React.FC<AuditingProps> = ({ flaggedItems, resolvedItems,
|
|||
onClick={() => setActiveTab('Errors')}
|
||||
className={`whitespace-nowrap py-3 px-1 border-b-2 font-semibold text-sm transition-colors ${
|
||||
activeTab === 'Errors'
|
||||
? 'border-brand-accent text-brand-accent'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
||||
? 'border-active-blue text-active-blue'
|
||||
: 'border-transparent text-black-title hover:text-active-blue hover:border-grey-300'
|
||||
}`}
|
||||
aria-current={activeTab === 'Errors' ? 'page' : undefined}
|
||||
>
|
||||
|
|
@ -208,7 +208,7 @@ export const Auditing: React.FC<AuditingProps> = ({ flaggedItems, resolvedItems,
|
|||
</div>
|
||||
|
||||
<section>
|
||||
<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">
|
||||
{activeTab === 'Flags' && <FlagsTable items={flaggedItems} onNavigate={onNavigate} />}
|
||||
{activeTab === 'Resolutions' && <ResolutionsTable items={resolvedItems} onNavigate={onNavigate} />}
|
||||
{activeTab === 'Errors' && <ErrorsTable items={errorItems} onNavigate={onNavigate} />}
|
||||
|
|
|
|||
|
|
@ -226,16 +226,16 @@ const StatusBadge: React.FC<{ status: string }> = ({ status }) => {
|
|||
let colorClasses = '';
|
||||
switch (status) {
|
||||
case 'In Progress':
|
||||
colorClasses = 'bg-blue-100 text-blue-800';
|
||||
colorClasses = 'bg-warning text-black-title';
|
||||
break;
|
||||
case 'Completed':
|
||||
colorClasses = 'bg-green-100 text-green-800';
|
||||
colorClasses = 'bg-success text-white';
|
||||
break;
|
||||
case 'Needs Review':
|
||||
colorClasses = 'bg-yellow-100 text-yellow-800';
|
||||
colorClasses = 'bg-warning-light text-black-title';
|
||||
break;
|
||||
default:
|
||||
colorClasses = 'bg-gray-100 text-gray-800';
|
||||
colorClasses = 'bg-grey-100 text-black-title';
|
||||
}
|
||||
return (
|
||||
<span className={`px-2.5 py-0.5 text-xs font-semibold rounded-full ${colorClasses}`}>
|
||||
|
|
@ -248,19 +248,19 @@ const OverallStatusBadge: React.FC<{ status: OverallStatus }> = ({ status }) =>
|
|||
let colorClasses = '';
|
||||
switch (status) {
|
||||
case 'Passed':
|
||||
colorClasses = 'bg-green-100 text-green-800';
|
||||
colorClasses = 'bg-success text-white';
|
||||
break;
|
||||
case 'Failed':
|
||||
colorClasses = 'bg-red-100 text-red-800';
|
||||
colorClasses = 'bg-error text-white';
|
||||
break;
|
||||
case 'Requires Manual Legal Review':
|
||||
colorClasses = 'bg-purple-100 text-purple-800';
|
||||
colorClasses = 'bg-warning text-black-title';
|
||||
break;
|
||||
case 'Analysis Error':
|
||||
colorClasses = 'bg-gray-200 text-gray-800';
|
||||
colorClasses = 'bg-grey-300 text-black-title';
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<span className={`inline-flex items-center px-3 py-1 text-sm font-bold rounded-full ${colorClasses}`}>
|
||||
{status}
|
||||
|
|
@ -299,17 +299,17 @@ const CampaignList: React.FC<{
|
|||
}, [filteredCampaigns]);
|
||||
|
||||
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':
|
||||
colorClasses = 'bg-blue-100 text-blue-800';
|
||||
colorClasses = 'bg-warning text-black-title';
|
||||
break;
|
||||
case 'Completed':
|
||||
colorClasses = 'bg-green-100 text-green-800';
|
||||
colorClasses = 'bg-success text-white';
|
||||
break;
|
||||
default:
|
||||
colorClasses = 'bg-gray-100 text-gray-800';
|
||||
colorClasses = 'bg-grey-100 text-black-title';
|
||||
}
|
||||
return `${baseClasses} ${colorClasses}`;
|
||||
};
|
||||
|
|
@ -364,7 +364,7 @@ const CampaignList: React.FC<{
|
|||
const isIndeterminate = selectedCampaigns.size > 0 && selectedCampaigns.size < filteredCampaigns.length;
|
||||
|
||||
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">
|
||||
<CampaignDeleteConfirmationModal
|
||||
isOpen={!!campaignToDelete}
|
||||
onClose={() => setCampaignToDelete(null)}
|
||||
|
|
@ -388,17 +388,17 @@ const CampaignList: React.FC<{
|
|||
<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">Campaigns</h1>
|
||||
<p className="text-base lg:text-lg text-gray-600 mt-1">Manage your campaigns and proof collections.</p>
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-primary-blue">Campaigns</h1>
|
||||
<p className="text-base lg:text-lg text-primary-blue mt-1">Manage your campaigns and proof collections.</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<label htmlFor="show-completed" className="text-sm font-medium text-gray-700 whitespace-nowrap">Show Completed</label>
|
||||
<label htmlFor="show-completed" className="text-sm font-medium text-black-title whitespace-nowrap">Show Completed</label>
|
||||
<ToggleSwitch enabled={showCompleted} onChange={setShowCompleted} />
|
||||
</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.5 px-6 rounded-full hover:bg-active-blue/90 transition-colors duration-300"
|
||||
>
|
||||
<PlusIcon className="h-5 w-5" />
|
||||
Create New Campaign
|
||||
|
|
@ -410,14 +410,14 @@ const CampaignList: React.FC<{
|
|||
<section>
|
||||
{/* Bulk Actions Bar */}
|
||||
{selectedCampaigns.size > 0 && (
|
||||
<div className="mb-4 bg-blue-50 border border-blue-200 rounded-lg p-3 flex items-center justify-between">
|
||||
<div className="mb-4 bg-info-light border border-active-blue rounded-[10px] p-3 flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<span className="text-sm font-medium text-blue-800">
|
||||
<span className="text-sm font-medium text-active-blue">
|
||||
{selectedCampaigns.size} campaign{selectedCampaigns.size !== 1 ? 's' : ''} selected
|
||||
</span>
|
||||
<button
|
||||
onClick={() => setSelectedCampaigns(new Set())}
|
||||
className="text-sm text-blue-600 hover:text-blue-800 underline"
|
||||
className="text-sm text-active-blue hover:text-primary-blue underline"
|
||||
>
|
||||
Clear selection
|
||||
</button>
|
||||
|
|
@ -425,7 +425,7 @@ const CampaignList: React.FC<{
|
|||
<button
|
||||
onClick={() => setShowBulkDeleteModal(true)}
|
||||
disabled={isDeleting}
|
||||
className="flex items-center gap-2 bg-red-600 text-white font-semibold py-1.5 px-3 rounded-lg hover:bg-red-700 transition-colors duration-300 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
className="flex items-center gap-2 bg-error text-white font-semibold py-1.5 px-4 rounded-full hover:bg-error/90 transition-colors duration-300 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
Delete Selected
|
||||
|
|
@ -433,10 +433,10 @@ const CampaignList: React.FC<{
|
|||
</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">
|
||||
<thead className="bg-lime">
|
||||
<tr>
|
||||
<th scope="col" className="px-4 py-3 text-left">
|
||||
<input
|
||||
|
|
@ -446,26 +446,26 @@ const CampaignList: React.FC<{
|
|||
if (el) el.indeterminate = isIndeterminate;
|
||||
}}
|
||||
onChange={handleSelectAll}
|
||||
className="h-4 w-4 text-brand-accent border-gray-300 rounded focus:ring-brand-accent cursor-pointer"
|
||||
className="h-4 w-4 text-active-blue border-grey-300 rounded focus:ring-active-blue cursor-pointer"
|
||||
aria-label="Select all campaigns"
|
||||
/>
|
||||
</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Campaign Name</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Proofs</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Status</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Created By</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Owning Agency</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Last Modified</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Campaign Name</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Proofs</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Status</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Created By</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Owning Agency</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Last Modified</th>
|
||||
<th scope="col" className="relative px-4 py-3"><span className="sr-only">Actions</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{filteredCampaigns.map((campaign) => {
|
||||
<tbody className="divide-y divide-grey-300">
|
||||
{filteredCampaigns.map((campaign, index) => {
|
||||
const isSelected = selectedCampaigns.has(campaign.name);
|
||||
return (
|
||||
<tr
|
||||
key={campaign.name}
|
||||
className={`hover:bg-gray-100 cursor-pointer ${isSelected ? 'bg-blue-50' : ''}`}
|
||||
className={`hover:bg-info-light cursor-pointer ${isSelected ? 'bg-info-light' : index % 2 === 0 ? 'bg-white' : 'bg-grey-100'}`}
|
||||
onClick={() => onSelectCampaign(campaign.name)}
|
||||
>
|
||||
<td className="px-4 py-4 whitespace-nowrap">
|
||||
|
|
@ -474,12 +474,12 @@ const CampaignList: React.FC<{
|
|||
checked={isSelected}
|
||||
onChange={() => {}} // Handled by onClick
|
||||
onClick={(e) => handleSelectCampaign(campaign.name, e)}
|
||||
className="h-4 w-4 text-brand-accent border-gray-300 rounded focus:ring-brand-accent cursor-pointer"
|
||||
className="h-4 w-4 text-active-blue border-grey-300 rounded focus:ring-active-blue cursor-pointer"
|
||||
aria-label={`Select ${campaign.name}`}
|
||||
/>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-brand-dark-blue">{campaign.name}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{campaign.proofs}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-black-title">{campaign.name}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{campaign.proofs}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm w-40">
|
||||
<div className="relative">
|
||||
<select
|
||||
|
|
@ -492,17 +492,17 @@ const CampaignList: React.FC<{
|
|||
<option value="In Progress">In Progress</option>
|
||||
<option value="Completed">Completed</option>
|
||||
</select>
|
||||
<ChevronDownIcon className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2 h-full w-4 text-gray-500" />
|
||||
<ChevronDownIcon className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2 h-full w-4 text-black-title" />
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{campaign.agencyLead}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{campaign.agency}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{formatDate(campaign.lastModified)}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{campaign.agencyLead}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{campaign.agency}</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">{formatDate(campaign.lastModified)}</td>
|
||||
<td className="px-4 py-4 whitespace-nowrap text-sm text-right">
|
||||
<button
|
||||
onClick={(e) => handleSingleDelete(campaign, e)}
|
||||
disabled={isDeleting}
|
||||
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 ${campaign.name}`}
|
||||
aria-label={`Delete ${campaign.name}`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -41,43 +41,43 @@ const specialistAgents: CheckDetail[] = [
|
|||
|
||||
export const ChecksOverview: React.FC = () => {
|
||||
return (
|
||||
<div className="relative bg-gradient-to-br from-emerald-50 via-white to-emerald-50/30 py-12 sm:py-16 w-full">
|
||||
<div className="relative bg-gradient-to-br from-lime/20 via-white to-lime/10 py-12 sm:py-16 w-full">
|
||||
{/* Decorative Background */}
|
||||
<div className="absolute inset-0 pointer-events-none">
|
||||
<div className="absolute top-0 left-1/4 w-[800px] h-[800px] bg-emerald-200/30 rounded-full blur-3xl -translate-y-1/2 mix-blend-multiply"></div>
|
||||
<div className="absolute bottom-0 right-0 w-[600px] h-[600px] bg-green-200/30 rounded-full blur-3xl translate-y-1/3 mix-blend-multiply"></div>
|
||||
<div className="absolute top-0 left-1/4 w-[800px] h-[800px] bg-lime/30 rounded-full blur-3xl -translate-y-1/2 mix-blend-multiply"></div>
|
||||
<div className="absolute bottom-0 right-0 w-[600px] h-[600px] bg-success-light rounded-full blur-3xl translate-y-1/3 mix-blend-multiply"></div>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
|
||||
{/* Header */}
|
||||
<div className="max-w-3xl mx-auto text-center mb-12">
|
||||
<div className="inline-flex items-center px-4 py-1.5 rounded-full bg-white border border-emerald-200 text-emerald-700 text-xs font-bold uppercase tracking-widest mb-4 shadow-sm">
|
||||
<span className="w-2 h-2 rounded-full bg-emerald-500 mr-2 animate-pulse"></span>
|
||||
<div className="inline-flex items-center px-4 py-1.5 rounded-full bg-white border border-lime text-primary-blue text-xs font-bold uppercase tracking-widest mb-4 shadow-sm">
|
||||
<span className="w-2 h-2 rounded-full bg-success mr-2 animate-pulse"></span>
|
||||
Intelligent Workflow
|
||||
</div>
|
||||
<h2 className="text-3xl md:text-4xl font-extrabold text-brand-dark-blue tracking-tight mb-4">
|
||||
<h2 className="text-3xl md:text-4xl font-extrabold text-primary-blue tracking-tight mb-4">
|
||||
Orchestrated by AI
|
||||
</h2>
|
||||
<p className="text-lg text-slate-600 leading-relaxed">
|
||||
<p className="text-lg text-black-title leading-relaxed">
|
||||
A central Lead Agent coordinates specialized experts to review every aspect of your content in parallel.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col lg:flex-row items-center justify-center lg:items-stretch gap-0 lg:gap-0">
|
||||
|
||||
|
||||
{/* 1. LEAD AGENT CARD (Left) */}
|
||||
<div className="w-full max-w-md lg:w-[380px] relative z-20 group/lead flex flex-col">
|
||||
<div className="flex-1 relative bg-[#001f5a] rounded-3xl p-6 shadow-2xl shadow-blue-900/20 border border-white/10 text-center transition-all duration-500 hover:-translate-y-2 hover:shadow-blue-900/40 overflow-hidden flex flex-col items-center justify-center">
|
||||
<div className="flex-1 relative bg-primary-blue rounded-[20px] p-6 shadow-2xl shadow-primary-blue/20 border border-white/10 text-center transition-all duration-500 hover:-translate-y-2 hover:shadow-primary-blue/40 overflow-hidden flex flex-col items-center justify-center">
|
||||
{/* Animated Gradient bg */}
|
||||
<div className="absolute top-[-50%] left-[-50%] w-[200%] h-[200%] bg-gradient-to-b from-transparent via-white/5 to-transparent rotate-45 transition-transform duration-[3s] group-hover/lead:translate-y-10"></div>
|
||||
|
||||
|
||||
<div className="relative z-10">
|
||||
<div className="h-20 w-20 mx-auto rounded-2xl bg-white/10 border border-white/20 backdrop-blur-md flex items-center justify-center mb-4 shadow-lg shadow-brand-dark-blue/30 group-hover/lead:scale-110 transition-all duration-500">
|
||||
<div className="h-20 w-20 mx-auto rounded-2xl bg-white/10 border border-white/20 backdrop-blur-md flex items-center justify-center mb-4 shadow-lg shadow-primary-blue/30 group-hover/lead:scale-110 transition-all duration-500">
|
||||
<LeadAgentIcon className="h-10 w-10 text-white" />
|
||||
</div>
|
||||
|
||||
|
||||
<h3 className="text-2xl font-bold text-white mb-2">Lead Agent</h3>
|
||||
<p className="text-brand-light-blue font-bold text-xs uppercase tracking-widest mb-4">Orchestrator</p>
|
||||
<p className="text-cyan-brand font-bold text-xs uppercase tracking-widest mb-4">Orchestrator</p>
|
||||
<p className="text-slate-300 text-sm leading-relaxed">
|
||||
Synthesizes feedback & coordinates analysis across all specialist agents.
|
||||
</p>
|
||||
|
|
@ -85,12 +85,12 @@ export const ChecksOverview: React.FC = () => {
|
|||
</div>
|
||||
|
||||
{/* Connection Node (Desktop) */}
|
||||
<div className="hidden lg:flex absolute top-1/2 -right-4 w-8 h-8 bg-[#001f5a] rounded-full border-4 border-emerald-50 items-center justify-center z-30 -translate-y-1/2 shadow-sm translate-x-1/2">
|
||||
<div className="w-2.5 h-2.5 bg-emerald-400 rounded-full animate-pulse"></div>
|
||||
<div className="hidden lg:flex absolute top-1/2 -right-4 w-8 h-8 bg-primary-blue rounded-full border-4 border-lime/50 items-center justify-center z-30 -translate-y-1/2 shadow-sm translate-x-1/2">
|
||||
<div className="w-2.5 h-2.5 bg-success rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
{/* Connection Node (Mobile) */}
|
||||
<div className="lg:hidden absolute -bottom-4 left-1/2 w-8 h-8 bg-[#001f5a] rounded-full border-4 border-emerald-50 items-center justify-center z-30 -translate-x-1/2 shadow-sm">
|
||||
<div className="w-2.5 h-2.5 bg-emerald-400 rounded-full animate-pulse"></div>
|
||||
<div className="lg:hidden absolute -bottom-4 left-1/2 w-8 h-8 bg-primary-blue rounded-full border-4 border-lime/50 items-center justify-center z-30 -translate-x-1/2 shadow-sm">
|
||||
<div className="w-2.5 h-2.5 bg-success rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -98,54 +98,54 @@ export const ChecksOverview: React.FC = () => {
|
|||
<div className="hidden lg:block w-24 relative z-10 self-center h-48">
|
||||
<svg className="absolute inset-0 w-full h-full overflow-visible" viewBox="0 0 100 200" preserveAspectRatio="none">
|
||||
{/* Connecting paths */}
|
||||
<path d="M0,100 C50,100 50,30 100,30" fill="none" stroke="#6ee7b7" strokeWidth="2" strokeDasharray="6 6" />
|
||||
<path d="M0,100 C50,100 50,170 100,170" fill="none" stroke="#6ee7b7" strokeWidth="2" strokeDasharray="6 6" />
|
||||
|
||||
<path d="M0,100 C50,100 50,30 100,30" fill="none" stroke="#C3FB5A" strokeWidth="2" strokeDasharray="6 6" />
|
||||
<path d="M0,100 C50,100 50,170 100,170" fill="none" stroke="#C3FB5A" strokeWidth="2" strokeDasharray="6 6" />
|
||||
|
||||
{/* Animated pulses on paths */}
|
||||
<circle r="3" fill="#10b981">
|
||||
<circle r="3" fill="#09821F">
|
||||
<animateMotion dur="2s" repeatCount="indefinite" path="M0,100 C50,100 50,30 100,30" />
|
||||
</circle>
|
||||
<circle r="3" fill="#10b981">
|
||||
<circle r="3" fill="#09821F">
|
||||
<animateMotion dur="2s" repeatCount="indefinite" begin="1s" path="M0,100 C50,100 50,170 100,170" />
|
||||
</circle>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Mobile Connector Spacer */}
|
||||
<div className="lg:hidden h-8 w-0.5 bg-emerald-300 my-3"></div>
|
||||
<div className="lg:hidden h-8 w-0.5 bg-lime my-3"></div>
|
||||
|
||||
{/* 3. SPECIALIST AGENTS (Right) */}
|
||||
<div className="flex-1 grid grid-cols-1 md:grid-cols-2 gap-4 w-full max-w-4xl pl-0 lg:pl-4">
|
||||
{specialistAgents.map((agent, index) => (
|
||||
<div
|
||||
key={agent.name}
|
||||
className="group relative rounded-2xl p-5 border border-emerald-100 shadow-sm transition-all duration-500 hover:shadow-xl hover:shadow-emerald-900/5 hover:-translate-y-2 hover:border-emerald-200 overflow-hidden bg-white"
|
||||
<div
|
||||
key={agent.name}
|
||||
className="group relative rounded-[10px] p-5 border border-grey-300 shadow-sm transition-all duration-500 hover:shadow-xl hover:shadow-success/10 hover:-translate-y-2 hover:border-success overflow-hidden bg-white"
|
||||
>
|
||||
{/* Base Gradient */}
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white via-white to-emerald-50/30 opacity-100 transition-opacity duration-500 group-hover:opacity-0"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white via-white to-lime/10 opacity-100 transition-opacity duration-500 group-hover:opacity-0"></div>
|
||||
|
||||
{/* Hover Gradient - Interactive Green */}
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white via-emerald-50 to-emerald-100/20 opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
|
||||
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white via-success-light to-lime/20 opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
|
||||
|
||||
{/* Animated Shine/Sweep Effect */}
|
||||
<div className="absolute top-[-50%] left-[-50%] w-[200%] h-[200%] bg-gradient-to-b from-transparent via-emerald-500/5 to-transparent rotate-45 translate-y-12 transition-transform duration-1000 group-hover:translate-y-[-10%] pointer-events-none"></div>
|
||||
<div className="absolute top-[-50%] left-[-50%] w-[200%] h-[200%] bg-gradient-to-b from-transparent via-success/5 to-transparent rotate-45 translate-y-12 transition-transform duration-1000 group-hover:translate-y-[-10%] pointer-events-none"></div>
|
||||
|
||||
{/* Glassy Highlight */}
|
||||
<div className="absolute -top-24 -right-24 w-48 h-48 bg-gradient-to-br from-emerald-400/10 to-transparent rounded-full blur-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none"></div>
|
||||
|
||||
<div className="absolute -top-24 -right-24 w-48 h-48 bg-gradient-to-br from-lime/30 to-transparent rounded-full blur-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none"></div>
|
||||
|
||||
<div className="relative z-10 flex items-start gap-4">
|
||||
<div className={`flex-shrink-0 w-12 h-12 rounded-2xl flex items-center justify-center transition-all duration-300 group-hover:scale-110 group-hover:shadow-md bg-emerald-50 text-emerald-600 group-hover:bg-emerald-600 group-hover:text-white`}>
|
||||
<div className={`flex-shrink-0 w-12 h-12 rounded-[10px] flex items-center justify-center transition-all duration-300 group-hover:scale-110 group-hover:shadow-md bg-success-light text-success group-hover:bg-success group-hover:text-white`}>
|
||||
{React.cloneElement(agent.icon as React.ReactElement, { className: "h-6 w-6 transition-colors duration-300" })}
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex-1">
|
||||
<h4 className="text-base font-bold text-slate-800 group-hover:text-emerald-900 transition-colors duration-300 mb-0.5">
|
||||
<h4 className="text-base font-bold text-black-title group-hover:text-primary-blue transition-colors duration-300 mb-0.5">
|
||||
{agent.name}
|
||||
</h4>
|
||||
<p className="text-[10px] font-extrabold text-slate-400 uppercase tracking-wider mb-1 group-hover:text-emerald-600 transition-colors duration-300">
|
||||
<p className="text-[10px] font-extrabold text-grey-700 uppercase tracking-wider mb-1 group-hover:text-success transition-colors duration-300">
|
||||
{agent.role}
|
||||
</p>
|
||||
<p className="text-xs text-slate-600 leading-relaxed group-hover:text-slate-700">
|
||||
<p className="text-xs text-black-title leading-relaxed group-hover:text-black-title">
|
||||
{agent.description}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -87,35 +87,35 @@ export const CreateCampaignModal: React.FC<CreateCampaignModalProps> = ({ 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 Campaign</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 Campaign</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="campaign-name" className="block text-sm font-medium text-gray-700">Campaign Name</label>
|
||||
<label htmlFor="campaign-name" className="block text-sm font-medium text-black-title">Campaign Name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="campaign-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="brand-guidelines" className="block text-sm font-medium text-gray-700">Brand Guidelines</label>
|
||||
<label htmlFor="brand-guidelines" className="block text-sm font-medium text-black-title">Brand Guidelines</label>
|
||||
<select
|
||||
id="brand-guidelines"
|
||||
value={selectedBrandGuideline}
|
||||
onChange={(e) => setSelectedBrandGuideline(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
|
||||
>
|
||||
<option value="" disabled>Select brand guidelines</option>
|
||||
|
|
@ -125,47 +125,47 @@ export const CreateCampaignModal: React.FC<CreateCampaignModalProps> = ({ isOpen
|
|||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="workfront-id" className="block text-sm font-medium text-gray-700">Workfront Campaign ID <span className="text-gray-400 font-normal">(Optional)</span></label>
|
||||
<label htmlFor="workfront-id" className="block text-sm font-medium text-black-title">Workfront Campaign ID <span className="text-grey-700 font-normal">(Optional)</span></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"
|
||||
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 htmlFor="agency-lead" className="block text-sm font-medium text-gray-700">Agency Lead</label>
|
||||
<label htmlFor="agency-lead" className="block text-sm font-medium text-black-title">Agency Lead</label>
|
||||
<input
|
||||
type="text"
|
||||
id="agency-lead"
|
||||
value={agencyLead}
|
||||
onChange={(e) => setAgencyLead(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>
|
||||
|
|
@ -174,13 +174,13 @@ export const CreateCampaignModal: React.FC<CreateCampaignModalProps> = ({ 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 Campaign
|
||||
|
|
|
|||
|
|
@ -77,27 +77,27 @@ const formatFeedbackText = (text: string): React.ReactNode => {
|
|||
const RagStatusBadge: React.FC<{ status: RagStatus; isLarge?: boolean }> = ({ status, isLarge = false }) => {
|
||||
let colorClasses = '';
|
||||
let iconColor = '';
|
||||
|
||||
|
||||
switch (status) {
|
||||
case 'Red':
|
||||
colorClasses = 'bg-red-50 border-red-200 text-red-800 shadow-red-100';
|
||||
iconColor = 'text-red-600';
|
||||
colorClasses = 'bg-error-light border-error text-error';
|
||||
iconColor = 'text-error';
|
||||
break;
|
||||
case 'Amber':
|
||||
colorClasses = 'bg-amber-50 border-amber-200 text-amber-800 shadow-amber-100';
|
||||
iconColor = 'text-amber-600';
|
||||
colorClasses = 'bg-warning-light border-warning text-black-title';
|
||||
iconColor = 'text-warning';
|
||||
break;
|
||||
case 'Green':
|
||||
colorClasses = 'bg-emerald-50 border-emerald-200 text-emerald-800 shadow-emerald-100';
|
||||
iconColor = 'text-emerald-600';
|
||||
colorClasses = 'bg-success-light border-success text-success';
|
||||
iconColor = 'text-success';
|
||||
break;
|
||||
case 'Error':
|
||||
colorClasses = 'bg-slate-50 border-slate-200 text-slate-700 shadow-slate-100';
|
||||
iconColor = 'text-slate-500';
|
||||
colorClasses = 'bg-grey-100 border-grey-300 text-grey-900';
|
||||
iconColor = 'text-grey-700';
|
||||
break;
|
||||
}
|
||||
|
||||
const sizeClasses = isLarge ? 'px-4 py-1.5 text-sm rounded-xl border shadow-sm' : 'px-2.5 py-1 text-xs rounded-lg border shadow-sm';
|
||||
const sizeClasses = isLarge ? 'px-4 py-1.5 text-sm rounded-[10px] border shadow-sm' : 'px-2.5 py-1 text-xs rounded-[10px] border shadow-sm';
|
||||
|
||||
return (
|
||||
<div className={`inline-flex items-center font-bold tracking-wide ${sizeClasses} ${colorClasses} backdrop-blur-sm`}>
|
||||
|
|
@ -128,43 +128,43 @@ const ResolveIssueModal: React.FC<{
|
|||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
<div
|
||||
className="fixed inset-0 bg-slate-900/60 backdrop-blur-sm flex items-center justify-center z-50 transition-all duration-300"
|
||||
onClick={onClose}
|
||||
>
|
||||
<div
|
||||
className="bg-white rounded-2xl shadow-2xl p-8 w-full max-w-lg transform transition-all border border-white/20 ring-1 ring-black/5"
|
||||
<div
|
||||
className="bg-white rounded-[10px] shadow-2xl p-8 w-full max-w-lg transform transition-all border border-grey-300"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<h3 className="text-2xl font-bold text-brand-dark-blue mb-2">Resolve Issue</h3>
|
||||
<p className="text-slate-600 mb-6">Please provide a reason for manually resolving this issue.</p>
|
||||
|
||||
<div className="my-6 p-4 bg-slate-50 border border-slate-200 rounded-xl text-slate-700 italic text-sm">
|
||||
<h3 className="text-2xl font-bold text-primary-blue mb-2">Resolve Issue</h3>
|
||||
<p className="text-black-title mb-6">Please provide a reason for manually resolving this issue.</p>
|
||||
|
||||
<div className="my-6 p-4 bg-grey-100 border border-grey-300 rounded-[10px] text-black-title italic text-sm">
|
||||
"{issueText}"
|
||||
</div>
|
||||
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
<label htmlFor="resolution-reason" className="block text-sm font-bold text-slate-700 mb-2">Reason for resolution</label>
|
||||
<label htmlFor="resolution-reason" className="block text-sm font-bold text-black-title mb-2">Reason for resolution</label>
|
||||
<textarea
|
||||
id="resolution-reason"
|
||||
value={reason}
|
||||
onChange={(e) => setReason(e.target.value)}
|
||||
className="w-full p-4 border border-slate-200 rounded-xl focus:ring-2 focus:ring-brand-accent/50 focus:border-brand-accent transition-all bg-slate-50 focus:bg-white resize-none"
|
||||
className="w-full p-4 border-2 border-grey-700 rounded-[10px] focus:ring-2 focus:ring-active-blue/50 focus:border-active-blue transition-all bg-grey-100 focus:bg-white resize-none text-black-title"
|
||||
rows={4}
|
||||
placeholder="e.g. 'Legal team has approved this exception via email...'"
|
||||
required
|
||||
/>
|
||||
<div className="mt-8 flex justify-end gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="px-5 py-2.5 rounded-xl text-slate-600 font-semibold hover:bg-slate-100 transition-colors"
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="px-6 py-2.5 rounded-full border-2 border-active-blue text-active-blue font-semibold hover:bg-active-blue hover:text-white transition-colors"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="px-5 py-2.5 rounded-xl bg-brand-accent text-white font-bold shadow-lg shadow-brand-accent/30 hover:bg-brand-light-blue transition-all disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
<button
|
||||
type="submit"
|
||||
className="px-6 py-2.5 rounded-full bg-active-blue text-white font-bold shadow-lg shadow-active-blue/30 hover:bg-active-blue/90 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
disabled={!reason.trim()}
|
||||
>
|
||||
Submit Resolution
|
||||
|
|
|
|||
|
|
@ -14,42 +14,42 @@ const ArrowRightIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
|
|||
|
||||
export const Hero: React.FC<HeroProps> = ({ onGetStarted }) => {
|
||||
return (
|
||||
<div className="relative overflow-hidden bg-slate-900 min-h-[350px] sm:min-h-[400px] md:min-h-[500px] flex items-center">
|
||||
<div className="relative overflow-hidden bg-primary-blue min-h-[350px] sm:min-h-[400px] md:min-h-[500px] flex items-center">
|
||||
{/* Abstract background elements */}
|
||||
<div className="absolute top-[-20%] right-[-10%] w-[600px] h-[600px] rounded-full bg-brand-accent/20 blur-3xl pointer-events-none"></div>
|
||||
<div className="absolute bottom-[-20%] left-[-10%] w-[500px] h-[500px] rounded-full bg-brand-dark-blue/40 blur-3xl pointer-events-none"></div>
|
||||
|
||||
<div className="absolute top-[-20%] right-[-10%] w-[600px] h-[600px] rounded-full bg-active-blue/20 blur-3xl pointer-events-none"></div>
|
||||
<div className="absolute bottom-[-20%] left-[-10%] w-[500px] h-[500px] rounded-full bg-electric-violet/20 blur-3xl pointer-events-none"></div>
|
||||
|
||||
{/* Grid Pattern Overlay */}
|
||||
<div className="absolute inset-0 bg-[url('https://grainy-gradients.vercel.app/noise.svg')] opacity-20 pointer-events-none"></div>
|
||||
|
||||
|
||||
<div className="max-w-screen-2xl mx-auto px-4 sm:px-6 lg:px-8 py-16 md:py-24 relative z-10 w-full">
|
||||
<div className="max-w-3xl">
|
||||
<div className="inline-flex items-center px-3 py-1 rounded-full bg-brand-accent/10 border border-brand-accent/20 text-brand-light-blue text-xs font-bold uppercase tracking-widest mb-6">
|
||||
<span className="w-2 h-2 rounded-full bg-brand-light-blue mr-2 animate-pulse"></span>
|
||||
<div className="inline-flex items-center px-3 py-1 rounded-full bg-active-blue/10 border border-active-blue/20 text-cyan-brand text-xs font-bold uppercase tracking-widest mb-6">
|
||||
<span className="w-2 h-2 rounded-full bg-cyan-brand mr-2 animate-pulse"></span>
|
||||
AI-Powered Compliance
|
||||
</div>
|
||||
|
||||
|
||||
<h1 className="text-5xl md:text-7xl font-extrabold text-white leading-tight mb-6">
|
||||
Mod Comms <br/>
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-brand-light-blue to-white">
|
||||
<span className="text-electric-violet">
|
||||
Intelligent Review
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
|
||||
<p className="text-lg md:text-xl text-slate-300 mb-10 leading-relaxed max-w-2xl">
|
||||
Streamline your creative approval process. Mod Comms analyses your assets against guidelines and best practice in seconds, not days.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4">
|
||||
<button
|
||||
<button
|
||||
onClick={onGetStarted}
|
||||
className="group inline-flex items-center justify-center px-8 py-4 text-base font-bold text-white bg-brand-accent rounded-xl shadow-lg shadow-brand-accent/30 hover:bg-white hover:text-brand-dark-blue transition-all duration-300"
|
||||
className="group inline-flex items-center justify-center px-8 py-4 text-base font-bold text-white bg-active-blue rounded-full shadow-lg shadow-active-blue/30 hover:bg-active-blue/90 transition-all duration-300"
|
||||
>
|
||||
Start Analysis
|
||||
<ArrowRightIcon className="ml-2 h-5 w-5 transform group-hover:translate-x-1 transition-transform" />
|
||||
</button>
|
||||
<button
|
||||
className="inline-flex items-center justify-center px-8 py-4 text-base font-bold text-white bg-white/5 border border-white/10 rounded-xl hover:bg-white/10 transition-all duration-300 backdrop-blur-sm"
|
||||
<button
|
||||
className="inline-flex items-center justify-center px-8 py-4 text-base font-bold text-white bg-white/5 border-2 border-white/20 rounded-full hover:bg-white/10 transition-all duration-300 backdrop-blur-sm"
|
||||
>
|
||||
View Documentation
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -30,21 +30,21 @@ const ManagementCard: React.FC<ManagementCardProps> = ({ title, items, onAdd, on
|
|||
};
|
||||
|
||||
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-4">{title}</h2>
|
||||
|
||||
<div className="bg-white rounded-[10px] shadow-md p-6 border border-grey-300 flex flex-col h-full">
|
||||
<h2 className="text-xl font-bold text-primary-blue mb-4">{title}</h2>
|
||||
|
||||
<form onSubmit={handleSubmit} className="flex gap-2 mb-4">
|
||||
<input
|
||||
type="text"
|
||||
value={newItem}
|
||||
onChange={(e) => setNewItem(e.target.value)}
|
||||
placeholder={placeholder || `New ${title.slice(0, -1)}...`}
|
||||
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-2 border-grey-700 rounded-[10px] focus:ring-2 focus:ring-active-blue focus:border-active-blue transition disabled:bg-grey-100 disabled:cursor-not-allowed text-black-title"
|
||||
disabled={disabled}
|
||||
/>
|
||||
<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={!newItem.trim() || disabled}
|
||||
>
|
||||
Add
|
||||
|
|
@ -57,12 +57,12 @@ const ManagementCard: React.FC<ManagementCardProps> = ({ title, items, onAdd, on
|
|||
{items.map((item) => (
|
||||
<li
|
||||
key={item}
|
||||
className="flex items-center justify-between bg-gray-50 p-2.5 rounded-md border border-gray-200 group hover:border-brand-accent/30 transition-colors"
|
||||
className="flex items-center justify-between bg-grey-100 p-2.5 rounded-[10px] border border-grey-300 group hover:border-active-blue/30 transition-colors"
|
||||
>
|
||||
<span className="text-gray-800">{item}</span>
|
||||
<span className="text-black-title">{item}</span>
|
||||
<button
|
||||
onClick={() => onRemove(item)}
|
||||
className={`text-gray-400 hover:text-red-600 transition-opacity ${disabled ? 'opacity-0 cursor-not-allowed' : 'opacity-0 group-hover:opacity-100'}`}
|
||||
className={`text-grey-700 hover:text-error transition-opacity ${disabled ? 'opacity-0 cursor-not-allowed' : 'opacity-0 group-hover:opacity-100'}`}
|
||||
title={`Remove ${item}`}
|
||||
disabled={disabled}
|
||||
>
|
||||
|
|
@ -72,7 +72,7 @@ const ManagementCard: React.FC<ManagementCardProps> = ({ title, items, onAdd, on
|
|||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<div className="text-center py-8 text-gray-500 bg-gray-50 rounded-md">
|
||||
<div className="text-center py-8 text-grey-700 bg-grey-100 rounded-[10px]">
|
||||
No items found.
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -159,50 +159,50 @@ const UsersTab: React.FC = () => {
|
|||
return (
|
||||
<div className="space-y-8">
|
||||
{/* Add User Section */}
|
||||
<div className="bg-white rounded-lg shadow-md p-6 border border-gray-200">
|
||||
<h3 className="text-lg font-bold text-brand-dark-blue mb-4 flex items-center gap-2">
|
||||
<PlusIcon className="h-5 w-5 text-brand-accent" />
|
||||
<div className="bg-white rounded-[10px] shadow-md p-6 border border-grey-300">
|
||||
<h3 className="text-lg font-bold text-primary-blue mb-4 flex items-center gap-2">
|
||||
<PlusIcon className="h-5 w-5 text-active-blue" />
|
||||
Add New User
|
||||
</h3>
|
||||
<form onSubmit={handleAddUser} className="grid grid-cols-1 md:grid-cols-4 gap-4 items-end">
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Name</label>
|
||||
<label className="block text-xs font-medium text-black-title mb-1">Name</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newName}
|
||||
onChange={(e) => setNewName(e.target.value)}
|
||||
className="w-full p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-brand-accent focus:border-brand-accent"
|
||||
className="w-full p-2 border-2 border-grey-700 rounded-[10px] focus:ring-2 focus:ring-active-blue focus:border-active-blue text-black-title"
|
||||
placeholder="e.g. John Smith"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Email</label>
|
||||
<label className="block text-xs font-medium text-black-title mb-1">Email</label>
|
||||
<input
|
||||
type="email"
|
||||
value={newEmail}
|
||||
onChange={(e) => setNewEmail(e.target.value)}
|
||||
className="w-full p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-brand-accent focus:border-brand-accent"
|
||||
className="w-full p-2 border-2 border-grey-700 rounded-[10px] focus:ring-2 focus:ring-active-blue focus:border-active-blue text-black-title"
|
||||
placeholder="user@example.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">Agency</label>
|
||||
<label className="block text-xs font-medium text-black-title mb-1">Agency</label>
|
||||
<div className="relative">
|
||||
<select
|
||||
value={newAgency}
|
||||
onChange={(e) => setNewAgency(e.target.value)}
|
||||
className="w-full p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-brand-accent focus:border-brand-accent appearance-none"
|
||||
className="w-full p-2 border-2 border-grey-700 rounded-[10px] focus:ring-2 focus:ring-active-blue focus:border-active-blue appearance-none text-black-title"
|
||||
>
|
||||
{agencies.map(a => <option key={a} value={a}>{a}</option>)}
|
||||
</select>
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 pointer-events-none" />
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-grey-700 pointer-events-none" />
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-brand-accent text-white font-semibold py-2 px-4 rounded-md hover:bg-brand-dark-blue transition-colors"
|
||||
className="bg-active-blue text-white font-semibold py-2 px-6 rounded-full hover:bg-active-blue/90 transition-colors"
|
||||
>
|
||||
Add User
|
||||
</button>
|
||||
|
|
@ -210,49 +210,49 @@ const UsersTab: React.FC = () => {
|
|||
</div>
|
||||
|
||||
{/* User List */}
|
||||
<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">
|
||||
<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">Name</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Email</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-gray-500 uppercase tracking-wider">Assigned Agency</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Name</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Email</th>
|
||||
<th scope="col" className="px-6 py-3 text-left text-xs font-bold text-black-title uppercase tracking-wider">Assigned Agency</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">
|
||||
{users.map((user) => (
|
||||
<tr key={user.id} className="hover:bg-gray-50">
|
||||
<tbody className="divide-y divide-grey-300">
|
||||
{users.map((user, index) => (
|
||||
<tr key={user.id} className={index % 2 === 0 ? 'bg-white' : 'bg-grey-100'}>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="flex items-center">
|
||||
<div className="flex-shrink-0 h-8 w-8 rounded-full bg-brand-light-blue/20 flex items-center justify-center text-brand-accent">
|
||||
<div className="flex-shrink-0 h-8 w-8 rounded-full bg-info-light flex items-center justify-center text-active-blue">
|
||||
<UserIcon className="h-4 w-4" />
|
||||
</div>
|
||||
<div className="ml-4">
|
||||
<div className="text-sm font-medium text-gray-900">{user.name}</div>
|
||||
<div className="text-sm font-medium text-black-title">{user.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">
|
||||
{user.email}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-black-title">
|
||||
<div className="relative max-w-xs">
|
||||
<select
|
||||
value={user.agency}
|
||||
onChange={(e) => handleAgencyChange(user.id, e.target.value)}
|
||||
className="w-full bg-white border border-gray-300 text-gray-700 py-1.5 pl-3 pr-8 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-brand-accent appearance-none"
|
||||
className="w-full bg-white border-2 border-active-blue text-black-title py-1.5 pl-3 pr-8 rounded-[10px] text-sm focus:outline-none focus:ring-2 focus:ring-active-blue appearance-none"
|
||||
>
|
||||
{agencies.map(a => <option key={a} value={a}>{a}</option>)}
|
||||
</select>
|
||||
<ChevronDownIcon className="absolute right-2 top-1/2 -translate-y-1/2 h-3 w-3 text-gray-500 pointer-events-none" />
|
||||
<ChevronDownIcon className="absolute right-2 top-1/2 -translate-y-1/2 h-3 w-3 text-active-blue pointer-events-none" />
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<button
|
||||
<button
|
||||
onClick={() => handleDeleteUser(user.id)}
|
||||
className="text-gray-400 hover:text-red-600 transition-colors"
|
||||
className="text-grey-700 hover:text-error transition-colors"
|
||||
title="Remove User"
|
||||
>
|
||||
<TrashIcon className="h-5 w-5" />
|
||||
|
|
@ -321,17 +321,17 @@ export const Settings: React.FC<SettingsProps> = ({
|
|||
|
||||
|
||||
return (
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-brand-gray flex flex-col">
|
||||
<div className="p-4 sm:p-6 lg:p-8 h-full bg-grey-100 flex flex-col">
|
||||
<header className="mb-6 flex-shrink-0">
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-brand-dark-blue">Settings</h1>
|
||||
<p className="text-base lg:text-lg text-gray-600 mt-1">
|
||||
<h1 className="text-3xl lg:text-4xl font-bold text-primary-blue">Settings</h1>
|
||||
<p className="text-base lg:text-lg text-primary-blue mt-1">
|
||||
Configure application defaults and user access.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
|
||||
<div className="flex-1 flex flex-col min-h-0">
|
||||
{/* Tabs Header */}
|
||||
<div className="border-b border-gray-200 bg-white px-4 rounded-t-lg shadow-sm flex-shrink-0">
|
||||
<div className="border-b border-grey-300 bg-white px-4 rounded-t-[10px] shadow-sm flex-shrink-0">
|
||||
<nav className="-mb-px flex space-x-8 overflow-x-auto" aria-label="Tabs">
|
||||
{[
|
||||
{ id: 'Campaigns', label: 'Campaigns' },
|
||||
|
|
@ -347,8 +347,8 @@ export const Settings: React.FC<SettingsProps> = ({
|
|||
className={`
|
||||
whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm transition-colors
|
||||
${activeTab === tab.id
|
||||
? 'border-brand-accent text-brand-accent'
|
||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
||||
? 'border-active-blue text-active-blue'
|
||||
: 'border-transparent text-black-title hover:text-active-blue hover:border-grey-300'
|
||||
}
|
||||
`}
|
||||
aria-current={activeTab === tab.id ? 'page' : undefined}
|
||||
|
|
@ -387,18 +387,18 @@ export const Settings: React.FC<SettingsProps> = ({
|
|||
|
||||
{activeTab === 'SubChannels' && (
|
||||
<div className="max-w-3xl space-y-4">
|
||||
<div className="bg-white p-4 rounded-lg border border-gray-200 shadow-sm">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Select Parent Channel</label>
|
||||
<div className="bg-white p-4 rounded-[10px] border border-grey-300 shadow-sm">
|
||||
<label className="block text-sm font-medium text-black-title mb-2">Select Parent Channel</label>
|
||||
<div className="relative">
|
||||
<select
|
||||
value={selectedChannel}
|
||||
onChange={(e) => setSelectedChannel(e.target.value)}
|
||||
className="w-full p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-brand-accent appearance-none"
|
||||
className={`w-full p-2 border-2 rounded-[10px] focus:ring-2 focus:ring-active-blue appearance-none text-black-title ${selectedChannel ? 'bg-info-light border-active-blue' : 'border-active-blue'}`}
|
||||
>
|
||||
<option value="" disabled>Select Channel</option>
|
||||
{Object.keys(options.channels).map(c => <option key={c} value={c}>{c}</option>)}
|
||||
</select>
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 pointer-events-none"/>
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-active-blue pointer-events-none"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -416,8 +416,8 @@ export const Settings: React.FC<SettingsProps> = ({
|
|||
{activeTab === 'ProofTypes' && (
|
||||
<div className="max-w-3xl space-y-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="bg-white p-4 rounded-lg border border-gray-200 shadow-sm">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Select Channel</label>
|
||||
<div className="bg-white p-4 rounded-[10px] border border-grey-300 shadow-sm">
|
||||
<label className="block text-sm font-medium text-black-title mb-2">Select Channel</label>
|
||||
<div className="relative">
|
||||
<select
|
||||
value={selectedChannel}
|
||||
|
|
@ -425,22 +425,22 @@ export const Settings: React.FC<SettingsProps> = ({
|
|||
setSelectedChannel(e.target.value);
|
||||
setSelectedSubChannel('');
|
||||
}}
|
||||
className="w-full p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-brand-accent appearance-none"
|
||||
className={`w-full p-2 border-2 rounded-[10px] focus:ring-2 focus:ring-active-blue appearance-none text-black-title ${selectedChannel ? 'bg-info-light border-active-blue' : 'border-active-blue'}`}
|
||||
>
|
||||
<option value="" disabled>Select Channel</option>
|
||||
{Object.keys(options.channels).map(c => <option key={c} value={c}>{c}</option>)}
|
||||
</select>
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 pointer-events-none"/>
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-active-blue pointer-events-none"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-4 rounded-lg border border-gray-200 shadow-sm">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Select Sub-Channel</label>
|
||||
<div className="bg-white p-4 rounded-[10px] border border-grey-300 shadow-sm">
|
||||
<label className="block text-sm font-medium text-black-title mb-2">Select Sub-Channel</label>
|
||||
<div className="relative">
|
||||
<select
|
||||
value={selectedSubChannel}
|
||||
onChange={(e) => setSelectedSubChannel(e.target.value)}
|
||||
className="w-full p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-brand-accent appearance-none disabled:bg-gray-100"
|
||||
className={`w-full p-2 border-2 rounded-[10px] focus:ring-2 focus:ring-active-blue appearance-none text-black-title disabled:bg-grey-100 disabled:border-grey-300 ${selectedSubChannel ? 'bg-info-light border-active-blue' : 'border-active-blue'}`}
|
||||
disabled={!selectedChannel}
|
||||
>
|
||||
<option value="" disabled>Select Sub-Channel</option>
|
||||
|
|
@ -448,7 +448,7 @@ export const Settings: React.FC<SettingsProps> = ({
|
|||
<option key={sc} value={sc}>{sc}</option>
|
||||
))}
|
||||
</select>
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 pointer-events-none"/>
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-active-blue pointer-events-none"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -456,8 +456,8 @@ export const Settings: React.FC<SettingsProps> = ({
|
|||
<ManagementCard
|
||||
title={selectedSubChannel ? `Proof Types for ${selectedSubChannel}` : "Proof Types"}
|
||||
items={
|
||||
(selectedChannel && selectedSubChannel)
|
||||
? (options.channels[selectedChannel][selectedSubChannel] || [])
|
||||
(selectedChannel && selectedSubChannel)
|
||||
? (options.channels[selectedChannel][selectedSubChannel] || [])
|
||||
: []
|
||||
}
|
||||
onAdd={(val) => onAddProofType(selectedChannel, selectedSubChannel, val)}
|
||||
|
|
@ -474,39 +474,39 @@ export const Settings: React.FC<SettingsProps> = ({
|
|||
|
||||
{activeTab === 'Beta' && (
|
||||
<div className="max-w-3xl space-y-6">
|
||||
<div className="bg-white rounded-lg shadow-md p-6 border border-gray-200">
|
||||
<h2 className="text-xl font-bold text-brand-dark-blue mb-2 flex items-center gap-2">
|
||||
<div className="bg-white rounded-[10px] shadow-md p-6 border border-grey-300">
|
||||
<h2 className="text-xl font-bold text-primary-blue mb-2 flex items-center gap-2">
|
||||
<span className="relative flex h-3 w-3">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-brand-accent opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-3 w-3 bg-brand-accent"></span>
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-electric-violet opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-3 w-3 bg-electric-violet"></span>
|
||||
</span>
|
||||
Beta Features
|
||||
</h2>
|
||||
<p className="text-gray-600 mb-6">
|
||||
<p className="text-black-title mb-6">
|
||||
Explore experimental features currently in development. These tools are functional but may change over time.
|
||||
</p>
|
||||
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<button
|
||||
<button
|
||||
onClick={() => onNavigate('WIP Reviewer')}
|
||||
className="flex flex-col items-start p-4 rounded-lg border border-gray-200 hover:border-brand-accent hover:bg-blue-50/50 transition-all duration-300 group text-left"
|
||||
className="flex flex-col items-start p-4 rounded-[10px] border border-grey-300 hover:border-active-blue hover:bg-info-light transition-all duration-300 group text-left"
|
||||
>
|
||||
<div className="p-2 rounded-md bg-brand-light-blue/10 text-brand-accent mb-3 group-hover:scale-110 transition-transform">
|
||||
<div className="p-2 rounded-[10px] bg-info-light text-active-blue mb-3 group-hover:scale-110 transition-transform">
|
||||
<ClipboardIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<h3 className="font-bold text-brand-dark-blue mb-1">WIP Reviewer</h3>
|
||||
<p className="text-sm text-gray-500">Early-stage feedback on assets before they are finalized.</p>
|
||||
<h3 className="font-bold text-primary-blue mb-1">WIP Reviewer</h3>
|
||||
<p className="text-sm text-grey-900">Early-stage feedback on assets before they are finalized.</p>
|
||||
</button>
|
||||
|
||||
<button
|
||||
<button
|
||||
onClick={() => onNavigate('CopyGenAI')}
|
||||
className="flex flex-col items-start p-4 rounded-lg border border-gray-200 hover:border-brand-accent hover:bg-blue-50/50 transition-all duration-300 group text-left"
|
||||
className="flex flex-col items-start p-4 rounded-[10px] border border-grey-300 hover:border-electric-violet hover:bg-info-light transition-all duration-300 group text-left"
|
||||
>
|
||||
<div className="p-2 rounded-md bg-purple-100 text-purple-600 mb-3 group-hover:scale-110 transition-transform">
|
||||
<div className="p-2 rounded-[10px] bg-electric-violet/10 text-electric-violet mb-3 group-hover:scale-110 transition-transform">
|
||||
<CopyGenAIIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<h3 className="font-bold text-brand-dark-blue mb-1">CopyGenAI</h3>
|
||||
<p className="text-sm text-gray-500">Generate and refine marketing copy with AI assistance.</p>
|
||||
<h3 className="font-bold text-primary-blue mb-1">CopyGenAI</h3>
|
||||
<p className="text-sm text-grey-900">Generate and refine marketing copy with AI assistance.</p>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -27,15 +27,15 @@ interface SidebarProps {
|
|||
|
||||
export const Sidebar: React.FC<SidebarProps> = ({ activeItem, onNavigate, userName, userEmail }) => {
|
||||
return (
|
||||
<aside className="w-72 flex-shrink-0 bg-[#0f172a] text-slate-200 flex flex-col border-r border-slate-800 font-sans">
|
||||
<aside className="w-72 flex-shrink-0 bg-primary-blue text-slate-200 flex flex-col border-r border-white/10 font-sans">
|
||||
{/* Brand Header */}
|
||||
<div className="h-24 flex items-center px-8 border-b border-slate-800/60">
|
||||
<BarclaysLogo className="h-8 w-auto text-white" />
|
||||
<div className="h-24 flex items-center px-8 border-b border-white/10">
|
||||
<BarclaysLogo className="h-8 w-auto text-cyan-brand" />
|
||||
<div className="ml-3 flex flex-col">
|
||||
<span className="text-lg font-bold tracking-tight text-white leading-tight">
|
||||
Mod Comms
|
||||
</span>
|
||||
<span className="text-xs text-slate-400 uppercase tracking-widest font-semibold">
|
||||
<span className="text-xs text-electric-violet uppercase tracking-widest font-semibold">
|
||||
Compliance AI
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -53,11 +53,11 @@ export const Sidebar: React.FC<SidebarProps> = ({ activeItem, onNavigate, userNa
|
|||
key={item.name}
|
||||
onClick={() => !isComingSoon && onNavigate(item.name)}
|
||||
className={`group w-full flex items-center px-4 py-3.5 text-left text-sm font-medium rounded-xl transition-all duration-300 ease-in-out ${
|
||||
isActive
|
||||
? 'bg-gradient-to-r from-brand-accent to-brand-light-blue text-white shadow-lg shadow-brand-accent/20'
|
||||
isActive
|
||||
? 'bg-white text-primary-blue shadow-lg'
|
||||
: isComingSoon
|
||||
? 'text-slate-600 cursor-not-allowed'
|
||||
: 'text-slate-400 hover:bg-white/5 hover:text-white'
|
||||
: 'text-slate-300 hover:bg-white/10 hover:text-white'
|
||||
}`}
|
||||
aria-current={isActive ? 'page' : undefined}
|
||||
disabled={isComingSoon}
|
||||
|
|
@ -65,7 +65,7 @@ export const Sidebar: React.FC<SidebarProps> = ({ activeItem, onNavigate, userNa
|
|||
<Icon className={`h-5 w-5 mr-4 transition-transform duration-300 ${isActive ? 'scale-110' : 'group-hover:scale-110'}`} />
|
||||
<span className="flex-1 tracking-wide">{item.name}</span>
|
||||
{isActive && (
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-white/80 shadow-glow"></div>
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-active-blue"></div>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
|
|
@ -73,16 +73,16 @@ export const Sidebar: React.FC<SidebarProps> = ({ activeItem, onNavigate, userNa
|
|||
</nav>
|
||||
|
||||
{/* User Profile Snippet */}
|
||||
<div className="p-4 border-t border-slate-800/60 bg-[#0b1120]">
|
||||
<div className="p-4 border-t border-white/10 bg-primary-blue/80">
|
||||
<button
|
||||
onClick={() => onNavigate('Profile')}
|
||||
className={`group w-full flex items-center gap-3 p-3 rounded-xl text-left transition-all duration-200 ${
|
||||
activeItem === 'Profile'
|
||||
? 'bg-slate-800'
|
||||
: 'hover:bg-slate-800'
|
||||
? 'bg-white/10'
|
||||
: 'hover:bg-white/10'
|
||||
}`}
|
||||
>
|
||||
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-brand-dark-blue to-brand-accent flex items-center justify-center ring-2 ring-white/10 group-hover:ring-brand-light-blue/50 transition-all">
|
||||
<div className="w-10 h-10 rounded-full bg-active-blue flex items-center justify-center ring-2 ring-white/20 group-hover:ring-active-blue/50 transition-all">
|
||||
<UserIcon className="h-5 w-5 text-white" />
|
||||
</div>
|
||||
<div className="overflow-hidden">
|
||||
|
|
|
|||
|
|
@ -5,17 +5,48 @@
|
|||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Barclays Mod Comms</title>
|
||||
<!-- Google Fonts - Inter (Barclays Effra alternative) -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
'sans': ['Inter', 'Arial', 'sans-serif'],
|
||||
},
|
||||
colors: {
|
||||
'brand-dark-blue': '#001f5a',
|
||||
'brand-light-blue': '#00a3e0',
|
||||
'brand-accent': '#0070c0',
|
||||
'brand-gray': '#f4f6f8',
|
||||
'sidebar-bg': '#1f2937',
|
||||
// Legacy colors (kept for backwards compatibility during migration)
|
||||
'brand-dark-blue': '#1A2142',
|
||||
'brand-light-blue': '#00AEEF',
|
||||
'brand-accent': '#006DE3',
|
||||
'brand-gray': '#F6F6F6',
|
||||
'sidebar-bg': '#1A2142',
|
||||
|
||||
// Primary Brand Colors
|
||||
'primary-blue': '#1A2142',
|
||||
'active-blue': '#006DE3',
|
||||
'electric-violet': '#7A0FF9',
|
||||
'lime': '#C3FB5A',
|
||||
'cyan-brand': '#00AEEF',
|
||||
|
||||
// Functional Colors
|
||||
'grey-100': '#F6F6F6',
|
||||
'grey-300': '#E2E2E2',
|
||||
'grey-700': '#8E8E8E',
|
||||
'grey-900': '#515151',
|
||||
'black-title': '#272727',
|
||||
|
||||
// Status Colors
|
||||
'info-light': '#E7F0FB',
|
||||
'success': '#09821F',
|
||||
'success-light': '#E9F4EA',
|
||||
'warning': '#FFBA00',
|
||||
'warning-light': '#FFF8E7',
|
||||
'error': '#E3000F',
|
||||
'error-light': '#FDE7E9',
|
||||
},
|
||||
animation: {
|
||||
'slow-ping': 'ping 2s cubic-bezier(0, 0, 0.2, 1) infinite',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue