Save France
Composants

Composants Partagés

Composants génériques réutilisables dans toute l'application

Vue d'ensemble

Les composants partagés sont des éléments d'interface utilisateur réutilisables à travers l'application. Ils sont conçus pour être indépendants et configurables via des props.

Liste des composants

1. AddressAutocomplete

Description

Composant d'autocomplétion d'adresse qui s'intègre avec une API de géocodage.

Props

NomTypeRequisDéfautDescription
modelValueAddressItemNonundefinedAdresse sélectionnée
searchTermstringNon''Terme de recherche actuel

Événements

NomParamètresDescription
update:modelValueAddressItemÉmis lorsque l'utilisateur sélectionne une adresse
update:searchTermstringÉmis lorsque l'utilisateur tape dans le champ de recherche

Types

interface AddressItem {
  geometry: any[];
  properties: {
    city: string;
    label: string;
    postcode: string;
    housenumber?: string;
  };
}

Utilisation

<template>
  <AddressAutocomplete 
    v-model="selectedAddress"
    v-model:search-term="searchTerm"
  />
</template>

<script setup>
const selectedAddress = ref();
const searchTerm = ref('');
</script>

2. ContractSummaryCard

Description

Composant d'affichage du résumé d'un contrat avec les informations du client et les détails du contrat.

Props

NomTypeRequisDéfautDescription
requestRequestOui-Objet contenant les informations de la demande

Types

interface Contact {
  name?: string;
  lastname?: string;
  email?: string;
  street?: string;
  postalCode?: string;
  city?: string;
  isPro?: boolean;
}

interface Price {
  ht?: number;
  ttc?: number;
}

interface Offer {
  price?: Price;
  maintenanceOffer?: {
    name?: string;
  };
}

interface Request {
  contact?: Contact;
  offer?: Offer;
  equipments?: Array<any>;
}

Utilisation

<template>
  <ContractSummaryCard :request="request" class="mb-8" />
</template>

<script setup>
const { data: request } = await useFetch(`/api/requests/${reqID}`, {
  headers: {
    Authorization: `Bearer ${token}`,
  },
});
</script>

Fonctionnalités

  • Affichage des informations client (nom, email, adresse)
  • Affichage des détails du contrat (type, prix HT/TTC, équipements)
  • Formatage automatique des prix (conversion centimes → euros)
  • Adaptation automatique du prix affiché selon le statut professionnel (HT pour les pros, TTC pour les particuliers)

3. StepNavigation

Description

Composant de navigation entre les étapes d'un formulaire ou d'un processus.

Props

NomTypeRequisDéfautDescription
stepsArray<{ id: string; label: string }>Oui[]Liste des étapes
currentStepstringOui-ID de l'étape courante
canContinuebooleanNontrueSi false, désactive le bouton suivant

Événements

NomParamètresDescription
next-Émis lorsque l'utilisateur clique sur Suivant
prev-Émis lorsque l'utilisateur clique sur Précédent
gotostepId: stringÉmis lorsque l'utilisateur clique sur une étape spécifique

Utilisation

<template>
  <StepNavigation
    :steps="steps"
    :current-step="currentStep"
    :can-continue="canContinue"
    @next="goToNextStep"
    @prev="goToPrevStep"
    @goto="goToStep"
  />
</template>

<script setup>
const steps = [
  { id: 'info', label: 'Informations' },
  { id: 'address', label: 'Adresse' },
  { id: 'summary', label: 'Récapitulatif' },
];

const currentStep = ref('info');

function goToNextStep() {
  // Logique pour passer à l'étape suivante
}

function goToPrevStep() {
  // Logique pour revenir à l'étape précédente
}

function goToStep(stepId) {
  // Logique pour aller à une étape spécifique
}
</script>

Bonnes Pratiques

  1. Props
    • Toujours typer les props avec TypeScript
    • Fournir des valeurs par défaut appropriées
    • Documenter chaque prop avec sa description et son type
  2. Événements
    • Utiliser des noms d'événements en kebab-case
    • Documenter les paramètres des événements
    • Utiliser des interfaces TypeScript pour les données complexes
  3. Style
    • Utiliser des classes utilitaires de Nuxt UI quand c'est possible
    • Éviter les styles en dur dans les composants partagés
    • Utiliser des variables CSS pour les couleurs et les espacements
  4. Accessibilité
    • Utiliser des éléments sémantiques
    • Implémenter la navigation au clavier
    • Ajouter des attributs ARIA quand nécessaire

Personnalisation

Thème

Les composants utilisent les variables CSS définies dans le thème Nuxt UI. Pour personnaliser :

/* assets/css/main.css */
:root {
  --primary: #3498db;
  --primary-dark: #2980b9;
  --text: #2d3436;
  /* ... autres variables */
}

Internationalisation

Les textes des composants sont gérés via le système de traduction Nuxt i18n. Pour ajouter une nouvelle langue :

// locales/fr.json
{
  "addressAutocomplete": {
    "placeholder": "Entrez votre adresse",
    "noResults": "Aucun résultat, essayez une autre adresse"
  }
}

Tests

Chaque composant doit être accompagné de tests unitaires. Exemple avec Vitest :

// tests/components/shared/AddressAutocomplete.spec.ts
import { mount } from '@vue/test-utils';
import { describe, it, expect } from 'vitest';
import AddressAutocomplete from '~/components/shared/AddressAutocomplete.vue';

describe('AddressAutocomplete', () => {
  it('affiche le placeholder par défaut', () => {
    const wrapper = mount(AddressAutocomplete);
    expect(wrapper.find('input').attributes('placeholder')).toContain('Entrez votre adresse');
  });
});

Dépendances

  • @nuxt/ui : Composants UI de base
  • vue : Framework principal
  • @vueuse/core : Utilitaires de composition

Dépannage

L'autocomplétion ne fonctionne pas

  1. Vérifiez que l'API de géocodage est accessible
  2. Vérifiez les erreurs dans la console du navigateur
  3. Assurez-vous que le composant a accès à l'URL de l'API

Les styles ne s'appliquent pas

  1. Vérifiez que le thème Nuxt UI est correctement configuré
  2. Assurez-vous que les styles personnalisés sont chargés dans app.vue

Exemple Complet

<template>
  <div class="address-form">
    <h2>Adresse de livraison</h2>
    <AddressAutocomplete
      v-model="selectedAddress"
      v-model:search-term="searchTerm"
      class="mb-4"
    />
    
    <UButton
      :disabled="!selectedAddress"
      @click="handleAddressSelect"
    >
      Valider l'adresse
    </UButton>
  </div>
</template>

<script setup lang="ts">
const selectedAddress = ref();
const searchTerm = ref('');

function handleAddressSelect() {
  if (selectedAddress.value) {
    // Traitement de l'adresse sélectionnée
    console.log('Adresse sélectionnée :', selectedAddress.value);
  }
}
</script>

<style scoped>
.address-form {
  max-width: 500px;
  margin: 0 auto;
  padding: 1rem;
}
</style>