181 lines
8.6 KiB
TypeScript
181 lines
8.6 KiB
TypeScript
|
|
import React, { useState, useEffect } from 'react';
|
|
import { XIcon } from './icons/XIcon';
|
|
|
|
interface CreateCampaignModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
onAddCampaign: (campaignData: {
|
|
name: string;
|
|
workfrontId: string;
|
|
clientLead: string;
|
|
brandGuidelines: string;
|
|
}) => void;
|
|
}
|
|
|
|
export const CreateCampaignModal: React.FC<CreateCampaignModalProps> = ({ isOpen, onClose, onAddCampaign }) => {
|
|
const [name, setName] = useState('');
|
|
const [brandGuidelines, setBrandGuidelines] = 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('');
|
|
setBrandGuidelines('');
|
|
setWorkfrontId('');
|
|
setClientLead('');
|
|
setError(null);
|
|
}
|
|
}, [isOpen]);
|
|
|
|
const validateWorkfrontId = (id: string): boolean => {
|
|
const isValid = /^#WF_\d+$/.test(id);
|
|
if (!isValid && id.length > 0) {
|
|
setError("Workfront Campaign 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() || !brandGuidelines.trim()) {
|
|
return;
|
|
}
|
|
|
|
if (!isIdValidOnSubmit) {
|
|
setError("Workfront Campaign ID must be in the format '#WF_12345'");
|
|
return;
|
|
}
|
|
|
|
setError(null);
|
|
onAddCampaign({ name, workfrontId, clientLead, brandGuidelines });
|
|
onClose();
|
|
};
|
|
|
|
if (!isOpen) return null;
|
|
|
|
const isFormInvalid = !name.trim() || !workfrontId.trim() || !clientLead.trim() || !brandGuidelines.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-lg 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">
|
|
<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>
|
|
<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"
|
|
required
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label htmlFor="brand-guidelines" className="block text-sm font-medium text-gray-700">Brand Guidelines</label>
|
|
<select
|
|
id="brand-guidelines"
|
|
value={brandGuidelines}
|
|
onChange={(e) => setBrandGuidelines(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"
|
|
required
|
|
>
|
|
<option value="" disabled>Select brand guidelines</option>
|
|
<option value="Barclays">Barclays</option>
|
|
<option value="Barclaycard">Barclaycard</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label htmlFor="workfront-id" className="block text-sm font-medium text-gray-700">Workfront Campaign ID</label>
|
|
<input
|
|
type="text"
|
|
id="workfront-id"
|
|
value={workfrontId}
|
|
onChange={handleWorkfrontIdChange}
|
|
className={`mt-1 block w-full p-2 border rounded-md shadow-sm focus:ring-brand-accent focus:border-brand-accent transition bg-white text-gray-900 placeholder:text-gray-400 ${error ? 'border-red-500 focus:border-red-500 focus:ring-red-500' : 'border-gray-300'}`}
|
|
placeholder="#WF_12345"
|
|
required
|
|
aria-invalid={!!error}
|
|
aria-describedby="workfront-id-error"
|
|
/>
|
|
{error && <p id="workfront-id-error" className="mt-1 text-sm text-red-600">{error}</p>}
|
|
</div>
|
|
<div>
|
|
<label htmlFor="client-lead" className="block text-sm font-medium text-gray-700">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"
|
|
required
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700">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"
|
|
disabled
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700">Agency Lead</label>
|
|
<input
|
|
type="text"
|
|
value="Steve O'Donoghue"
|
|
className="mt-1 block w-full p-2 border border-gray-300 rounded-md shadow-sm bg-gray-100 text-gray-600 cursor-not-allowed"
|
|
disabled
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="mt-8 flex justify-end gap-3">
|
|
<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"
|
|
>
|
|
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"
|
|
disabled={isFormInvalid || !!error}
|
|
>
|
|
Create Campaign
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|