Source: src/components/UserForm.jsx

import React, { useState, useEffect } from "react";
import "./UserFormStyle.css";
import axios from "axios";
import { toast } from "react-toastify";
import {
  validateName,
  validateEmail,
  validateBirthDate,
  validatePostalCode,
} from "../utils/validators";

/**
 * Formulaire d'inscription utilisateur avec validation
 * @component
 * @param {Object} props
 * @param {Array} props.users - liste des utilisateurs
 * @param {Function} props.setUsers - met à jour la liste
 * @param {string} props.apiUrl - URL de l'API
 * @returns {JSX.Element} formulaire de saisie
 */
function UserForm({ users, setUsers, apiUrl }) {
  const [firstName, setFirstName] = useState("");
  const [lastName, setLastName] = useState("");
  const [email, setEmail] = useState("");
  const [birthDate, setBirthDate] = useState("");
  const [city, setCity] = useState("");
  const [postalCode, setPostalCode] = useState("");
  const [errors, setErrors] = useState({});
  const [isDisabled, setIsDisabled] = useState(true);

  // Récupère les utilisateurs au chargement
  useEffect(() => {
    axios
      .get(`${apiUrl}/api/users`)
      .then((res) => {
        setUsers(res.data.utilisateurs || []);
      })
      .catch((err) => {
        console.error("Erreur de récupération :", err);
        toast.error("Impossible de charger les utilisateurs.");
      });
  }, [apiUrl, setUsers]);

  useEffect(() => {
    setIsDisabled(
      !(firstName && lastName && email && birthDate && city && postalCode)
    );
  }, [firstName, lastName, email, birthDate, city, postalCode]);

  const validateField = (name, value) => {
    switch (name) {
      case "firstName":
      case "lastName":
      case "city":
        return !value || !validateName(value)
          ? "Champ invalide (lettres, accents, tirets uniquement)"
          : "";
      case "email":
        return !value || !validateEmail(value) ? "Email invalide" : "";
      case "birthDate":
        return !value || !validateBirthDate(value)
          ? "Vous devez avoir au moins 18 ans"
          : "";
      case "postalCode":
        return !value || !validatePostalCode(value)
          ? "Code postal invalide (5 chiffres)"
          : "";
      default:
        return "";
    }
  };

  const handleChange = (setter, fieldName) => (e) => {
    const value = e.target.value;
    setter(value);
    setErrors((prev) => ({
      ...prev,
      [fieldName]: validateField(fieldName, value),
    }));
  };

  const handleSubmit = (e) => {
    e.preventDefault();

    const newErrors = {
      firstName: validateField("firstName", firstName),
      lastName: validateField("lastName", lastName),
      email: validateField("email", email),
      birthDate: validateField("birthDate", birthDate),
      city: validateField("city", city),
      postalCode: validateField("postalCode", postalCode),
    };

    setErrors(newErrors);

    if (Object.values(newErrors).some((err) => err)) {
      toast.error("Veuillez corriger les erreurs du formulaire.");
      return;
    }

    const newUser = { firstName, lastName, email, birthDate, city, postalCode };

    axios
      .post(`${apiUrl}/api/users`, newUser)
      .then((response) => {
        setUsers([...users, response.data.utilisateur]);
        toast.success("Inscription réussie !");
        setFirstName("");
        setLastName("");
        setEmail("");
        setBirthDate("");
        setCity("");
        setPostalCode("");
        setErrors({});
      })
      .catch((error) => {
        console.error("Erreur d’inscription :", error);
        toast.error("Échec de l’inscription.");
      });
  };

  return (
    <div className="container">
      <h2 className="title">User Registration</h2>
      <form onSubmit={handleSubmit}>
        {[
          {
            name: "firstName",
            placeholder: "First Name",
            value: firstName,
            setter: setFirstName,
          },
          {
            name: "lastName",
            placeholder: "Last Name",
            value: lastName,
            setter: setLastName,
          },
          {
            name: "email",
            placeholder: "Email",
            value: email,
            setter: setEmail,
          },
          {
            name: "birthDate",
            type: "date",
            value: birthDate,
            setter: setBirthDate,
          },
          { name: "city", placeholder: "City", value: city, setter: setCity },
          {
            name: "postalCode",
            placeholder: "Postal Code",
            value: postalCode,
            setter: setPostalCode,
          },
        ].map(({ name, placeholder, value, setter, type = "text" }) => (
          <div key={name} className="form-group">
            <input
              type={type}
              name={name}
              placeholder={placeholder}
              className={`input-field ${errors[name] ? "error" : ""}`}
              value={value}
              onChange={handleChange(setter, name)}
              aria-label={name}
            />
            {errors[name] && <p className="error-message">{errors[name]}</p>}
          </div>
        ))}

        <button type="submit" disabled={isDisabled}>
          Submit
        </button>
      </form>
    </div>
  );
}

export default UserForm;