Source: components/RegistrationForm.jsx

import { useState, useMemo } from "react";
import { validatePerson } from "../utils/validation";

/**
 * Initial state for the registration form.
 * All fields start empty.
 */
const initialState = {
  lastName: "",
  firstName: "",
  email: "",
  birthDate: "",
  city: "",
  postalCode: "",
};

/**
 * RegistrationForm Component
 * Renders a user registration form and handles validation, submission, 
 * and user feedback (errors and success message).
 */
export default function RegistrationForm() {
  const [form, setForm] = useState(initialState);
  const [errors, setErrors] = useState(validatePerson(initialState));
  const [success, setSuccess] = useState(false);

  /**
   * Memoized person object derived from form state.
   * This object is used for validation and submission.
   */
  const person = useMemo(
    () => ({
      lastName: form.lastName,
      firstName: form.firstName,
      email: form.email,
      birthDate: form.birthDate,
      city: form.city,
      postalCode: form.postalCode,
    }),
    [form]
  );

  const isValid = Object.keys(errors).length === 0;
  // console.log("Form valid: ", isValid, "Errors: ", errors)

  /**
   * Handle input changes
   * • Updates the form state with the new value
   * • Clears the success message
   * • Re-validates the form after the change
   */
  const handleChange = (e) => {
    setSuccess(false);
    setForm({ ...form, [e.target.name]: e.target.value });
    setErrors(validatePerson({ ...person, [e.target.name]: e.target.value }));
  };

  /**
   * Handle form submission
   * • Saves the person object to localStorage
   * • Shows success message
   * • Resets form to initial state
   */
  const handleSubmit = (e) => {
    e.preventDefault();

    localStorage.setItem("user", JSON.stringify(person));
    setSuccess(true);
    setForm(initialState);
  };

  /**
   * Render a single input field with validation feedback
   * @param {string} name Field name in state
   * @param {string} placeholder Field placeholder text
   * @param {string} type Input type, default "text"
   * @returns JSX fragment containing input and error message
   */
  const renderField = (name, placeholder, type = "text") => (
    <>
      <input
        type={type}
        name={name}
        placeholder={placeholder}
        value={form[name]}
        onChange={handleChange}
        style={{ borderColor: errors[name] ? "red" : undefined }}
      />
      {errors[name] && <span style={{ color: "red" }}>{placeholder} invalide</span>}
    </>
  );

  /**
   * Render the registration form
   * - Uses renderField for each input
   * - Submit button is disabled if form invalid or already submitted
   * - Displays a success message when submission succeeds
   */
  return (
    <form onSubmit={handleSubmit} aria-label="registration-form">
      {renderField("lastName", "Nom")}
      {renderField("firstName", "Prénom")}
      {renderField("email", "Email")}
      {renderField("birthDate", "Date naissance", "date")}
      {renderField("city", "Ville")}
      {renderField("postalCode", "Code postal")}

      <button type="submit" disabled={!isValid || success}>S'inscrire</button>

      {success && <p style={{ color: "green" }}>Utilisateur enregistré !</p>}
    </form>
  );
}