modcomms/frontend/components/CreateCampaignModal.tsx
Vadym Samoilenko 41ea5dc57b Update Workfront Campaign ID field: simplify placeholder and remove format validation
- Change placeholder from '#WF_12345' to 'WF1234567'
- Remove format validation and error messaging (field is optional, free-form)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 15:54:27 +01:00

160 lines
8.3 KiB
TypeScript
Executable file

import React, { useState, useEffect } from 'react';
import { XIcon } from './icons/XIcon';
import apiService from '../services/apiService';
import { useUser } from '../contexts/UserContext';
interface CreateCampaignModalProps {
isOpen: boolean;
onClose: () => void;
onAddCampaign: (campaignData: {
name: string;
workfrontId: string;
clientLead: string;
agencyLead: string;
brandGuidelines: string;
}) => void;
brandGuidelines?: string[];
}
export const CreateCampaignModal: React.FC<CreateCampaignModalProps> = ({ isOpen, onClose, onAddCampaign, brandGuidelines: brandGuidelineOptions = [] }) => {
const { user } = useUser();
const [name, setName] = useState('');
const [selectedBrandGuideline, setSelectedBrandGuideline] = useState('');
const [workfrontId, setWorkfrontId] = useState('');
const [clientLead, setClientLead] = useState('');
const [agencyLead, setAgencyLead] = useState('');
useEffect(() => {
if (isOpen) {
setName('');
setSelectedBrandGuideline('');
setWorkfrontId('');
setClientLead('');
setAgencyLead('');
}
}, [isOpen]);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!name.trim() || !clientLead.trim() || !agencyLead.trim() || !selectedBrandGuideline.trim()) {
return;
}
onAddCampaign({ name, workfrontId: workfrontId.trim(), clientLead, agencyLead, brandGuidelines: selectedBrandGuideline });
onClose();
};
if (!isOpen) return null;
const isFormInvalid = !name.trim() || !clientLead.trim() || !agencyLead.trim() || !selectedBrandGuideline.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 border-2 border-oliver-azure"
onClick={(e) => e.stopPropagation()}
>
<div className="flex justify-between items-center mb-6">
<h2 className="text-2xl font-bold text-oliver-black">Create New Campaign</h2>
<button onClick={onClose} className="p-1 rounded-full text-oliver-black/60 hover:bg-oliver-grey hover:text-oliver-black 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-oliver-black">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-2 border-oliver-azure rounded-[10px] shadow-sm focus:ring-oliver-azure focus:border-oliver-azure transition bg-white text-oliver-black"
required
/>
</div>
<div>
<label htmlFor="brand-guidelines" className="block text-sm font-medium text-oliver-black">Brand Guidelines</label>
<select
id="brand-guidelines"
value={selectedBrandGuideline}
onChange={(e) => setSelectedBrandGuideline(e.target.value)}
className="mt-1 block w-full p-2 border-2 border-oliver-azure rounded-[10px] shadow-sm focus:ring-oliver-azure focus:border-oliver-azure transition bg-white text-oliver-black"
required
>
<option value="" disabled>Select brand guidelines</option>
{brandGuidelineOptions.map((brand) => (
<option key={brand} value={brand}>{brand}</option>
))}
</select>
</div>
<div>
<label htmlFor="workfront-id" className="block text-sm font-medium text-oliver-black">Workfront Campaign ID <span className="text-oliver-black/60 font-normal">(Optional)</span></label>
<input
type="text"
id="workfront-id"
value={workfrontId}
onChange={(e) => setWorkfrontId(e.target.value)}
className="mt-1 block w-full p-2 border-2 border-oliver-azure rounded-[10px] shadow-sm focus:ring-oliver-azure focus:border-oliver-azure transition bg-white text-oliver-black placeholder:text-oliver-black/60"
placeholder="WF1234567"
/>
</div>
<div>
<label htmlFor="client-lead" className="block text-sm font-medium text-oliver-black">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-oliver-azure rounded-[10px] shadow-sm focus:ring-oliver-azure focus:border-oliver-azure transition bg-white text-oliver-black"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-oliver-black">Agency</label>
<input
type="text"
value={user?.agencyName ?? ''}
className="mt-1 block w-full p-2 border-2 border-grey-300 rounded-[10px] shadow-sm bg-oliver-grey text-oliver-black cursor-not-allowed"
disabled
/>
</div>
<div>
<label htmlFor="agency-lead" className="block text-sm font-medium text-oliver-black">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-2 border-oliver-azure rounded-[10px] shadow-sm focus:ring-oliver-azure focus:border-oliver-azure transition bg-white text-oliver-black"
required
/>
</div>
</div>
<div className="mt-8 flex justify-end gap-3">
<button
type="button"
onClick={onClose}
className="border-2 border-oliver-azure text-oliver-azure font-semibold py-2 px-6 rounded-full hover:bg-oliver-azure hover:text-white transition-colors duration-300"
>
Cancel
</button>
<button
type="submit"
className="bg-oliver-azure text-white font-semibold py-2 px-6 rounded-full hover:bg-oliver-azure/90 transition-colors duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed"
disabled={isFormInvalid}
>
Create Campaign
</button>
</div>
</form>
</div>
</div>
);
};