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

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 14:00:13 -06:00

163 lines
7.5 KiB
TypeScript
Executable file

import React, { useState, useEffect } from 'react';
import { XIcon } from './icons/XIcon';
interface CreateProjectModalProps {
isOpen: boolean;
onClose: () => void;
onAddProject: (projectData: {
name: string;
workfrontId: string;
clientLead: string;
}) => void;
}
export const CreateProjectModal: React.FC<CreateProjectModalProps> = ({ isOpen, onClose, onAddProject }) => {
const [name, setName] = useState('');
const [workfrontId, setWorkfrontId] = useState('');
const [clientLead, setClientLead] = useState('');
const [error, setError] = useState<string | null>(null);
useEffect(() => {
// Reset form when modal opens
if (isOpen) {
setName('');
setWorkfrontId('');
setClientLead('');
setError(null);
}
}, [isOpen]);
const validateWorkfrontId = (id: string): boolean => {
const isValid = /^#WF_\d+$/.test(id);
if (!isValid && id.length > 0) {
setError("Workfront Project ID must be in the format '#WF_12345'");
} else {
setError(null);
}
return isValid || id.length === 0;
};
const handleWorkfrontIdChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newId = e.target.value;
setWorkfrontId(newId);
validateWorkfrontId(newId);
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
const isIdValidOnSubmit = /^#WF_\d+$/.test(workfrontId);
if (!name.trim() || !clientLead.trim() || !workfrontId.trim()) {
return;
}
if (!isIdValidOnSubmit) {
setError("Workfront Project ID must be in the format '#WF_12345'");
return;
}
setError(null);
onAddProject({ name, workfrontId, clientLead });
onClose();
};
if (!isOpen) return null;
const isFormInvalid = !name.trim() || !workfrontId.trim() || !clientLead.trim();
return (
<div
className="fixed inset-0 bg-black bg-opacity-60 flex items-center justify-center z-50 transition-opacity duration-300"
onClick={onClose}
aria-modal="true"
role="dialog"
>
<div
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-primary-blue">Create New Project</h2>
<button onClick={onClose} className="p-1 rounded-full text-grey-700 hover:bg-grey-100 hover:text-black-title transition-colors">
<XIcon className="h-6 w-6" />
</button>
</div>
<form onSubmit={handleSubmit} noValidate>
<div className="space-y-4">
<div>
<label htmlFor="project-name" className="block text-sm font-medium text-black-title">Project Name</label>
<input
type="text"
id="project-name"
value={name}
onChange={(e) => setName(e.target.value)}
className="mt-1 block w-full p-2 border-2 border-grey-700 rounded-[10px] shadow-sm focus:ring-active-blue focus:border-active-blue transition bg-white text-black-title"
required
/>
</div>
<div>
<label htmlFor="workfront-id" className="block text-sm font-medium text-black-title">Workfront Project ID</label>
<input
type="text"
id="workfront-id"
value={workfrontId}
onChange={handleWorkfrontIdChange}
className={`mt-1 block w-full p-2 border-2 rounded-[10px] shadow-sm focus:ring-active-blue focus:border-active-blue transition bg-white text-black-title placeholder:text-grey-700 ${error ? 'border-error focus:border-error focus:ring-error' : 'border-grey-700'}`}
placeholder="#WF_12345"
required
aria-invalid={!!error}
aria-describedby="workfront-id-error"
/>
{error && <p id="workfront-id-error" className="mt-1 text-sm text-error">{error}</p>}
</div>
<div>
<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-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-black-title">Agency</label>
<input
type="text"
value="OLIVER Agency"
className="mt-1 block w-full p-2 border-2 border-grey-300 rounded-[10px] shadow-sm bg-grey-100 text-grey-900 cursor-not-allowed"
disabled
/>
</div>
<div>
<label className="block text-sm font-medium text-black-title">Agency Lead</label>
<input
type="text"
value="Steve O'Donoghue"
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>
<div className="mt-8 flex justify-end gap-3">
<button
type="button"
onClick={onClose}
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-active-blue text-white font-semibold py-2 px-6 rounded-full hover:bg-active-blue/90 transition-colors duration-300 disabled:bg-grey-700 disabled:cursor-not-allowed"
disabled={isFormInvalid || !!error}
>
Create Project
</button>
</div>
</form>
</div>
</div>
);
};