import type { Meta, StoryObj } from '@storybook/vue3-vite' import TableToolbar from './TableToolbar.vue' import SySelect from '@/components/Customs/Selects/SySelect/SySelect.vue' import { ref, computed } from 'vue' import { fn } from 'storybook/test' import SyTable from '@/components/Tables/SyTable/SyTable.vue' const meta = { title: 'Composants/Tableaux/TableToolbar', component: TableToolbar, argTypes: { 'locales': { description: 'Surcharge des chaînes affichées à l\'utilisateur (libellés de la barre d\'outils : recherche, ajout, compteur de lignes). Les valeurs par défaut sont définies dans le fichier `locales.ts` du composant. La prop accepte un objet partiel : seules les clés renseignées surchargent les valeurs par défaut, le reste est conservé.', control: 'object', table: { type: { summary: 'object', detail: `{ rowText: (lignes: string, plural: boolean) => string, search: string, addBtnLabel: string, }` }, category: 'props', }, }, 'nbTotal': { description: 'Le nombre total de résultats', type: 'number', control: { type: 'number', }, table: { category: 'props', }, }, 'nbFiltered': { description: 'Le nombre de résultats filtrés.', type: 'number', control: { type: 'number', }, }, 'search': { description: 'La valeur du champ de recherche', type: 'string', control: { type: 'text', }, }, 'searchLabel': { description: 'Le label du champ de recherche', type: 'string', control: { type: 'text', }, defaultValue: 'Rechercher', }, 'showAddButton': { description: 'Affiche le bouton d\'ajout', type: 'boolean', control: { type: 'boolean', }, }, 'addButtonLabel': { description: 'Le label du bouton d\'ajout', type: 'string', control: { type: 'text', }, defaultValue: 'Ajouter', }, 'loading': { description: 'Désactive les éléments interactifs', type: 'boolean', control: { type: 'boolean', }, defaultValue: false, }, 'vuetifyOptions': { control: 'object', description: 'Personnalisation des composants Vuetify internes', table: { category: 'props', defaultValue: { summary: 'object', detail: ` { toolbar: { flat: true, color: '#FFFFFF', height: 'auto', minHeight: '56px', class: 'd-flex', }, addBtn: { variant: 'outlined', color: 'primary', class: 'my-1 px-2 px-md-4', minWidth: '44px', }, addIconLabel: { class: 'mr-1', }, textField: { variant: 'underlined', clearable: true, singleLine: true, hideDetails: true, }, }`, }, }, }, 'filters': { control: 'text', description: 'Slot pour ajouter des filtres', }, 'searchLeft': { control: 'text', description: 'Slot pour le contenu à gauche du champ de recherche', }, 'searchRight': { control: 'text', description: 'Slot pour le contenu à droite du champ de recherche', }, 'onAdd': { description: 'Événement émis lors du clic sur le bouton d\'ajout', table: { category: 'events', }, }, 'onUpdate:search': { description: 'Événement émis lors de la modification du champ de recherche', table: { category: 'events', }, }, }, parameters: { controls: { exclude: ['add', 'update:search'], }, }, } satisfies Meta export default meta type Story = StoryObj const headers = [ { title: 'Nom', sortable: true, key: 'lastname', }, { title: 'Prénom', sortable: true, key: 'firstname', }, { title: 'Email', sortable: true, key: 'email', }, ] const items = [ { firstname: 'Virginie', lastname: 'Beauchesne', email: 'virginie.beauchesne@example.com', }, { firstname: 'Étienne', lastname: 'Salois', email: 'etienne.salois@example.com', }, ] const defaultVuetifyOptions = { textField: { variant: 'outlined', density: 'compact', hideDetails: true, clearable: true, }, } const createFilteredItems = (search: { value: string | undefined }) => computed(() => { if (!search.value) { return items } const value = search.value.toLowerCase() return items.filter(item => ( item.firstname.toLowerCase().includes(value) || item.lastname.toLowerCase().includes(value) || item.email.toLowerCase().includes(value) )) }) export const Default: Story = { args: { 'nbTotal': 2, 'onAdd': fn(), 'onUpdate:search': fn(), 'vuetifyOptions': defaultVuetifyOptions, }, render: args => ({ components: { TableToolbar, SyTable }, setup() { const search = ref('') const filteredItems = createFilteredItems(search) return { args, headers, items, filteredItems, search } }, template: ` `, }), parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, } export const AddButton: Story = { args: { 'nbTotal': 2, 'onAdd': fn(), 'onUpdate:search': fn(), 'vuetifyOptions': defaultVuetifyOptions, }, render: args => ({ components: { TableToolbar, SyTable }, setup() { const search = ref('') const filteredItems = createFilteredItems(search) return { args, headers, items, filteredItems, search } }, template: ` `, }), parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, } export const Labels: Story = { args: { 'nbTotal': 2, 'onAdd': fn(), 'onUpdate:search': fn(), 'showAddButton': true, 'addButtonLabel': 'Ajouter un patient', 'searchLabel': 'Rechercher un patient', 'vuetifyOptions': defaultVuetifyOptions, }, render: args => ({ components: { TableToolbar, SyTable }, setup() { const search = ref('') const filteredItems = createFilteredItems(search) return { args, headers, items, filteredItems, search } }, template: ` `, }), parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, } export const Loading: Story = { args: { 'nbTotal': 2, 'onAdd': fn(), 'onUpdate:search': fn(), 'loading': true, 'vuetifyOptions': defaultVuetifyOptions, }, render: args => ({ components: { TableToolbar, SyTable }, setup() { const search = ref('') const filteredItems = createFilteredItems(search) return { args, headers, items, filteredItems, search } }, template: ` `, }), parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, } export const NbFiltered: Story = { args: { 'nbTotal': 2, 'nbFiltered': 1, 'onAdd': fn(), 'onUpdate:search': fn(), 'vuetifyOptions': defaultVuetifyOptions, }, render: args => ({ components: { TableToolbar, SyTable }, setup() { const search = ref('') const filteredItems = createFilteredItems(search) return { args, headers, items, filteredItems, search } }, template: ` `, }), parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, } export const SlotFilters: Story = { args: { 'nbTotal': 2, 'onAdd': fn(), 'onUpdate:search': fn(), 'vuetifyOptions': defaultVuetifyOptions, }, render: args => ({ components: { TableToolbar, SySelect, SyTable }, setup() { const search = ref(undefined) const filteredItems = createFilteredItems(search) const filterItems = ref<{ text: string, value: string }[]>( items.map(item => ({ text: item.lastname, value: item.lastname, })), ) return { args, headers, items, filteredItems, filterItems, search } }, template: ` `, }), parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, } export const OtherSlots: Story = { args: { 'nbTotal': 2, 'onAdd': fn(), 'onUpdate:search': fn(), 'vuetifyOptions': defaultVuetifyOptions, }, render: args => ({ components: { TableToolbar, SyTable }, setup() { const search = ref('') const filteredItems = createFilteredItems(search) return { args, headers, items, filteredItems, search } }, template: ` `, }), parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, } export const Customization: Story = { args: { 'nbTotal': 2, 'onAdd': fn(), 'onUpdate:search': fn(), 'showAddButton': true, 'vuetifyOptions': { toolbar: { class: 'py-2', }, textField: { variant: 'outlined', density: 'compact', hideDetails: true, clearable: true, }, addBtn: { color: 'secondary', }, addIcon: { class: 'd-none', }, }, }, render: args => ({ components: { TableToolbar, SyTable }, setup() { const search = ref('') const filteredItems = createFilteredItems(search) return { args, headers, items, filteredItems, search } }, template: ` `, }), parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, }