import type { Meta, StoryObj } from '@storybook/vue3' import AmeliproCard from '../AmeliproCard/AmeliproCard.vue' import AmeliproResultList from './AmeliproResultList.vue' import type { IDataListItem } from '../types' import { computed, ref } from 'vue' const meta = { argTypes: { '`result-${item.id}`': { description: 'Slot individuel si tous vos résultats ne sont pas basés sur le même gabarit' }, 'change:pagination-select': { description: 'Événement émis à la sélection d’un nombre de résultats par page. Émet le nombre de résultat par page sélectionné', type: 'number' }, 'change:sort-select': { description: 'Événement émis à la sélection d’un tri. Émet le choix de tri sélectionné', type: '' }, 'click': { description: 'Événement émis au click sur un bouton de pagination', type: 'void' }, 'counterLabel': { description: 'Label du compteur de résultats en haut de la liste de résultats' }, 'hiddenLabels': { description: 'Masque les labels des champs select' }, 'items': { description: 'Tableau comprenant la liste des résultats', table: { type: { detail: `Array<{ id: number, [key: string]: string, }>`, summary: 'IDataListItem[]', }, }, }, 'itemsToDisplayDesktop': { description: 'Nombre d’éléments affichés par page en desktop par défaut' }, 'itemsToDisplayMobile': { description: 'Nombre d’éléments affichés par page en mobile par défaut' }, 'noResultListInfos': { description: 'Masques les informations et les filtres au-dessus de la liste de résultats' }, 'paginationSelect': { description: 'Affiche le select nombre de résultat par page' }, 'paginationSelectLabel': { description: 'Label du select de pagination' }, 'paginationSelectPlaceholder': { description: 'Placeholder du select de pagination' }, 'result': { description: 'Slot générique permettant de donner le même aspect à tout les items de votre liste' }, 'sortSelect': { description: 'Affiche le select de tri' }, 'sortSelectDefaultValue': { description: 'valeur par défaut sélectionnée dans le select dédié aux tris', control: 'text', }, 'sortSelectItems': { description: 'Items du select dédié aux tris' }, 'sortSelectLabel': { description: 'Label du select de tri' }, 'sortSelectPlaceholder': { description: 'Placeholder du select de tri' }, 'title': { description: 'Titre de la liste' }, 'uniqueId': { description: 'Identifiant unique de la liste' }, }, component: AmeliproResultList, title: 'Composants/Amelipro/Listes de résultats/AmeliproResultList', } as Meta export default meta type Story = StoryObj const items: IDataListItem[] = [ { email: 'jean.bernard@gmail.com', firstname: 'Jean', id: 0, name: 'Bernard', }, { email: 'simon.pierre@gmail.com', firstname: 'Simon', id: 1, name: 'Pierre', }, { email: 'michel.souris@gmail.com', firstname: 'Michel', id: 2, name: 'Souris', }, { email: 'amandine.jabot@gmail.com', firstname: 'Amandine', id: 3, name: 'Jabot', }, { email: 'jean.bernard@gmail.com', firstname: 'Jean', id: 4, name: 'Bernard', }, { email: 'simon.pierre@gmail.com', firstname: 'Simon', id: 5, name: 'Pierre', }, { email: 'michel.souris@gmail.com', firstname: 'Michel', id: 6, name: 'Souris', }, { email: 'amandine.jabot@gmail.com', firstname: 'Amandine', id: 7, name: 'Jabot', }, { email: 'jean.bernard@gmail.com', firstname: 'Jean', id: 8, name: 'Bernard', }, { email: 'simon.pierre@gmail.com', firstname: 'Simon', id: 9, name: 'Pierre', }, { email: 'michel.souris@gmail.com', firstname: 'Michel', id: 10, name: 'Souris', }, { email: 'amandine.jabot@gmail.com', firstname: 'Amandine', id: 11, name: 'Jabot', }, ] export const Default: Story = { args: { items, title: 'Exemple de liste de résultats', uniqueId: 'amelipro-result-list-id', }, parameters: { sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, render: args => ({ components: { AmeliproResultList, AmeliproCard }, setup() { return { args } }, template: `
`, }), } // --- Pagination et tri (avec gestion de l'événement de tri) --- export const PaginationEtTri: Story = { name: 'Pagination et tri', args: { items, uniqueId: 'amelipro-result-list-pagination', title: 'Avec pagination et tri', itemsToDisplayDesktop: 4, itemsToDisplayMobile: 2, sortSelectDefaultValue: 'desc', sortSelectItems: [ { title: 'Nom croissant', value: 'asc' }, { title: 'Nom décroissant', value: 'desc' }, ], sortSelectLabel: 'Trier par :', sortSelectPlaceholder: 'Choisir un ordre', }, parameters: { sourceCode: [ { name: 'Template', code: ``, }, { name: 'Script', code: ``, }, ], }, render: args => ({ components: { AmeliproResultList, AmeliproCard }, setup() { const sortOrder = ref<'asc' | 'desc'>('asc') const sortedItems = computed(() => [...(args.items ?? [])].sort((a, b) => sortOrder.value === 'asc' ? String(a.name).localeCompare(String(b.name)) : String(b.name).localeCompare(String(a.name)), ), ) function onSortChange(val: 'asc' | 'desc') { sortOrder.value = val } return { args, sortedItems, onSortChange } }, template: `

Pagination et tri sont activés grâce aux props itemsToDisplayDesktop, itemsToDisplayMobile et sortSelectItems. Le tri est effectif grâce à la gestion de l’événement change:sort-select.

`, }), } // --- Slot individuel pour un résultat --- export const ResultatIndividuel: Story = { name: 'Résultat individuel', args: { items, uniqueId: 'amelipro-result-list-individuel', title: 'Slot individuel', }, parameters: { sourceCode: [ { name: 'Template', code: ``, }, ], }, render: args => ({ components: { AmeliproResultList, AmeliproCard }, setup() { return { args } }, template: `

Le slot result-1 permet d’ajouter un rendu spécifique pour le résultat d’id 1.

`, }), } // --- Masquage des labels --- export const LabelsCaches: Story = { name: 'Labels cachés', args: { items, uniqueId: 'amelipro-result-list-hidden-labels', title: 'Labels cachés', hiddenLabels: true, }, parameters: { sourceCode: [ { name: 'Template', code: ``, }, ], }, render: args => ({ components: { AmeliproResultList, AmeliproCard }, setup() { return { args } }, template: `

Les labels des champs select sont masqués grâce à la prop hiddenLabels.

`, }), } // --- Masquage des infos de liste --- export const SansInfosListe: Story = { name: 'Sans infos de liste', args: { items, uniqueId: 'amelipro-result-list-no-infos', title: 'Sans infos de liste', noResultListInfos: true, }, parameters: { sourceCode: [ { name: 'Template', code: ``, }, ], }, render: args => ({ components: { AmeliproResultList, AmeliproCard }, setup() { return { args } }, template: `

Les informations et filtres au-dessus de la liste sont masqués grâce à la prop noResultListInfos.

`, }), } // --- Sélection du nombre de résultats par page (paginationSelect) --- export const PaginationSelect: Story = { name: 'Sélecteur de pagination', args: { items, uniqueId: 'amelipro-result-list-pagination-select', title: 'Sélecteur de pagination', paginationSelect: true, itemsToDisplayDesktop: 3, itemsToDisplayMobile: 2, paginationSelectLabel: 'Résultats par page :', paginationSelectPlaceholder: 'Sélectionner...', }, parameters: { sourceCode: [ { name: 'Template', code: ``, }, ], }, render: args => ({ components: { AmeliproResultList, AmeliproCard }, setup() { return { args } }, template: `

Affichage du sélecteur du nombre de résultats par page grâce à la prop paginationSelect.

`, }), } // --- Compteur personnalisé --- export const CompteurPersonnalise: Story = { name: 'Compteur personnalisé', args: { items, uniqueId: 'amelipro-result-list-counter-label', title: 'Compteur personnalisé', counterLabel: 'Nombre de résultats trouvés :', }, parameters: { sourceCode: [ { name: 'Template', code: ``, }, ], }, render: args => ({ components: { AmeliproResultList, AmeliproCard }, setup() { return { args } }, template: `

Le compteur de résultats est personnalisé grâce à la prop counterLabel.

`, }), } // --- Placeholder et label personnalisés pour la pagination --- export const PaginationLabelPlaceholder: Story = { name: 'Label et placeholder pagination', args: { items, uniqueId: 'amelipro-result-list-pagination-label-placeholder', title: 'Label et placeholder pagination', paginationSelect: true, paginationSelectLabel: 'Afficher :', paginationSelectPlaceholder: 'Choisissez...', }, parameters: { sourceCode: [ { name: 'Template', code: ``, }, ], }, render: args => ({ components: { AmeliproResultList, AmeliproCard }, setup() { return { args } }, template: `

Personnalisation du label et du placeholder du select de pagination.

`, }), } // --- Liste vide --- export const ListeVide: Story = { name: 'Liste vide', args: { items: [], uniqueId: 'amelipro-result-list-empty', title: 'Aucun résultat', }, parameters: { sourceCode: [ { name: 'Template', code: ``, }, ], }, render: args => ({ components: { AmeliproResultList }, setup() { return { args } }, template: `

Affichage du composant avec une liste vide.

`, }), } // --- Slot générique sans carte --- export const ResultatSansCarte: Story = { name: 'Résultat sans carte', args: { items, uniqueId: 'amelipro-result-list-no-card', title: 'Résultat sans carte', }, parameters: { sourceCode: [ { name: 'Template', code: ``, }, ], }, render: args => ({ components: { AmeliproResultList }, setup() { return { args } }, template: `

Affichage d’un résultat personnalisé sans carte via le slot result.

`, }), } // --- Exemple combiné (toutes options) --- export const ExempleCombine: Story = { name: 'Exemple combiné', args: { items, uniqueId: 'amelipro-result-list-combine', title: 'Exemple combiné', paginationSelect: true, paginationSelectLabel: 'Résultats par page :', paginationSelectPlaceholder: 'Sélectionner...', sortSelectItems: [ { title: 'Nom croissant', value: 'asc' }, { title: 'Nom décroissant', value: 'desc' }, ], sortSelectLabel: 'Trier par :', sortSelectPlaceholder: 'Choisir un ordre', counterLabel: 'Nombre de résultats :', hiddenLabels: true, noResultListInfos: true, itemsToDisplayDesktop: 3, itemsToDisplayMobile: 2, }, parameters: { sourceCode: [ { name: 'Template', code: ``, }, ], }, render: args => ({ components: { AmeliproResultList }, setup() { return { args } }, template: `

Exemple combinant tri, pagination, labels cachés, infos masquées et slot individuel.

`, }), }