import { Controls, Canvas, Meta, Source } from '@storybook/blocks';
import * as SyFormStories from './SyForm.stories';

<Meta of={SyFormStories} />

<div className="header">
  <h1>SyForm</h1>
  <p>
    SyForm est un composant de formulaire qui étend les fonctionnalités du v-form de Vuetify avec un 
    système de validation en cascade permettant de gérer facilement la validation des composants personnalisés 
    et natifs Vuetify dans un même formulaire.
  </p>
</div>

## Fonctionnalités

- Validation automatique des composants personnalisés et natifs Vuetify lors de la soumission
- Système de validation en cascade pour les formulaires complexes et imbriqués
- API simplifiée avec événement `submit` enrichi d'informations de validation
- Méthodes exposées pour la validation et la réinitialisation programmatives

## Utilisation basique

Le composant `SyForm` peut être utilisé comme un formulaire standard avec validation automatique lors de la soumission.

<Canvas of={SyFormStories.Basic} />

<Source dark code={'\n<script setup lang="ts">\nimport { ref } from "vue"\nimport SyForm from "@cnamts/synapse"\nimport SyTextField from "@cnamts/synapse"\n\nconst name = ref("")\nconst email = ref("")\n\nconst onSubmit = (event) => {\n  if (event.isValid) {\n    alert("Formulaire valide !")\n  }\n  else {\n    alert("Formulaire invalide, veuillez corriger les erreurs.")\n  }\n}\n</script>\n\n<template>\n  <SyForm @submit="onSubmit">\n    <div class="d-flex flex-column gap-4">\n      <SyTextField v-model="name" label="Nom" required />\n      <SyTextField v-model="email" label="Email" required :rules="[v => /.+@.+/.test(v) || \'E-mail invalide\']" />\n      <v-btn type="submit" color="primary">Soumettre</v-btn>\n    </div>\n  </SyForm>\n</template>'} />

## Validation personnalisée

Vous pouvez implémenter des règles de validation personnalisées et accéder au formulaire via une référence.

<Canvas of={SyFormStories.CustomValidation} />

<Source dark code={'\n<script setup lang="ts">\nimport { ref } from "vue"\nimport SyForm from "@cnamts/synapse"\nimport SyTextField from "@cnamts/synapse"\n\nconst username = ref("")\nconst password = ref("")\nconst confirmPassword = ref("")\nconst form = ref(null)\n\nconst validatePasswordMatch = () => {\n  return password.value === confirmPassword.value || "Les mots de passe ne correspondent pas"\n}\n\nconst onSubmit = (event) => {\n  if (event.isValid) {\n    alert("Inscription réussie !")\n  }\n}\n\nconst validateManually = () => {\n  form.value?.validate().then((isValid) => {\n    alert(isValid ? "Formulaire valide !" : "Formulaire invalide !")\n  })\n}\n</script>\n\n<template>\n  <div>\n    <SyForm ref="form" @submit="onSubmit">\n      <div class="d-flex flex-column gap-4">\n        <SyTextField v-model="username" label="Nom d\'utilisateur" required />\n        <SyTextField v-model="password" label="Mot de passe" type="password" required :rules="[v => v.length >= 8 || \'Minimum 8 caractères\']" />\n        <SyTextField \n          v-model="confirmPassword" \n          label="Confirmer le mot de passe" \n          type="password" \n          required \n          :rules="[validatePasswordMatch]" \n        />\n        <div class="d-flex gap-3">\n          <v-btn type="submit" color="primary">S\'inscrire</v-btn>\n          <v-btn @click="validateManually" color="secondary">Valider sans soumettre</v-btn>\n        </div>\n      </div>\n    </SyForm>\n  </div>\n</template>'} />

## Différents types de champs

`SyForm` prend en charge tous les types de champs, qu'ils soient personnalisés ou natifs de Vuetify.

<Canvas of={SyFormStories.MixedFields} />

