import type { Meta, StoryObj } from '@storybook/vue3'
import PaginatedTable from './PaginatedTable.vue'
import { StateEnum } from './constants/StateEnum'
import type { DataOptions } from './types'
import { ref } from 'vue'
import type { VDataTable } from 'vuetify/components'
import { createDeprecationNotice } from '@/stories/DeprecationNotice/DeprecationNotice'
interface User {
[key: string]: string
firstname: string
lastname: string
email: string
}
interface DataObj {
items: User[]
total: number
}
const meta = {
title: 'Composants/Tableaux/PaginatedTable',
component: PaginatedTable,
decorators: [
() => ({
template: '
',
}),
],
parameters: {
layout: 'fullscreen',
},
argTypes: {
headers: {
description: 'Liste des colonnes du tableau',
control: { type: 'object' },
table: {
category: 'props',
},
},
items: {
description: 'Liste des éléments à afficher dans le tableau',
control: { type: 'object' },
table: {
category: 'props',
},
},
options: {
description: 'Options de configuration du tableau',
name: 'v-model:options',
control: { type: 'object' },
table: {
category: 'props',
},
},
serverItemsLength: {
description: 'Nombre total d\'éléments à afficher',
control: { type: 'number' },
},
suffix: {
description: 'Suffixe permettant de gérer individuellement le stockage des options d’un tableau d’une page à l’autre. S’il n’est pas renseigné, le stockage s’effectue globalement pour tous les tableaux.',
control: { type: 'text' },
},
itemsPerPage: {
description: 'Nombre d\'éléments par page',
control: { type: 'number' },
},
caption: {
description: 'Texte de la légende du tableau',
control: { type: 'text' },
},
multiSort: {
description: 'Permet de trier sur plusieurs colonnes simultanément. Lorsque activé, des indicateurs numériques apparaissent à côté des icônes de tri pour montrer l\'ordre de priorité.',
control: { type: 'boolean' },
table: {
category: 'props',
type: { summary: 'boolean' },
defaultValue: {
summary: 'false',
},
},
},
mustSort: {
description: 'Force au moins une colonne à être toujours triée. Si désactivé, toutes les colonnes peuvent être non triées.',
control: { type: 'boolean' },
table: {
category: 'props',
type: { summary: 'boolean' },
defaultValue: {
summary: 'false',
},
},
},
},
} satisfies Meta
export default meta
type Story = StoryObj
export const Default: Story = {
parameters: {
sourceCode: [
{
name: 'Template',
code: `
`,
},
{
name: 'Script',
code: `
`,
},
],
},
args: {
// @ts-expect-error - props of VDataTable
headers: [
{
title: 'Nom',
key: 'lastname',
},
{
title: 'Prénom',
key: 'firstname',
},
{
title: 'Email',
value: 'email',
},
],
items: [
{
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: 'Thierry',
lastname: 'Bobu',
email: 'thierry.bobu@example.com',
},
{
firstname: 'Bernadette',
lastname: 'Langelier',
email: 'bernadette.langelier@exemple.com',
},
{
firstname: 'Agate',
lastname: 'Roy',
email: 'agate.roy@exemple.com',
},
],
caption: 'Liste des utilisateurs',
options: {
itemsPerPage: 4,
},
},
render: (args) => {
return {
components: { PaginatedTable },
setup() {
return { args }
},
template: `
`,
}
},
}
export const SortBy: Story = {
parameters: {
sourceCode: [
{
name: 'Template',
code: `
`,
},
{
name: 'Script',
code: `
`,
},
],
},
args: {
// @ts-expect-error - props of VDataTable
headers: [
{
title: 'Nom',
key: 'lastname',
},
{
title: 'Prénom',
key: 'firstname',
},
{
title: 'Email',
value: 'email',
},
],
items: [
{
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: 'Thierry',
lastname: 'Bobu',
email: 'thierry.bobu@example.com',
},
{
firstname: 'Bernadette',
lastname: 'Langelier',
email: 'bernadette.langelier@exemple.com',
},
{
firstname: 'Agate',
lastname: 'Roy',
email: 'agate.roy@exemple.com',
},
],
caption: 'Liste des utilisateurs',
options: {
sortBy: [{ key: 'lastname', order: 'desc' }],
},
},
render: (args) => {
return {
components: { PaginatedTable },
setup() {
return { args }
},
template: `
`,
}
},
}
export const TableServer: Story = {
parameters: {
a11y: {
disable: true,
},
sourceCode: [
{
name: 'Template',
code: `
`,
},
{
name: 'Script',
code: `
`,
},
],
},
args: {
options: {
itemsPerPage: 5,
sortBy: [{ key: 'lastname', order: 'asc' }],
page: 1,
},
caption: 'Liste des utilisateurs',
},
render: (args) => {
return {
components: { PaginatedTable },
setup() {
const totalUsers = ref(0)
const users = ref([])
const state = ref(StateEnum.IDLE)
const options = ref({
itemsPerPage: 5,
sortBy: [{ key: 'lastname', order: 'asc' }],
page: 1,
})
const headers = [
{ title: 'Nom', key: 'lastname' },
{ title: 'Prénom', key: 'firstname' },
{ title: 'Email', key: 'email' },
]
const fetchData = async (): Promise => {
// @ts-expect-error - fetchData is not defined
const { items, total } = await getDataFromApi(options.value)
users.value = items
totalUsers.value = total
console.log(users.value, totalUsers.value)
}
const wait = async (ms: number) => {
return new Promise(resolve => setTimeout(resolve, ms))
}
const getDataFromApi = async ({ sortBy, page, itemsPerPage }: DataOptions): Promise => {
state.value = StateEnum.PENDING
await wait(1000)
return new Promise((resolve) => {
let items: User[] = getUsers()
const total = items.length
if (sortBy && sortBy.length > 0) {
items = items.sort((a, b) => {
const key = sortBy[0]!.key
const order = sortBy[0]!.order === 'asc' ? 1 : -1
return a[key]! > b[key]! ? order : -order
})
}
if (itemsPerPage > 0) {
items = items.slice((page - 1) * itemsPerPage, page * itemsPerPage)
}
resolve({ items, total })
state.value = StateEnum.RESOLVED
})
}
const getUsers = (): User[] => {
return [
{ 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: 'Serge', lastname: 'Rivard', email: 'serge.rivard@example.com' },
{ firstname: 'Jacques', lastname: 'Demers', email: 'jacques.demers@example.com' },
{ firstname: 'Aimée', lastname: 'Josseaume', email: 'aimee.josseaume@example.com' },
{ firstname: 'Delphine', lastname: 'Robillard', email: 'delphine.robillard@example.com' },
{ firstname: 'Alexandre', lastname: 'Lazure', email: 'alexandre.lazure@example.com' },
]
}
return { args, headers, users, options, state, fetchData, totalUsers, StateEnum }
},
template: `
`,
}
},
}
export const ManyTables: Story = {
parameters: {
a11y: {
disable: true,
},
sourceCode: [
{
name: 'Template',
code: `
`,
},
{
name: 'Script',
code: `
`,
},
],
},
args: {
options: {
itemsPerPage: 5,
page: 1,
},
caption: 'Liste des utilisateurs',
},
render: (args) => {
return {
components: { PaginatedTable },
setup() {
const itemsTable1 = ref([
{
id: 1,
lastname: 'Doe',
firstname: 'John',
},
{
id: 2,
lastname: 'Smith',
firstname: 'Jane',
},
{
id: 3,
lastname: 'Brown',
firstname: 'Charlie',
},
])
const itemsTable2 = ref([
{
id: 1,
lastname: 'Smith',
firstname: 'Jane',
},
{
id: 2,
lastname: 'Doe',
firstname: 'John',
},
{
id: 3,
lastname: 'Brown',
firstname: 'Charlie',
},
])
return { args, itemsTable1, itemsTable2 }
},
template: `
`,
}
},
}
export const DeprecationNotice = {
...createDeprecationNotice([
{ label: 'SyTable', url: '?path=/docs/composants-tableaux-sytable--docs' },
]),
tags: ['!dev'],
}