import React, { useState, useRef, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { Calendar, Mail, Lock, Clock, ArrowLeft, Info, Upload, Eye, EyeOff } from 'lucide-react'; import { format, addDays } from 'date-fns'; import { toast } from 'react-toastify'; import { Button, Input, Card } from '../../components/common'; import { useMutation, useQuery } from '@tanstack/react-query'; import { eventsService } from '../../services/events.service'; import { categoriesService } from '../../services/categories.service'; import { useTranslation } from 'react-i18next'; 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; allow_user_uploads: boolean; upload_category_id: number | null; } const EVENT_TYPES = [ { value: 'wedding', labelKey: 'events.types.wedding', emoji: '💒' }, { value: 'birthday', labelKey: 'events.types.birthday', emoji: '🎂' }, { value: 'corporate', labelKey: 'events.types.corporate', emoji: '🏢' }, { value: 'other', labelKey: 'events.types.other', emoji: '📸' }, ]; const COLOR_THEMES = [ { value: 'default', labelKey: 'events.themes.default', color: 'bg-primary-600', theme: { primaryColor: '#5C8762', accentColor: '#22c55e', backgroundColor: '#fafafa', textColor: '#171717', borderRadius: 'md' as const } }, { value: 'blue', labelKey: 'events.themes.oceanBlue', color: 'bg-blue-600', theme: { primaryColor: '#2563eb', accentColor: '#3b82f6', backgroundColor: '#f0f9ff', textColor: '#0f172a', borderRadius: 'md' as const } }, { value: 'purple', labelKey: 'events.themes.royalPurple', color: 'bg-purple-600', theme: { primaryColor: '#9333ea', accentColor: '#a855f7', backgroundColor: '#faf5ff', textColor: '#1e1b4b', borderRadius: 'md' as const } }, { value: 'rose', labelKey: 'events.themes.roseGold', color: 'bg-rose-600', theme: { primaryColor: '#e11d48', accentColor: '#f43f5e', backgroundColor: '#fff1f2', textColor: '#881337', borderRadius: 'md' as const } }, { value: 'amber', labelKey: 'events.themes.sunsetAmber', 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 { t } = useTranslation(); 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, allow_user_uploads: false, upload_category_id: null, }); const [errors, setErrors] = useState>>({}); const [showPassword, setShowPassword] = useState(false); // Fetch categories for user upload selection const { data: categories } = useQuery({ queryKey: ['categories', 'global'], queryFn: () => categoriesService.getGlobalCategories() }); const createMutation = useMutation({ mutationFn: eventsService.createEvent, onSuccess: (data) => { if (isMountedRef.current) { toast.success(t('toast.eventCreated')); // 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(t('errors.networkError')); } 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(t('errors.sessionExpired')); navigate('/admin/login'); } else { const errorMessage = error.response?.data?.error; // Check if it's the password security requirements error if (errorMessage === 'Password does not meet security requirements') { toast.error(t('validation.passwordSecurityRequirements')); } else { toast.error(errorMessage || t('errors.failedToCreateEvent')); } } }, }); const validateForm = (): boolean => { const newErrors: Partial> = {}; if (!formData.event_name.trim()) { newErrors.event_name = t('validation.eventNameRequired'); } if (!formData.host_email) { newErrors.host_email = t('validation.hostEmailRequired'); } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.host_email)) { newErrors.host_email = t('validation.invalidEmailFormat'); } if (!formData.admin_email) { newErrors.admin_email = t('validation.adminEmailRequired'); } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.admin_email)) { newErrors.admin_email = t('validation.invalidEmailFormat'); } if (!formData.password) { newErrors.password = t('validation.passwordRequired'); } else if (formData.password.length < 6) { newErrors.password = t('validation.passwordMinLength'); } else if (/^\d{1,6}$/.test(formData.password)) { // Prevent simple numeric passwords like "123456" newErrors.password = t('validation.passwordTooSimple', 'Password cannot be just numbers. Consider using a date format like "04.07.2025"'); } if (formData.password !== formData.confirm_password) { newErrors.confirm_password = t('validation.passwordsDoNotMatch'); } if (formData.expires_in_days < 1 || formData.expires_in_days > 365) { newErrors.expires_in_days = t('validation.expirationRange'); } 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, allow_user_uploads: formData.allow_user_uploads, upload_category_id: formData.upload_category_id, }); }; 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 */}

{t('events.createNewEvent')}

{t('events.createNewEventSubtitle')}

{/* Event Details */}

{t('events.eventDetails')}

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