import logger from '@/utils/logger'; import { useForm, Controller } from 'react-hook-form'; import { useEffect } from 'react'; import SelectChoice from './SelectChoice'; import InputTextIcon from './InputTextIcon'; import * as LucideIcons from 'lucide-react'; import Button from './Button'; import DjangoCSRFToken from '../DjangoCSRFToken'; import WisiwigTextArea from './WisiwigTextArea'; import RadioList from './RadioList'; import CheckBox from './CheckBox'; import ToggleSwitch from './ToggleSwitch'; import InputPhone from './InputPhone'; import FileUpload from './FileUpload'; import SignatureField from './SignatureField'; /* * Récupère une icône Lucide par son nom. */ export function getIcon(name) { if (Object.keys(LucideIcons).includes(name)) { const Icon = LucideIcons[name]; return Icon ?? null; } else { return null; } } export default function FormRenderer({ formConfig, csrfToken, initialValues = {}, onFormSubmit = (data) => { alert(JSON.stringify(data, null, 2)); }, // Callback de soumission personnalisé (optionnel) }) { const { handleSubmit, control, formState: { errors }, reset, } = useForm({ defaultValues: initialValues }); // Réinitialiser le formulaire quand les valeurs initiales changent useEffect(() => { if (initialValues && Object.keys(initialValues).length > 0) { reset(initialValues); } }, [initialValues, reset]); // Fonction utilitaire pour envoyer les données au backend const sendFormDataToBackend = async (formData) => { try { // Cette fonction peut être remplacée par votre propre implémentation // Exemple avec fetch: const response = await fetch('/api/submit-form', { method: 'POST', body: formData, // Les en-têtes sont automatiquement définis pour FormData }); if (!response.ok) { throw new Error(`Erreur HTTP ${response.status}`); } const result = await response.json(); logger.debug('Envoi réussi:', result); return result; } catch (error) { logger.error("Erreur lors de l'envoi:", error); throw error; } }; const onSubmit = async (data) => { logger.debug('=== DÉBUT onSubmit ==='); logger.debug('Réponses :', data); try { // Vérifier si nous avons des fichiers dans les données const hasFiles = Object.keys(data).some((key) => { return ( data[key] instanceof FileList || (data[key] && data[key][0] instanceof File) || (typeof data[key] === 'string' && data[key].startsWith('data:image')) ); }); if (hasFiles) { // Utiliser FormData pour l'envoi de fichiers const formData = new FormData(); // Ajouter l'ID du formulaire formData.append('formId', (formConfig?.id || 'unknown').toString()); // Traiter chaque champ et ses valeurs Object.keys(data).forEach((key) => { const value = data[key]; if ( value instanceof FileList || (value && value[0] instanceof File) ) { // Gérer les champs de type fichier if (value.length > 0) { for (let i = 0; i < value.length; i++) { formData.append(`files.${key}`, value[i]); } } } else if ( typeof value === 'string' && value.startsWith('data:image') ) { // Gérer les signatures (SVG ou images base64) if (value.includes('svg+xml')) { // Gérer les signatures SVG const svgData = value.split(',')[1]; const svgBlob = new Blob([atob(svgData)], { type: 'image/svg+xml', }); formData.append(`files.${key}`, svgBlob, `signature_${key}.svg`); } else { // Gérer les images base64 classiques const byteString = atob(value.split(',')[1]); const ab = new ArrayBuffer(byteString.length); const ia = new Uint8Array(ab); for (let i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } const blob = new Blob([ab], { type: 'image/png' }); formData.append(`files.${key}`, blob, `signature_${key}.png`); } } else { // Gérer les autres types de champs formData.append( `data.${key}`, value !== undefined ? value.toString() : '' ); } }); if (onFormSubmit) { // Utiliser le callback personnalisé si fourni await onFormSubmit(formData, true); } else { // Sinon, utiliser la fonction par défaut await sendFormDataToBackend(formData); alert('Formulaire avec fichier(s) envoyé avec succès'); } } else { // Pas de fichier, on peut utiliser JSON const formattedData = { formId: formConfig?.id || 'unknown', responses: { ...data }, }; if (onFormSubmit) { // Utiliser le callback personnalisé si fourni await onFormSubmit(formattedData, false); } else { // Afficher un message pour démonstration alert('Données reçues : ' + JSON.stringify(formattedData, null, 2)); } } reset(); // Réinitialiser le formulaire après soumission } catch (error) { logger.error('Erreur lors de la soumission du formulaire:', error); alert(`Erreur lors de l'envoi du formulaire: ${error.message}`); } logger.debug('=== FIN onSubmit ==='); }; const onError = (errors) => { logger.error('=== ERREURS DE VALIDATION ==='); logger.error('Erreurs :', errors); alert('Erreurs de validation : ' + JSON.stringify(errors, null, 2)); }; return (
); }