<Source dark code={'\n<script setup lang="ts">\nimport { ref } from "vue"\nimport SyForm from "@cnamts/synapse"\nimport SyTextField from "@cnamts/synapse"\nimport SySelect from "@/components/Customs/Selects/SySelect/SySelect.vue"\nimport SyCheckbox from "@/components/Customs/SyCheckbox/SyCheckbox.vue"\n\nconst formData = ref({\n  name: "",\n  email: "",\n  country: "",\n  subscribe: false,\n})\n\nconst countries = [\n  { text: "France", value: "fr" },\n  { text: "Allemagne", value: "de" },\n  { text: "Espagne", value: "es" },\n  { text: "Italie", value: "it" },\n]\n\nconst onSubmit = (event) => {\n  if (event.isValid) {\n    alert("Formulaire valide ! Données: " + JSON.stringify(formData.value))\n  }\n}\n</script>\n\n<template>\n  <SyForm @submit="onSubmit">\n    <div class="d-flex flex-column gap-4">\n      <SyTextField v-model="formData.name" label="Nom complet" required />\n      <SyTextField v-model="formData.email" label="Email" required :rules="[v => /.+@.+/.test(v) || \'E-mail invalide\']" />\n      <SySelect v-model="formData.country" :items="countries" label="Pays" required />\n      <SyCheckbox v-model="formData.subscribe" label="S\'abonner à la newsletter" />\n      <v-btn type="submit" color="primary">Enregistrer</v-btn>\n    </div>\n  </SyForm>\n</template>'} />

## Sans validation automatique

Si vous souhaitez gérer vous-même la validation, vous pouvez désactiver la validation automatique en passant `validate-on-submit="false"`.

<Source dark code={'\n<script setup lang="ts">\nimport { ref } from "vue"\nimport SyForm from "@cnamts/synapse"\nimport SyTextField from "@cnamts/synapse"\n\nconst name = ref("")\nconst email = ref("")\n\nconst onSubmit = () => {\n  // La validation ne se fait pas automatiquement\n  alert("Soumission du formulaire sans validation automatique. Vous devez gérer la validation manuellement.")\n}\n</script>\n\n<template>\n  <SyForm :validate-on-submit="false" @submit="onSubmit">\n    <div class="d-flex flex-column gap-4">\n      <SyTextField v-model="name" label="Nom" required />\n      <SyTextField v-model="email" label="Email" required :rules="[v => /.+@.+/.test(v) || \'E-mail invalide\']" />\n      <v-btn type="submit" color="primary">Soumettre</v-btn>\n    </div>\n  </SyForm>\n</template>'} />

## API

<Controls of={SyFormStories.Basic} />

## Événements

