feat: Précablage du formulaire dynamique [N3WTS-17]

This commit is contained in:
2025-11-30 17:24:25 +01:00
parent 7486f6c5ce
commit dd00cba385
41 changed files with 2637 additions and 606 deletions

View File

@ -6,6 +6,7 @@ import Button from './Button';
import IconSelector from './IconSelector';
import * as LucideIcons from 'lucide-react';
import { FIELD_TYPES } from './FormTypes';
import FIELD_TYPES_WITH_ICONS from './FieldTypesWithIcons';
export default function AddFieldModal({
isOpen,
@ -55,6 +56,10 @@ export default function AddFieldModal({
acceptTypes: '',
maxSize: 5,
checked: false,
signatureData: '',
backgroundColor: '#ffffff',
penColor: '#000000',
penWidth: 2,
validation: {
pattern: '',
minLength: '',
@ -62,6 +67,16 @@ export default function AddFieldModal({
},
};
// Si un type a été présélectionné depuis le sélecteur de type
if (editingField && !isEditing) {
// S'assurer que le type est correctement défini
if (typeof editingField.type === 'string') {
defaultValues.type = editingField.type;
} else if (editingField.value) {
defaultValues.type = editingField.value;
}
}
setCurrentField(defaultValues);
// Réinitialiser le formulaire avec les valeurs de l'élément à éditer
@ -75,17 +90,32 @@ export default function AddFieldModal({
acceptTypes: defaultValues.acceptTypes,
maxSize: defaultValues.maxSize,
checked: defaultValues.checked,
signatureData: defaultValues.signatureData,
backgroundColor: defaultValues.backgroundColor,
penColor: defaultValues.penColor,
penWidth: defaultValues.penWidth,
validation: defaultValues.validation,
});
}
}, [isOpen, editingField, reset]);
}, [isOpen, editingField, reset, isEditing]);
// Ajouter une option au select
const addOption = () => {
const addOption = (e) => {
// Arrêter la propagation de l'événement pour éviter que le clic n'atteigne l'arrière-plan
if (e) {
e.preventDefault();
e.stopPropagation();
}
if (newOption.trim()) {
// Vérifie si options existe et est un tableau, sinon initialise comme tableau vide
const currentOptions = Array.isArray(currentField.options)
? currentField.options
: [];
setCurrentField({
...currentField,
options: [...currentField.options, newOption.trim()],
options: [...currentOptions, newOption.trim()],
});
setNewOption('');
}
@ -93,7 +123,12 @@ export default function AddFieldModal({
// Supprimer une option du select
const removeOption = (index) => {
const newOptions = currentField.options.filter((_, i) => i !== index);
// Vérifie si options existe et est un tableau, sinon initialise comme tableau vide
const currentOptions = Array.isArray(currentField.options)
? currentField.options
: [];
const newOptions = currentOptions.filter((_, i) => i !== index);
setCurrentField({ ...currentField, options: newOptions });
};
@ -141,15 +176,28 @@ export default function AddFieldModal({
name="type"
selected={value}
callback={(e) => {
onChange(e.target.value);
const newType = e.target.value;
onChange(newType);
// Assurons-nous que les options restent un tableau si on sélectionne select ou radio
let updatedOptions = currentField.options;
// Si options n'existe pas ou n'est pas un tableau, initialiser comme tableau vide
if (!updatedOptions || !Array.isArray(updatedOptions)) {
updatedOptions = [];
}
setCurrentField({
...currentField,
type: e.target.value,
type: newType,
options: updatedOptions,
});
}}
choices={FIELD_TYPES}
choices={FIELD_TYPES_WITH_ICONS}
placeHolder="Sélectionner un type"
required
showIcons={true}
customSelect={true}
/>
)}
/>
@ -353,21 +401,22 @@ export default function AddFieldModal({
/>
</div>
<div className="space-y-1">
{currentField.options.map((option, index) => (
<div
key={index}
className="flex items-center justify-between bg-gray-50 p-2 rounded"
>
<span>{option}</span>
<button
type="button"
onClick={() => removeOption(index)}
className="text-red-500 hover:text-red-700"
{Array.isArray(currentField.options) &&
currentField.options.map((option, index) => (
<div
key={index}
className="flex items-center justify-between bg-gray-50 p-2 rounded"
>
</button>
</div>
))}
<span>{option}</span>
<button
type="button"
onClick={() => removeOption(index)}
className="text-red-500 hover:text-red-700"
>
</button>
</div>
))}
</div>
</div>
)}
@ -396,21 +445,22 @@ export default function AddFieldModal({
/>
</div>
<div className="space-y-1">
{currentField.options.map((option, index) => (
<div
key={index}
className="flex items-center justify-between bg-gray-50 p-2 rounded"
>
<span>{option}</span>
<button
type="button"
onClick={() => removeOption(index)}
className="text-red-500 hover:text-red-700"
{Array.isArray(currentField.options) &&
currentField.options.map((option, index) => (
<div
key={index}
className="flex items-center justify-between bg-gray-50 p-2 rounded"
>
</button>
</div>
))}
<span>{option}</span>
<button
type="button"
onClick={() => removeOption(index)}
className="text-red-500 hover:text-red-700"
>
</button>
</div>
))}
</div>
</div>
)}
@ -484,6 +534,81 @@ export default function AddFieldModal({
</>
)}
{currentField.type === 'signature' && (
<>
<Controller
name="backgroundColor"
control={control}
defaultValue={currentField.backgroundColor || '#ffffff'}
render={({ field: { onChange, value } }) => (
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Couleur de fond
</label>
<input
type="color"
value={value}
onChange={(e) => {
onChange(e.target.value);
setCurrentField({
...currentField,
backgroundColor: e.target.value,
});
}}
className="w-full h-10 border border-gray-300 rounded-md cursor-pointer"
/>
</div>
)}
/>
<Controller
name="penColor"
control={control}
defaultValue={currentField.penColor || '#000000'}
render={({ field: { onChange, value } }) => (
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Couleur du stylo
</label>
<input
type="color"
value={value}
onChange={(e) => {
onChange(e.target.value);
setCurrentField({
...currentField,
penColor: e.target.value,
});
}}
className="w-full h-10 border border-gray-300 rounded-md cursor-pointer"
/>
</div>
)}
/>
<Controller
name="penWidth"
control={control}
defaultValue={currentField.penWidth || 2}
render={({ field: { onChange, value } }) => (
<InputTextIcon
label="Épaisseur du stylo (px)"
name="penWidth"
type="number"
min="1"
max="10"
value={value}
onChange={(e) => {
onChange(parseInt(e.target.value));
setCurrentField({
...currentField,
penWidth: parseInt(e.target.value) || 2,
});
}}
/>
)}
/>
</>
)}
{currentField.type === 'checkbox' && (
<>
<div className="flex items-center mt-2">