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: `
Filtre personnalisé :
{
// Utiliser la fonction updateFilter fournie par le slot
updateFilter(val)
}"
/>
`,
},
{
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: `
Filtre personnalisé :
{
updateFilter(val);
handleFilterChange(val);
}"
/>
`,
}),
}
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: `
`,
}),
}