"use client"; import { useRef, useState } from "react"; import type { FormHTMLAttributes, PropsWithChildren } from "react"; type Props = PropsWithChildren< FormHTMLAttributes & { confirmTitle: string; confirmMessage: string; confirmCta?: string; cancelCta?: string; disabled?: boolean; submitLabel?: string; // when you want to render a default submit button buttonClassName?: string; // Nouveau: support pour les actions async (API calls) action?: string | ((formData: FormData) => Promise); } >; export default function ConfirmableForm({ children, confirmTitle, confirmMessage, confirmCta = "Confirmer", cancelCta = "Annuler", disabled, submitLabel, buttonClassName, action, ...formProps }: Props) { const formRef = useRef(null); const [open, setOpen] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); function onSubmitIntercept(e: React.FormEvent) { if (disabled || isSubmitting) return; // disabled => laisse le navigateur gérer e.preventDefault(); setOpen(true); } async function doSubmit() { if (!formRef.current || isSubmitting) return; setIsSubmitting(true); setOpen(false); try { if (typeof action === "function") { // Action async personnalisée const formData = new FormData(formRef.current); await action(formData); } else if (typeof action === "string") { // URL d'action classique formRef.current.action = action; formRef.current.submit(); } else { // Soumission classique formRef.current.submit(); } } catch (error) { console.error("Erreur lors de la soumission:", error); // L'erreur est gérée par le composant parent via l'action } finally { setIsSubmitting(false); } } return ( <>
{children} {submitLabel && ( )}
{open && (
{/* backdrop */}
setOpen(false)} aria-hidden /> {/* modal */}

{confirmTitle}

{confirmMessage}

)} ); }