import React, { useState, useRef, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { Calendar, Mail, Lock, Clock, ArrowLeft, Info } from 'lucide-react'; import { format, addDays } from 'date-fns'; import { toast } from 'react-toastify'; import { Button, Input, Card } from '../../components/common'; import { useMutation } from '@tanstack/react-query'; import { eventsService } from '../../services/events.service'; interface FormData { event_type: string; event_name: string; event_date: string; host_email: string; admin_email: string; password: string; confirm_password: string; welcome_message: string; color_theme: string; expires_in_days: number; } const EVENT_TYPES = [ { value: 'wedding', label: 'Wedding', emoji: '💒' }, { value: 'birthday', label: 'Birthday', emoji: '🎂' }, { value: 'corporate', label: 'Corporate', emoji: '🏢' }, { value: 'other', label: 'Other', emoji: '📸' }, ]; const COLOR_THEMES = [ { value: 'default', label: 'Default (Green)', color: 'bg-primary-600', theme: { primaryColor: '#5C8762', accentColor: '#22c55e', backgroundColor: '#fafafa', textColor: '#171717', borderRadius: 'md' as const } }, { value: 'blue', label: 'Ocean Blue', color: 'bg-blue-600', theme: { primaryColor: '#2563eb', accentColor: '#3b82f6', backgroundColor: '#f0f9ff', textColor: '#0f172a', borderRadius: 'md' as const } }, { value: 'purple', label: 'Royal Purple', color: 'bg-purple-600', theme: { primaryColor: '#9333ea', accentColor: '#a855f7', backgroundColor: '#faf5ff', textColor: '#1e1b4b', borderRadius: 'md' as const } }, { value: 'rose', label: 'Rose Gold', color: 'bg-rose-600', theme: { primaryColor: '#e11d48', accentColor: '#f43f5e', backgroundColor: '#fff1f2', textColor: '#881337', borderRadius: 'md' as const } }, { value: 'amber', label: 'Sunset Amber', color: 'bg-amber-600', theme: { primaryColor: '#d97706', accentColor: '#f59e0b', backgroundColor: '#fffbeb', textColor: '#451a03', borderRadius: 'md' as const } }, ]; export const CreateEventPage: React.FC = () => { const navigate = useNavigate(); const isMountedRef = useRef(true); useEffect(() => { return () => { isMountedRef.current = false; }; }, []); const [formData, setFormData] = useState({ event_type: 'wedding', event_name: '', event_date: format(new Date(), 'yyyy-MM-dd'), host_email: '', admin_email: '', password: '', confirm_password: '', welcome_message: '', color_theme: 'default', expires_in_days: 30, }); const [errors, setErrors] = useState>>({}); const [showPassword, setShowPassword] = useState(false); const createMutation = useMutation({ mutationFn: eventsService.createEvent, onSuccess: (data) => { if (isMountedRef.current) { toast.success('Event created successfully!'); // Add a small delay to ensure navigation works properly setTimeout(() => { if (isMountedRef.current && data?.id) { navigate(`/admin/events/${data.id}`); } else { navigate('/admin/events'); } }, 100); } }, onError: (error: any) => { if (!isMountedRef.current) return; if (error.code === 'ERR_NETWORK' || error.code === 'ERR_CONNECTION_RESET') { toast.error('Network error. Please check your connection and try again.'); } else if (error.response?.data?.errors) { const newErrors: Record = {}; error.response.data.errors.forEach((err: any) => { newErrors[err.path] = err.msg; }); setErrors(newErrors); } else if (error.response?.status === 401) { toast.error('Session expired. Please login again.'); navigate('/admin/login'); } else { toast.error(error.response?.data?.error || 'Failed to create event'); } }, }); const validateForm = (): boolean => { const newErrors: Partial> = {}; if (!formData.event_name.trim()) { newErrors.event_name = 'Event name is required'; } if (!formData.host_email) { newErrors.host_email = 'Host email is required'; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.host_email)) { newErrors.host_email = 'Invalid email format'; } if (!formData.admin_email) { newErrors.admin_email = 'Admin email is required'; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.admin_email)) { newErrors.admin_email = 'Invalid email format'; } if (!formData.password) { newErrors.password = 'Password is required'; } else if (formData.password.length < 6) { newErrors.password = 'Password must be at least 6 characters'; } if (formData.password !== formData.confirm_password) { newErrors.confirm_password = 'Passwords do not match'; } if (formData.expires_in_days < 1 || formData.expires_in_days > 365) { newErrors.expires_in_days = 'Expiration must be between 1 and 365 days'; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!validateForm()) { return; } const selectedTheme = COLOR_THEMES.find(t => t.value === formData.color_theme); createMutation.mutate({ event_type: formData.event_type, event_name: formData.event_name, event_date: formData.event_date, host_email: formData.host_email, admin_email: formData.admin_email, password: formData.password, welcome_message: formData.welcome_message || '', color_theme: selectedTheme ? JSON.stringify(selectedTheme.theme) : undefined, expiration_days: formData.expires_in_days, }); }; const handleInputChange = (field: keyof FormData) => ( e: React.ChangeEvent ) => { const value = field === 'expires_in_days' ? parseInt(e.target.value) || 0 : e.target.value; setFormData(prev => ({ ...prev, [field]: value })); // Clear error when user types if (errors[field]) { setErrors(prev => ({ ...prev, [field]: '' })); } }; return (
{/* Page Header */}

Create New Event

Set up a new photo gallery for your event

{/* Event Details */}

Event Details

{/* Event Type */}
{EVENT_TYPES.map(type => ( ))}
{/* Event Name */}
} />
{/* Event Date */}
{/* Welcome Message */}