import React, { useState } from 'react'; import { IMaskInput } from 'react-imask'; import axios from 'axios'; export default function ReclamationForm({ objetId, userPrenom = '', userNom = '', userTelephone = '', userEmail = '', isLoggedIn: initialIsLoggedIn = false, loginUrl = '/login', csrfToken = '' }) { const [step, setStep] = useState(1); const [isLoggedIn, setIsLoggedIn] = useState(initialIsLoggedIn); const [showLoginModal, setShowLoginModal] = useState(false); const [formData, setFormData] = useState({ prenom: userPrenom, nom: userNom, telephone: userTelephone, email: userEmail, message: '', fichier: null, consent: false }); const [loginData, setLoginData] = useState({ email: '', password: '' }); const [loginError, setLoginError] = useState(null); const [isLoggingIn, setIsLoggingIn] = useState(false); const [errors, setErrors] = useState({}); const [isSubmitting, setIsSubmitting] = useState(false); const [serverError, setServerError] = useState(null); const [successMessage, setSuccessMessage] = useState(null); const handleLogin = async (e) => { e.preventDefault(); setIsLoggingIn(true); setLoginError(null); try { const params = new URLSearchParams(); params.append('email', loginData.email); params.append('password', loginData.password); params.append('_csrf_token', csrfToken); const response = await axios.post('/login', params, { headers: { 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' } }); if (response.data.success) { const user = response.data.user; setFormData(prev => ({ ...prev, prenom: user.prenom || '', nom: user.nom || '', telephone: user.telephone || '', email: user.email || '' })); setIsLoggedIn(true); setShowLoginModal(false); } } catch (error) { setLoginError(error.response?.data?.error || 'Identifiants invalides.'); } finally { setIsLoggingIn(false); } }; const handleLoginChange = (e) => { const { name, value } = e.target; setLoginData(prev => ({ ...prev, [name]: value })); }; const validateField = (name, value) => { let error = null; switch (name) { case 'prenom': if (!value) error = 'Le prénom est requis'; break; case 'nom': if (!value) error = 'Le nom est requis'; break; case 'telephone': const safeValue = value || ''; const phoneDigits = safeValue.replace(/\D/g, ''); const unmasked = safeValue.replace(/[\s\-_]/g, ''); if (!safeValue || phoneDigits.length <= 4) { error = 'Le téléphone est requis'; } else if (phoneDigits.length < 12 || !/^\+221(7[05678]|30|33)\d{7}$/.test(unmasked)) { error = 'Format invalide (ex: +221 77 123 45 67)'; } break; case 'email': if (value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) { error = 'Format email invalide'; } break; case 'message': if (!value) error = 'Le message est requis'; else if (value.length < 20) error = 'Veuillez fournir une description plus détaillée (min. 20 caractères)'; break; case 'consent': if (!value) error = 'Vous devez certifier l\'exactitude des informations'; break; case 'fichier': if (value && value.size > 5 * 1024 * 1024) { error = 'Le fichier ne doit pas dépasser 5 Mo'; } break; default: break; } return error; }; const validateStep = (currentStep) => { let newErrors = {}; if (currentStep === 1) { newErrors.prenom = validateField('prenom', formData.prenom); newErrors.nom = validateField('nom', formData.nom); newErrors.telephone = validateField('telephone', formData.telephone); newErrors.email = validateField('email', formData.email); } else if (currentStep === 2) { newErrors.message = validateField('message', formData.message); } else if (currentStep === 3) { newErrors.consent = validateField('consent', formData.consent); } // Filter out null errors const filteredErrors = Object.fromEntries(Object.entries(newErrors).filter(([_, v]) => v !== null)); setErrors(filteredErrors); return Object.keys(filteredErrors).length === 0; }; const handleChange = (e) => { const { name, value, type, checked } = e.target; const newValue = type === 'checkbox' ? checked : value; setFormData(prev => ({ ...prev, [name]: newValue })); // Real-time validation const error = validateField(name, newValue); setErrors(prev => ({ ...prev, [name]: error })); }; const handleFileChange = (e) => { const file = e.target.files[0]; if (file) { const error = validateField('fichier', file); setErrors(prev => ({ ...prev, fichier: error })); if (!error) { setFormData(prev => ({ ...prev, fichier: file })); } else { setFormData(prev => ({ ...prev, fichier: null })); } } }; const nextStep = () => { if (validateStep(step)) { setStep(prev => prev + 1); window.scrollTo({ top: 0, behavior: 'smooth' }); } }; const prevStep = () => { setStep(prev => prev - 1); window.scrollTo({ top: 0, behavior: 'smooth' }); }; const handleSubmit = async (e) => { e.preventDefault(); if (!validateStep(3)) return; setIsSubmitting(true); setServerError(null); const data = new FormData(); data.append('prenom', formData.prenom); data.append('nom', formData.nom); data.append('telephone', formData.telephone.replace(/[\s]/g, '')); if (formData.email) { data.append('email', formData.email); } data.append('message', formData.message); if (formData.fichier) { data.append('fichier', formData.fichier); } try { const response = await axios.post(`/api-reclamation/${objetId}`, data, { headers: { 'Content-Type': 'multipart/form-data' } }); if (response.data.success) { setSuccessMessage(response.data.message); window.scrollTo({ top: 0, behavior: 'smooth' }); setTimeout(() => { window.location.href = response.data.redirectUrl; }, 3000); } } catch (error) { setServerError(error.response?.data?.error || 'Une erreur est survenue lors de l\'envoi.'); setIsSubmitting(false); } }; if (successMessage) { return (
Redirection en cours vers les détails de l'objet...
Vous avez déjà un compte ?
pour pré-remplir vos informations automatiquement.
{step === 1 ? 'Commencez par nous dire qui vous êtes.' : step === 2 ? 'Expliquez-nous pourquoi cet objet vous appartient.' : 'Vérifiez et confirmez votre demande.'}
{serverError && (