import type { Meta, StoryObj } from '@storybook/vue3-vite' import { ref } from 'vue' import dayjs from 'dayjs' import type { VDataTable } from 'vuetify/components' import SyServerTable from './SyServerTable.vue' import { commonTableArgTypes, commonTableEventArgs } from '../common/storyArgTypes' import type { FilterOption, FilterType } from '../common/types' import { useServerTableDemo } from '../common/serverStoryHelpers' const meta = { title: 'Composants/Tableaux/SyServerTable/Filtres', component: SyServerTable, decorators: [ () => ({ template: '
', }), ], parameters: { layout: 'fullscreen', }, argTypes: { ...commonTableArgTypes, items: { description: 'Liste des éléments à afficher dans le tableau', control: { type: 'object' }, table: { category: 'props', defaultValue: { summary: 'undefined', }, }, }, serverItemsLength: { description: 'Nombre total d\'éléments à afficher', control: { type: 'number' }, }, }, } satisfies Meta export default meta type Story = StoryObj const serverFilterUsers: Record[] = [ { firstname: 'Virginie', lastname: 'Beauchesne', email: 'virginie.beauchesne@example.com' }, { firstname: 'Simone', lastname: 'Bellefeuille', email: 'simone.bellefeuille@example.com' }, { firstname: 'Étienne', lastname: 'Salois', email: 'etienne.salois@example.com' }, { firstname: 'Bernadette', lastname: 'Langelier', email: 'bernadette.langelier@example.com' }, { firstname: 'Agate', lastname: 'Roy', email: 'agate.roy@example.com' }, { firstname: 'Louis', lastname: 'Denis', email: 'louis.denis@example.com' }, { firstname: 'Édith', lastname: 'Cartier', email: 'edith.cartier@example.com' }, { firstname: 'Alphonse', lastname: 'Bouvier', email: 'alphonse.bouvier@example.com' }, { firstname: 'Eustache', lastname: 'Dubois', email: 'eustache.dubois@example.com' }, { firstname: 'Rosemarie', lastname: 'Quessy', email: 'rosemarie.quessy@example.com' }, { firstname: 'Martin', lastname: 'Lavoie', email: 'martin.lavoie@example.com' }, { firstname: 'Céline', lastname: 'Tremblay', email: 'celine.tremblay@example.com' }, { firstname: 'Jacques', lastname: 'Gagnon', email: 'jacques.gagnon@example.com' }, { firstname: 'Isabelle', lastname: 'Côté', email: 'isabelle.cote@example.com' }, { firstname: 'Philippe', lastname: 'Bouchard', email: 'philippe.bouchard@example.com' }, ] const serverFilterNumberUsers: Record[] = [ { name: 'Jean Dupont', age: 32, salary: 45000 }, { name: 'Marie Martin', age: 28, salary: 52000 }, { name: 'Pierre Durand', age: 45, salary: 65000 }, { name: 'Sophie Petit', age: 36, salary: 48000 }, { name: 'Thomas Leroy', age: 41, salary: 58000 }, { name: 'Julie Bernard', age: 29, salary: 47000 }, { name: 'Nicolas Moreau', age: 38, salary: 61000 }, { name: 'Camille Dubois', age: 33, salary: 49000 }, { name: 'Alexandre Lefebvre', age: 44, salary: 67000 }, { name: 'Émilie Girard', age: 31, salary: 51000 }, { name: 'Lucas Roux', age: 39, salary: 59000 }, { name: 'Chloé Lambert', age: 27, salary: 46000 }, { name: 'Maxime Simon', age: 42, salary: 63000 }, { name: 'Laura Fournier', age: 35, salary: 54000 }, { name: 'Antoine Mercier', age: 40, salary: 60000 }, ] const serverFilterSelectUsers: Record[] = [ { name: 'Jean Dupont', department: 'RH', status: 'Actif' }, { name: 'Marie Martin', department: 'IT', status: 'En congé' }, { name: 'Pierre Durand', department: 'Finance', status: 'Actif' }, { name: 'Sophie Petit', department: 'Marketing', status: 'Actif' }, { name: 'Thomas Leroy', department: 'IT', status: 'Inactif' }, { name: 'Julie Bernard', department: 'RH', status: 'Actif' }, { name: 'Nicolas Moreau', department: 'Finance', status: 'En congé' }, { name: 'Camille Dubois', department: 'Marketing', status: 'Inactif' }, { name: 'Alexandre Lefebvre', department: 'IT', status: 'Actif' }, { name: 'Émilie Girard', department: 'RH', status: 'En congé' }, { name: 'Lucas Roux', department: 'Finance', status: 'Actif' }, { name: 'Chloé Lambert', department: 'Marketing', status: 'Actif' }, { name: 'Maxime Simon', department: 'IT', status: 'Inactif' }, { name: 'Laura Fournier', department: 'RH', status: 'Actif' }, { name: 'Antoine Mercier', department: 'Finance', status: 'En congé' }, ] const serverFilterAutocompleteUsers: Record[] = [ { name: 'Jean Dupont', department: 'RH', status: 'Actif' }, { name: 'Marie Martin', department: 'IT', status: 'En congé' }, { name: 'Pierre Durand', department: 'Finance', status: 'Actif' }, { name: 'Sophie Petit', department: 'Marketing', status: 'Actif' }, { name: 'Thomas Leroy', department: 'IT', status: 'Inactif' }, ] const serverFilterDateUsers: Record[] = [ { name: 'Jean-Pierre Dubois', hireDate: dayjs('2025-05-15').format('DD/MM/YYYY') }, { name: 'Marie-Claire Lefèvre', hireDate: dayjs('2025-03-10').format('DD/MM/YYYY') }, { name: 'François Moreau', hireDate: dayjs('2025-11-22').format('DD/MM/YYYY') }, { name: 'Céline Rousseau', hireDate: dayjs('2025-01-08').format('DD/MM/YYYY') }, { name: 'Thierry Bertrand', hireDate: dayjs('2025-07-30').format('DD/MM/YYYY') }, ] const serverCustomFilterUsers: Record[] = [ { firstname: 'Virginie', lastname: 'Beauchesne', status: 'Actif' }, { firstname: 'Simone', lastname: 'Bellefeuille', status: 'Inactif' }, { firstname: 'Étienne', lastname: 'Salois', status: 'En attente' }, { firstname: 'Thierry', lastname: 'Bobu', status: 'Actif' }, { firstname: 'Bernadette', lastname: 'Langelier', status: 'Inactif' }, { firstname: 'Agate', lastname: 'Roy', status: 'En attente' }, ] export const ServerFilterByText: Story = { parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { serverItemsLength: 15, headers: [ { title: 'Prénom', key: 'firstname', filterable: true, filterType: 'text', }, { title: 'Nom', key: 'lastname', filterable: true, filterType: 'text', }, { title: 'Email', key: 'email', filterable: true, filterType: 'text', }, ], caption: '', options: { itemsPerPage: 5, page: 1, filters: [], }, showFilters: true, suffix: 'server-filter-text', density: 'default', striped: false, ...commonTableEventArgs(), }, render: args => ({ components: { SyServerTable }, setup() { const { items, totalItems, state, options, fetchData, StateEnum } = useServerTableDemo(args, serverFilterUsers) return { args, items, totalItems, state, options, fetchData, StateEnum } }, template: ` `, }), } export const ServerFilterByNumber: Story = { parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { headers: [ { title: 'Nom', key: 'name', filterable: true, filterType: 'text', }, { title: 'Âge', key: 'age', filterable: true, filterType: 'number', }, { title: 'Salaire', key: 'salary', filterable: true, filterType: 'number', }, ], caption: '', options: { itemsPerPage: 5, page: 1, filters: [], }, serverItemsLength: 15, showFilters: true, suffix: 'server-filter-number', density: 'default', striped: false, ...commonTableEventArgs(), }, render: args => ({ components: { SyServerTable }, setup() { const { items, totalItems, state, options, fetchData, StateEnum } = useServerTableDemo(args, serverFilterNumberUsers) return { args, items, totalItems, state, options, fetchData, StateEnum } }, template: ` `, }), } export const ServerFilterBySelect: Story = { parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { headers: [ { title: 'Nom', key: 'name', filterable: true, filterType: 'text', }, { title: 'Département', key: 'department', filterable: true, filterType: 'select', multiple: false, chips: false, hideMessages: true, filterOptions: [ { text: 'RH', value: 'RH' }, { text: 'IT', value: 'IT' }, { text: 'Finance', value: 'Finance' }, { text: 'Marketing', value: 'Marketing' }, ], }, { title: 'Statut', key: 'status', filterable: true, filterType: 'select', multiple: false, chips: false, hideMessages: true, filterOptions: [ { text: 'Actif', value: 'Actif' }, { text: 'En congé', value: 'En congé' }, { text: 'Inactif', value: 'Inactif' }, ], }, ], caption: '', options: { itemsPerPage: 5, page: 1, filters: [], }, serverItemsLength: 15, showFilters: true, suffix: 'server-filter-select', density: 'default', striped: false, ...commonTableEventArgs(), }, render: args => ({ components: { SyServerTable }, setup() { const { items, totalItems, state, options, fetchData, StateEnum } = useServerTableDemo(args, serverFilterSelectUsers) return { args, items, totalItems, state, options, fetchData, StateEnum } }, template: ` `, }), } export const ServerFilterBySelectMultiple: Story = { parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { headers: [ { title: 'Nom', key: 'name', filterable: true, filterType: 'text', }, { title: 'Département', key: 'department', filterable: true, filterType: 'select', multiple: true, chips: true, hideMessages: true, filterOptions: [ { text: 'RH', value: 'RH' }, { text: 'IT', value: 'IT' }, { text: 'Finance', value: 'Finance' }, { text: 'Marketing', value: 'Marketing' }, ], }, { title: 'Statut', key: 'status', filterable: true, filterType: 'select', multiple: true, chips: true, hideMessages: true, filterOptions: [ { text: 'Actif', value: 'Actif' }, { text: 'En congé', value: 'En congé' }, { text: 'Inactif', value: 'Inactif' }, ], }, ], caption: '', options: { itemsPerPage: 5, page: 1, filters: [], }, serverItemsLength: 15, showFilters: true, suffix: 'server-filter-select', density: 'default', striped: false, ...commonTableEventArgs(), }, render: args => ({ components: { SyServerTable }, setup() { const { items, totalItems, state, options, fetchData, StateEnum } = useServerTableDemo(args, serverFilterSelectUsers) return { args, items, totalItems, state, options, fetchData, StateEnum } }, template: ` `, }), } export const ServerFilterByAutocomplete: Story = { parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { headers: [ { title: 'Nom', key: 'name', filterable: true, filterType: 'text' as FilterType, }, { title: 'Département', key: 'department', filterable: true, filterType: 'autocomplete' as FilterType, filterOptions: [ { text: 'RH', value: 'RH' }, { text: 'IT', value: 'IT' }, { text: 'Finance', value: 'Finance' }, { text: 'Marketing', value: 'Marketing' }, ], }, { title: 'Statut', key: 'status', filterable: true, filterType: 'autocomplete' as FilterType, multiple: true, chips: true, filterOptions: [ { text: 'Actif', value: 'Actif' }, { text: 'En congé', value: 'En congé' }, { text: 'Inactif', value: 'Inactif' }, ], }, ], serverItemsLength: 0, suffix: 'server-filter-autocomplete', showFilters: true, ...commonTableEventArgs(), }, render: args => ({ components: { SyServerTable }, setup() { const { items, totalItems, state, options, fetchData, StateEnum } = useServerTableDemo(args, serverFilterAutocompleteUsers) return { args, items, totalItems, state, options, fetchData, StateEnum } }, template: ` `, }), } export const ServerFilterByExacteDate: Story = { parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { serverItemsLength: 5, showFilters: true, headers: [ { title: 'Nom', key: 'name', filterable: true, filterType: 'text', }, { title: 'Date d\'embauche', key: 'hireDate', filterable: true, filterType: 'date', dateFormat: 'DD/MM/YYYY', }, ], options: { itemsPerPage: 5, page: 1, filters: [], }, caption: '', suffix: 'server-filter-date', density: 'default', striped: false, ...commonTableEventArgs(), }, render: args => ({ components: { SyServerTable }, setup() { const { items, totalItems, state, options, fetchData, StateEnum } = useServerTableDemo(args, serverFilterDateUsers) return { args, items, totalItems, state, options, fetchData, StateEnum } }, template: ` `, }), } export const ServerFilterByPeriod: Story = { parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { serverItemsLength: 5, showFilters: true, headers: [ { title: 'Nom', key: 'name', filterable: true, filterType: 'text', }, { title: 'Date d\'embauche', key: 'hireDate', filterable: true, filterType: 'period', dateFormat: 'DD/MM/YYYY', }, ], options: { itemsPerPage: 5, page: 1, filters: [], }, caption: '', suffix: 'server-filter-date', density: 'default', striped: false, ...commonTableEventArgs(), }, render: args => ({ components: { SyServerTable }, setup() { const { items, totalItems, state, options, fetchData, StateEnum } = useServerTableDemo(args, serverFilterDateUsers) return { args, items, totalItems, state, options, fetchData, StateEnum } }, template: ` `, }), } export const CustomFilterSlot: Story = { parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, { name: 'Style', code: ` `, }, ], }, args: { serverItemsLength: 6, headers: [ { title: 'Nom', key: 'lastname', filterable: true, filterType: 'text', }, { title: 'Prénom', key: 'firstname', filterable: true, filterType: 'text', }, { title: 'Statut', key: 'status', filterable: true, filterType: 'custom' as FilterType, }, ], items: [ { firstname: 'Virginie', lastname: 'Beauchesne', status: 'Actif', }, { firstname: 'Simone', lastname: 'Bellefeuille', status: 'Inactif', }, { firstname: 'Étienne', lastname: 'Salois', status: 'En attente', }, { firstname: 'Thierry', lastname: 'Bobu', status: 'Actif', }, { firstname: 'Bernadette', lastname: 'Langelier', status: 'Inactif', }, { firstname: 'Agate', lastname: 'Roy', status: 'En attente', }, ], caption: '', options: { itemsPerPage: 4, page: 1, filters: [], }, showFilters: true, suffix: 'server-custom-filter-slot', density: 'default', striped: false, ...commonTableEventArgs(), }, render: args => ({ components: { SyServerTable }, setup() { const { items, totalItems, state, options, fetchData, StateEnum } = useServerTableDemo(args, serverCustomFilterUsers) const customFilterValue = ref('') const statusOptions = ['Actif', 'Inactif', 'En attente'] // Synchronise l'état local du filtre personnalisé dans options.filters function handleFilterChange(val: string) { if (!options.value.filters) { options.value.filters = [] } const currentFilters = options.value.filters as FilterOption[] const newFilters = [...currentFilters].filter(f => f.key !== 'status') if (val) { newFilters.push({ key: 'status', value: val, type: 'select' as FilterType, }) } options.value = { ...options.value, filters: newFilters, } } return { args, items, totalItems, state, options, fetchData, StateEnum, customFilterValue, statusOptions, handleFilterChange } }, template: ` `, }), } export const CustomFilterInputs: Story = { parameters: { a11y: { disable: true, }, sourceCode: [ { name: 'Template', code: ` `, }, { name: 'Script', code: ` `, }, ], }, args: { serverItemsLength: 15, headers: [ { title: 'Prénom', key: 'firstname', filterable: true, filterType: 'text', }, { title: 'Nom', key: 'lastname', filterable: true, filterType: 'text', }, { title: 'Email', key: 'email', filterable: true, filterType: 'text', }, ], caption: '', options: { itemsPerPage: 5, page: 1, filters: [], }, filterInputConfig: { variant: 'outlined', density: 'comfortable', hideDetails: true, clearable: false, disableErrorHandling: true, }, showFilters: true, suffix: 'server-filter-text', density: 'default', striped: false, ...commonTableEventArgs(), }, render: args => ({ components: { SyServerTable }, setup() { const { items, totalItems, state, options, fetchData, StateEnum } = useServerTableDemo(args, serverFilterUsers) return { args, items, totalItems, state, options, fetchData, StateEnum } }, template: ` `, }), }