<table>
  <thead>
    <tr>
      <th>Nom</th>
      <th>Description</th>
      <th>Signature</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>submit</code></td>
      <td>Émis lors de la soumission du formulaire. Le payload contient le résultat de la validation.</td>
      <td><code>(payload: &#123; isValid: boolean &#125;) =&gt; void</code></td>
    </tr>
    <tr>
      <td><code>reset</code></td>
      <td>Émis lors de la réinitialisation du formulaire (appel explicite de <code>reset()</code> ou bouton <code>type="reset"</code>).</td>
      <td><code>() =&gt; void</code></td>
    </tr>
  </tbody>
</table>

## Méthodes exposées

<table>
  <thead>
    <tr>
      <th>Nom</th>
      <th>Description</th>
      <th>Signature</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>validate</code></td>
      <td>Valide tous les composants du formulaire (Vuetify + composants personnalisés) et met à jour l’état interne de validation.</td>
      <td><code>() =&gt; Promise&lt;boolean&gt;</code></td>
    </tr>
    <tr>
      <td><code>reset</code></td>
      <td>Réinitialise tous les composants du formulaire et émet l’événement <code>reset</code>.</td>
      <td><code>() =&gt; void</code></td>
    </tr>
    <tr>
      <td><code>clearValidation</code></td>
      <td>Efface uniquement les états de validation (messages d’erreur, etc.) sans modifier les valeurs des champs.</td>
      <td><code>() =&gt; void</code></td>
    </tr>
  </tbody>
</table>

## Le système de validation en cascade

`SyForm` fonctionne avec le système de validation en cascade basé sur les composables `useFormValidation` et `useValidatable`. Ce système permet aux composants de s'auto-enregistrer auprès du formulaire parent, sans nécessiter de références manuelles.

<Source dark code={'\n// Dans SyForm.vue\nimport { ref } from "vue"\nimport { useFormValidation } from "@/composables/validation/useFormValidation"\n\nconst { validateAll } = useFormValidation()\n\nconst validate = async () => {\n  // 1. Valider les composants Vuetify natifs\n  const vuetifyValid = await form.value?.validate() ?? false\n  \n  // 2. Valider les composants personnalisés\n  const customComponentsValid = await validateAll()\n  \n  // Le formulaire est valide si les deux sont valides\n  return vuetifyValid && customComponentsValid\n}\n'} />

## Composants compatibles

Les composants suivants sont déjà intégrés avec le système de validation en cascade et fonctionnent automatiquement avec `SyForm` :

- SyTextField
- SySelect
- SyCheckbox
- DatePicker
- ComplexDatePicker
- DateTextInput
- NirField
- PasswordField
- PhoneField

## Exemple d'utilisation complète

<Source dark code={'\n<script setup lang="ts">\nimport { ref } from "vue"\nimport SyForm from "@cnamts/synapse"\nimport SyTextField from "@cnamts/synapse"\nimport SyCheckbox from "@/components/Customs/SyCheckbox/SyCheckbox.vue"\n\nconst formData = ref({\n  name: "",\n  email: "",\n  acceptTerms: false\n})\n\nconst formRef = ref(null)\n\nconst onSubmit = (event) => {\n  if (event.isValid) {\n    // Traitement des données du formulaire\n    console.log("Données valides:", formData.value)\n  }\n}\n\nconst validateManually = async () => {\n  const isValid = await formRef.value?.validate()\n  console.log("Formulaire valide:", isValid)\n}\n\nconst resetForm = () => {\n  formRef.value?.reset()\n  formData.value = { name: "", email: "", acceptTerms: false }\n}\n</script>\n\n<template>\n  <SyForm ref="formRef" @submit="onSubmit">\n    <SyTextField v-model="formData.name" label="Nom" required />\n    <SyTextField \n      v-model="formData.email" \n      label="Email" \n      required \n      :rules="[v => /.+@.+/.test(v) || \'E-mail invalide\']" \n    />\n    <SyCheckbox v-model="formData.acceptTerms" label="J\'accepte les conditions" required />\n    \n    <div class="actions">\n      <v-btn type="submit">Soumettre</v-btn>\n      <v-btn @click="validateManually">Valider</v-btn>\n      <v-btn @click="resetForm">Réinitialiser</v-btn>\n    </div>\n  </SyForm>\n</template>\n'} />

## Bonnes pratiques

1. **Validez toujours vos données côté serveur** - Ne vous fiez jamais uniquement à la validation côté client.
2. **Fournissez des messages d'erreur explicites** - Aidez l'utilisateur à comprendre ce qu'il doit corriger.
3. **Implémentez une validation progressive** - Validez au fur et à mesure que l'utilisateur remplit le formulaire.
4. **Respectez l'accessibilité** - Les messages d'erreur doivent être accessibles aux lecteurs d'écran.
5. **Testez vos formulaires** - Assurez-vous que la validation fonctionne comme prévu dans tous les scénarios.

## Note sur l'accessibilité

Le composant `SyForm` est conçu pour être accessible. Il utilise les attributs ARIA appropriés et est conforme aux recommandations du RGAA (Référentiel Général d'Amélioration de l'Accessibilité).
