From 8991a554d2a0d6297d860a53b6fb17de220c31e8 Mon Sep 17 00:00:00 2001 From: WillianLomeu Date: Fri, 2 Aug 2024 12:56:41 -0300 Subject: [PATCH 1/2] feat(pagination): added item per page on pagination --- src/components.d.ts | 54 ++-- src/components/grid/readme.md | 4 +- src/components/pagination/pagination.scss | 2 - src/components/pagination/pagination.tsx | 305 ++++++++++++++-------- src/components/pagination/readme.md | 40 +-- src/components/typo/readme.md | 2 + src/index.html | 7 +- 7 files changed, 269 insertions(+), 145 deletions(-) diff --git a/src/components.d.ts b/src/components.d.ts index 93458b13..1f3497f3 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -1776,6 +1776,9 @@ export namespace Components { * Data test is the prop to specifically test the component action object. */ "dataTest"?: string; + /** + * Disable state. Indicates if the component is disabled. + */ "disable"?: boolean; /** * Icon. Used to add icon in list item. @@ -1785,6 +1788,9 @@ export namespace Components { * A prop for make the nav open. */ "isOpen"?: boolean; + /** + * Loading state. Indicates if the component is in a loading state. + */ "loading"?: boolean; /** * SecondaryText. Used to insert a secondaryText in the display item. @@ -1845,35 +1851,39 @@ export namespace Components { } interface BdsPagination { /** - * Data test is the prop to specifically test the component action object. dtButtonEnd is the data-test to button end + * Propriedade de teste para especificamente testar a ação do botão final. dtButtonEnd é o data-test para o botão final. */ "dtButtonEnd"?: string; /** - * Data test is the prop to specifically test the component action object. dtButtonInitial is the data-test to button initial. + * Propriedade de teste para especificamente testar a ação do botão inicial. dtButtonInitial é o data-test para o botão inicial. */ "dtButtonInitial"?: string; /** - * Data test is the prop to specifically test the component action object. dtButtonNext is the data-test to button next. + * Propriedade de teste para especificamente testar a ação do botão de próxima página. dtButtonNext é o data-test para o botão próximo. */ "dtButtonNext"?: string; /** - * Data test is the prop to specifically test the component action object. dtButtonPrev is the data-test to button prev. + * Propriedade de teste para especificamente testar a ação do botão de página anterior. dtButtonPrev é o data-test para o botão anterior. */ "dtButtonPrev"?: string; /** - * Data test is the prop to specifically test the component action object. dtSelectNumber is the data-test to select number. + * Propriedade de teste para especificamente testar o seletor de número de páginas. dtSelectNumber é o data-test para o seletor de número de páginas. */ "dtSelectNumber"?: string; + "itemsPage"?: any; + "language"?: string; + "numberItems"?: number; /** - * Set the placement of the options menu. Can be 'bottom' or 'top'. + * Define a posição do menu de opções. Pode ser 'bottom' ou 'top'. Padrão é 'auto', que ajusta automaticamente a posição. */ "optionsPosition"?: PaginationOptionsPositionType; + "pageCounter"?: boolean; /** - * Prop to recive the number of pages. + * Propriedade para receber o número total de páginas, baseado no total de itens e itens por página. */ "pages"?: number; /** - * When the component are render this page are set. + * Propriedade que define a página inicial ao renderizar o componente. */ "startedPage"?: number; } @@ -5471,6 +5481,9 @@ declare namespace LocalJSX { * Data test is the prop to specifically test the component action object. */ "dataTest"?: string; + /** + * Disable state. Indicates if the component is disabled. + */ "disable"?: boolean; /** * Icon. Used to add icon in list item. @@ -5480,6 +5493,9 @@ declare namespace LocalJSX { * A prop for make the nav open. */ "isOpen"?: boolean; + /** + * Loading state. Indicates if the component is in a loading state. + */ "loading"?: boolean; /** * When de open or close of component change, the event are dispache. @@ -5546,39 +5562,43 @@ declare namespace LocalJSX { } interface BdsPagination { /** - * Data test is the prop to specifically test the component action object. dtButtonEnd is the data-test to button end + * Propriedade de teste para especificamente testar a ação do botão final. dtButtonEnd é o data-test para o botão final. */ "dtButtonEnd"?: string; /** - * Data test is the prop to specifically test the component action object. dtButtonInitial is the data-test to button initial. + * Propriedade de teste para especificamente testar a ação do botão inicial. dtButtonInitial é o data-test para o botão inicial. */ "dtButtonInitial"?: string; /** - * Data test is the prop to specifically test the component action object. dtButtonNext is the data-test to button next. + * Propriedade de teste para especificamente testar a ação do botão de próxima página. dtButtonNext é o data-test para o botão próximo. */ "dtButtonNext"?: string; /** - * Data test is the prop to specifically test the component action object. dtButtonPrev is the data-test to button prev. + * Propriedade de teste para especificamente testar a ação do botão de página anterior. dtButtonPrev é o data-test para o botão anterior. */ "dtButtonPrev"?: string; /** - * Data test is the prop to specifically test the component action object. dtSelectNumber is the data-test to select number. + * Propriedade de teste para especificamente testar o seletor de número de páginas. dtSelectNumber é o data-test para o seletor de número de páginas. */ "dtSelectNumber"?: string; + "itemsPage"?: any; + "language"?: string; + "numberItems"?: number; /** - * When de value of component change, the event are dispache. + * Evento emitido quando o valor da página atual é alterado. Pode ser escutado para realizar ações específicas ao mudar de página. */ "onBdsPaginationChange"?: (event: BdsPaginationCustomEvent) => void; /** - * Set the placement of the options menu. Can be 'bottom' or 'top'. + * Define a posição do menu de opções. Pode ser 'bottom' ou 'top'. Padrão é 'auto', que ajusta automaticamente a posição. */ "optionsPosition"?: PaginationOptionsPositionType; + "pageCounter"?: boolean; /** - * Prop to recive the number of pages. + * Propriedade para receber o número total de páginas, baseado no total de itens e itens por página. */ "pages"?: number; /** - * When the component are render this page are set. + * Propriedade que define a página inicial ao renderizar o componente. */ "startedPage"?: number; } diff --git a/src/components/grid/readme.md b/src/components/grid/readme.md index bb02dd9b..482e80d8 100644 --- a/src/components/grid/readme.md +++ b/src/components/grid/readme.md @@ -22,7 +22,7 @@ | `margin` | `margin` | | `"none" \| "half" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "10" \| "11" \| "12" \| "l-none" \| "l-half" \| "l-1" \| "l-2" \| "l-3" \| "l-4" \| "l-5" \| "l-6" \| "l-7" \| "l-8" \| "l-9" \| "l-10" \| "l-11" \| "l-12" \| "b-none" \| "b-half" \| "b-1" \| "b-2" \| "b-3" \| "b-4" \| "b-5" \| "b-6" \| "b-7" \| "b-8" \| "b-9" \| "b-10" \| "b-11" \| "r-none" \| "r-half" \| "r-1" \| "r-2" \| "r-3" \| "r-4" \| "r-5" \| "r-6" \| "r-7" \| "r-8" \| "r-9" \| "r-10" \| "r-11" \| "r-12" \| "t-none" \| "t-half" \| "t-1" \| "t-2" \| "t-3" \| "t-4" \| "t-5" \| "t-6" \| "t-7" \| "t-8" \| "t-9" \| "t-10" \| "t-11" \| "t-12" \| "y-none" \| "y-half" \| "y-1" \| "y-2" \| "y-3" \| "y-4" \| "y-5" \| "y-6" \| "y-7" \| "y-8" \| "y-9" \| "y-10" \| "y-11" \| "y-12" \| "x-none" \| "x-half" \| "x-1" \| "x-2" \| "x-3" \| "x-4" \| "x-5" \| "x-6" \| "x-7" \| "x-8" \| "x-9" \| "x-10" \| "x-11" \| "x-12"` | `undefined` | | `md` | `md` | | `"1" \| "10" \| "11" \| "12" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "auto"` | `undefined` | | `mdOffset` | `md-offset` | | `"1" \| "10" \| "11" \| "12" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "auto"` | `undefined` | -| `padding` | `padding` | | `"none" \| "half" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "10" \| "11" \| "12" \| "l-none" \| "l-half" \| "l-1" \| "l-2" \| "l-3" \| "l-4" \| "l-5" \| "l-6" \| "l-7" \| "l-8" \| "l-9" \| "l-10" \| "l-11" \| "l-12" \| "b-none" \| "b-half" \| "b-1" \| "b-2" \| "b-3" \| "b-4" \| "b-5" \| "b-6" \| "b-7" \| "b-8" \| "b-9" \| "b-10" \| "b-11" \| "b-12" \| "r-none" \| "r-half" \| "r-1" \| "r-2" \| "r-3" \| "r-4" \| "r-5" \| "r-6" \| "r-7" \| "r-8" \| "r-9" \| "r-10" \| "r-11" \| "r-12" \| "t-none" \| "t-half" \| "t-1" \| "t-2" \| "t-3" \| "t-4" \| "t-5" \| "t-6" \| "t-7" \| "t-8" \| "t-9" \| "t-10" \| "t-11" \| "t-12" \| "y-none" \| "y-half" \| "y-1" \| "y-2" \| "y-3" \| "y-4" \| "y-5" \| "y-6" \| "y-7" \| "y-8" \| "y-9" \| "y-10" \| "y-11" \| "y-12" \| "x-none" \| "x-half" \| "x-1" \| "x-2" \| "x-3" \| "x-4" \| "x-5" \| "x-6" \| "x-7" \| "x-8" \| "x-9" \| "x-10" \| "x-11" \| "x-12"` | `undefined` | +| `padding` | `padding` | | `"none" \| "half" \| "1" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "10" \| "11" \| "12" \| "l-none" \| "l-half" \| "l-1" \| "l-2" \| "l-3" \| "l-4" \| "l-5" \| "l-6" \| "l-7" \| "l-8" \| "l-9" \| "l-10" \| "l-11" \| "l-12" \| "b-none" \| "b-half" \| "b-1" \| "b-2" \| "b-3" \| "b-4" \| "b-5" \| "b-6" \| "b-7" \| "b-8" \| "b-9" \| "b-10" \| "b-11" \| "r-none" \| "r-half" \| "r-1" \| "r-2" \| "r-3" \| "r-4" \| "r-5" \| "r-6" \| "r-7" \| "r-8" \| "r-9" \| "r-10" \| "r-11" \| "r-12" \| "t-none" \| "t-half" \| "t-1" \| "t-2" \| "t-3" \| "t-4" \| "t-5" \| "t-6" \| "t-7" \| "t-8" \| "t-9" \| "t-10" \| "t-11" \| "t-12" \| "y-none" \| "y-half" \| "y-1" \| "y-2" \| "y-3" \| "y-4" \| "y-5" \| "y-6" \| "y-7" \| "y-8" \| "y-9" \| "y-10" \| "y-11" \| "y-12" \| "x-none" \| "x-half" \| "x-1" \| "x-2" \| "x-3" \| "x-4" \| "x-5" \| "x-6" \| "x-7" \| "x-8" \| "x-9" \| "x-10" \| "x-11" \| "x-12" \| "b-12"` | `undefined` | | `sm` | `sm` | | `"1" \| "10" \| "11" \| "12" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "auto"` | `undefined` | | `smOffset` | `sm-offset` | | `"1" \| "10" \| "11" \| "12" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "auto"` | `undefined` | | `xg` | `xg` | | `"1" \| "10" \| "11" \| "12" \| "2" \| "3" \| "4" \| "5" \| "6" \| "7" \| "8" \| "9" \| "auto"` | `undefined` | @@ -46,6 +46,7 @@ - [bds-carousel](../carousel) - [bds-datepicker](../datepicker) - [bds-list-item-content](../list) + - [bds-pagination](../pagination) - [bds-skeleton](../skeleton) - [bds-tab-group](../tabs) - [bds-test-component](../test-component) @@ -62,6 +63,7 @@ graph TD; bds-carousel --> bds-grid bds-datepicker --> bds-grid bds-list-item-content --> bds-grid + bds-pagination --> bds-grid bds-skeleton --> bds-grid bds-tab-group --> bds-grid bds-test-component --> bds-grid diff --git a/src/components/pagination/pagination.scss b/src/components/pagination/pagination.scss index f00c1e34..9f6b8a51 100644 --- a/src/components/pagination/pagination.scss +++ b/src/components/pagination/pagination.scss @@ -5,8 +5,6 @@ display: block; .actions { - display: flex; - gap: 8px; &_select { width: 74px; diff --git a/src/components/pagination/pagination.tsx b/src/components/pagination/pagination.tsx index 77baf544..d4ad420b 100644 --- a/src/components/pagination/pagination.tsx +++ b/src/components/pagination/pagination.tsx @@ -7,72 +7,111 @@ export type PaginationOptionsPositionType = 'auto' | 'top' | 'bottom'; shadow: true, }) export class Pagination { - @Element() private el!: HTMLElement; - /** - * State for keep the value selected on select: - */ - @State() value: number = this.startedPage; - /** - * State for keep if the select are open or close; - */ - @State() openSelect: boolean; - /** - * State for recive and save the number of pages. - */ - @State() paginationNumbers = []; - - @State() intoView?: HTMLElement = null; - - /** - * Prop to recive the number of pages. - */ - @Prop() pages?: number; - /** - * When the component are render this page are set. - */ - @Prop() startedPage?: number; - /** - * Set the placement of the options menu. Can be 'bottom' or 'top'. - */ - @Prop() optionsPosition?: PaginationOptionsPositionType = 'auto'; - - /** - * Data test is the prop to specifically test the component action object. - * dtButtonInitial is the data-test to button initial. - */ - @Prop() dtButtonInitial?: string = null; - - /** - * Data test is the prop to specifically test the component action object. - * dtButtonPrev is the data-test to button prev. - */ - @Prop() dtButtonPrev?: string = null; - - /** - * Data test is the prop to specifically test the component action object. - * dtSelectNumber is the data-test to select number. - */ - @Prop() dtSelectNumber?: string = null; - - /** - * Data test is the prop to specifically test the component action object. - * dtButtonNext is the data-test to button next. - */ - @Prop() dtButtonNext?: string = null; - - /** - * Data test is the prop to specifically test the component action object. - * dtButtonEnd is the data-test to button end - */ - @Prop() dtButtonEnd?: string = null; - /** - * When de value of component change, the event are dispache. - */ - @Event() bdsPaginationChange: EventEmitter; +// Elemento HTML nativo onde o componente será renderizado +@Element() private el!: HTMLElement; + +/** + * Estado que armazena o valor selecionado no seletor de página. + * Inicialmente, é configurado com a página inicial (startedPage). + */ +@State() value: number = this.startedPage; + +// Estado que armazena o valor selecionado no seletor de itens por página +@State() itemValue: number; + +/** + * Estado que controla se o seletor de opções de página está aberto ou fechado. + */ +@State() openSelect: boolean; + +/** + * Estado que armazena o número de páginas, gerado com base no total de itens e itens por página. + */ +@State() paginationNumbers = []; + +// Estado que armazena o número de itens por página selecionado +@State() itemsPerPage: number; + +// Estado que guarda o elemento pai com rolagem (se houver) +@State() intoView?: HTMLElement = null; + +/** + * Propriedade para receber o número total de páginas, baseado no total de itens e itens por página. + */ +@Prop() pages?: number; + +/** + * Propriedade que define a página inicial ao renderizar o componente. + */ +@Prop() startedPage?: number; + +/** + * Define a posição do menu de opções. Pode ser 'bottom' ou 'top'. + * Padrão é 'auto', que ajusta automaticamente a posição. + */ +@Prop() optionsPosition?: PaginationOptionsPositionType = 'auto'; + +// Propriedade que controla se o contador de páginas será exibido +@Prop() pageCounter?: boolean = false; + +// Propriedade para receber as opções de itens por página (por exemplo, [10, 20, 30]) +@Prop() itemsPage?: any; + +// Propriedade que define o número total de itens que serão paginados +@Prop() numberItems?: number; + +// Propriedade para definir o idioma do componente (opcional) +@Prop() language?: string; + +/** + * Propriedade de teste para especificamente testar a ação do botão inicial. + * dtButtonInitial é o data-test para o botão inicial. + */ +@Prop() dtButtonInitial?: string = null; + +/** + * Propriedade de teste para especificamente testar a ação do botão de página anterior. + * dtButtonPrev é o data-test para o botão anterior. + */ +@Prop() dtButtonPrev?: string = null; + +/** + * Propriedade de teste para especificamente testar o seletor de número de páginas. + * dtSelectNumber é o data-test para o seletor de número de páginas. + */ +@Prop() dtSelectNumber?: string = null; + +/** + * Propriedade de teste para especificamente testar a ação do botão de próxima página. + * dtButtonNext é o data-test para o botão próximo. + */ +@Prop() dtButtonNext?: string = null; + +/** + * Propriedade de teste para especificamente testar a ação do botão final. + * dtButtonEnd é o data-test para o botão final. + */ +@Prop() dtButtonEnd?: string = null; + +/** + * Evento emitido quando o valor da página atual é alterado. + * Pode ser escutado para realizar ações específicas ao mudar de página. + */ +@Event() bdsPaginationChange: EventEmitter; + +// Variável que armazena o número do primeiro item sendo exibido na página atual +startItem: number; + +// Variável que armazena o número do último item sendo exibido na página atual +endItem: number; componentWillLoad() { this.countPage(); this.intoView = getScrollParent(this.el); + this.processItemsPage(); + this.itemValue = this.itemsPage[0]; + this.itemSelected(this.itemValue); + this.countItem(); } @Watch('pages') @@ -86,6 +125,22 @@ export class Pagination { this.bdsPaginationChange.emit(this.value); } + processItemsPage() { + if (typeof this.itemsPage === 'string') { + try { + this.itemsPage = JSON.parse(this.itemsPage.replace(/'/g, '"')); + } catch (error) { + console.error('Failed to parse itemsPage:', error); + this.itemsPage = []; + } + } + } + + countItem() { + this.pages = this.numberItems / this.itemValue; + console.log(this.numberItems, this.itemValue, this.pages); + } + countPage() { if (this.paginationNumbers.length !== 0) { this.paginationNumbers = []; @@ -102,19 +157,21 @@ export class Pagination { } } - previewPage = (event: Event) => { + nextPage = (event: Event) => { const el = this.value; - if (el > 1) { + if (el < this.pages) { event.preventDefault(); - this.value = this.value - 1; + this.value = this.value + 1; + this.updateItemRange(); } }; - nextPage = (event: Event) => { + previewPage = (event: Event) => { const el = this.value; - if (el < this.pages) { + if (el > 1) { event.preventDefault(); - this.value = this.value + 1; + this.value = this.value - 1; + this.updateItemRange(); } }; @@ -123,6 +180,7 @@ export class Pagination { if (el > 1) { event.preventDefault(); this.value = this.paginationNumbers[0]; + this.updateItemRange(); } }; @@ -131,6 +189,7 @@ export class Pagination { if (el < this.pages) { event.preventDefault(); this.value = this.pages; + this.updateItemRange(); } }; @@ -145,50 +204,82 @@ export class Pagination { optionSelected(index) { this.value = index; this.openOptions(); + this.updateItemRange(); + } + + itemSelected(index) { + this.itemValue = index; + this.itemsPerPage = index; + this.openOptions(); + this.countItem(); + this.updateItemRange(); + } + + updateItemRange() { + console.log(this.value, this.itemsPerPage); + this.startItem = (this.value - 1) * this.itemsPerPage + 1; + this.endItem = Math.min(this.value * this.itemsPerPage, this.numberItems); + console.log(this.startItem, this.endItem); } render() { return ( -
- this.firstPage(ev)} - size="short" - variant="secondary" - icon="arrow-first" - dataTest={this.dtButtonInitial} - > - this.previewPage(ev)} - size="short" - variant="secondary" - icon="arrow-left" - dataTest={this.dtButtonPrev} - > - - - {this.paginationNumbers.map((el, index) => ( - this.optionSelected(el)}> - {el} - - ))} - - - this.nextPage(ev)} - size="short" - variant="secondary" - icon="arrow-right" - dataTest={this.dtButtonNext} - > - this.lastPage(ev)} - size="short" - variant="secondary" - icon="arrow-last" - dataTest={this.dtButtonEnd} - > -
+ + + Itens por página: + + {this.itemsPage.map((el, index) => ( + this.itemSelected(el)}> + {el} + + ))} + + + {' '} + {this.startItem}-{this.endItem} de {this.numberItems} + + + + this.firstPage(ev)} + size="short" + variant="secondary" + icon="arrow-first" + dataTest={this.dtButtonInitial} + > + this.previewPage(ev)} + size="short" + variant="secondary" + icon="arrow-left" + dataTest={this.dtButtonPrev} + > + + + {this.paginationNumbers.map((el, index) => ( + this.optionSelected(el)}> + {el} + + ))} + + {this.pageCounter && de {this.pages} páginas} + this.nextPage(ev)} + size="short" + variant="secondary" + icon="arrow-right" + dataTest={this.dtButtonNext} + > + this.lastPage(ev)} + size="short" + variant="secondary" + icon="arrow-last" + dataTest={this.dtButtonEnd} + > + +
); } diff --git a/src/components/pagination/readme.md b/src/components/pagination/readme.md index e3ee5d75..676f5316 100644 --- a/src/components/pagination/readme.md +++ b/src/components/pagination/readme.md @@ -7,40 +7,47 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ----------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ----------- | -| `dtButtonEnd` | `dt-button-end` | Data test is the prop to specifically test the component action object. dtButtonEnd is the data-test to button end | `string` | `null` | -| `dtButtonInitial` | `dt-button-initial` | Data test is the prop to specifically test the component action object. dtButtonInitial is the data-test to button initial. | `string` | `null` | -| `dtButtonNext` | `dt-button-next` | Data test is the prop to specifically test the component action object. dtButtonNext is the data-test to button next. | `string` | `null` | -| `dtButtonPrev` | `dt-button-prev` | Data test is the prop to specifically test the component action object. dtButtonPrev is the data-test to button prev. | `string` | `null` | -| `dtSelectNumber` | `dt-select-number` | Data test is the prop to specifically test the component action object. dtSelectNumber is the data-test to select number. | `string` | `null` | -| `optionsPosition` | `options-position` | Set the placement of the options menu. Can be 'bottom' or 'top'. | `"auto" \| "bottom" \| "top"` | `'auto'` | -| `pages` | `pages` | Prop to recive the number of pages. | `number` | `undefined` | -| `startedPage` | `started-page` | When the component are render this page are set. | `number` | `undefined` | +| Property | Attribute | Description | Type | Default | +| ----------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ----------- | +| `dtButtonEnd` | `dt-button-end` | Propriedade de teste para especificamente testar a ação do botão final. dtButtonEnd é o data-test para o botão final. | `string` | `null` | +| `dtButtonInitial` | `dt-button-initial` | Propriedade de teste para especificamente testar a ação do botão inicial. dtButtonInitial é o data-test para o botão inicial. | `string` | `null` | +| `dtButtonNext` | `dt-button-next` | Propriedade de teste para especificamente testar a ação do botão de próxima página. dtButtonNext é o data-test para o botão próximo. | `string` | `null` | +| `dtButtonPrev` | `dt-button-prev` | Propriedade de teste para especificamente testar a ação do botão de página anterior. dtButtonPrev é o data-test para o botão anterior. | `string` | `null` | +| `dtSelectNumber` | `dt-select-number` | Propriedade de teste para especificamente testar o seletor de número de páginas. dtSelectNumber é o data-test para o seletor de número de páginas. | `string` | `null` | +| `itemsPage` | `items-page` | | `any` | `undefined` | +| `language` | `language` | | `string` | `undefined` | +| `numberItems` | `number-items` | | `number` | `undefined` | +| `optionsPosition` | `options-position` | Define a posição do menu de opções. Pode ser 'bottom' ou 'top'. Padrão é 'auto', que ajusta automaticamente a posição. | `"auto" \| "bottom" \| "top"` | `'auto'` | +| `pageCounter` | `page-counter` | | `boolean` | `false` | +| `pages` | `pages` | Propriedade para receber o número total de páginas, baseado no total de itens e itens por página. | `number` | `undefined` | +| `startedPage` | `started-page` | Propriedade que define a página inicial ao renderizar o componente. | `number` | `undefined` | ## Events -| Event | Description | Type | -| --------------------- | ---------------------------------------------------------- | ------------------ | -| `bdsPaginationChange` | When de value of component change, the event are dispache. | `CustomEvent` | +| Event | Description | Type | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------ | +| `bdsPaginationChange` | Evento emitido quando o valor da página atual é alterado. Pode ser escutado para realizar ações específicas ao mudar de página. | `CustomEvent` | ## Dependencies ### Depends on -- [bds-button-icon](../icon-button) +- [bds-grid](../grid) +- [bds-typo](../typo) - [bds-select](../selects/select) - [bds-select-option](../select-option) +- [bds-button-icon](../icon-button) ### Graph ```mermaid graph TD; - bds-pagination --> bds-button-icon + bds-pagination --> bds-grid + bds-pagination --> bds-typo bds-pagination --> bds-select bds-pagination --> bds-select-option - bds-button-icon --> bds-icon + bds-pagination --> bds-button-icon bds-select --> bds-icon bds-select --> bds-typo bds-select --> bds-select-option @@ -48,6 +55,7 @@ graph TD; bds-select-option --> bds-checkbox bds-checkbox --> bds-icon bds-checkbox --> bds-typo + bds-button-icon --> bds-icon style bds-pagination fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/src/components/typo/readme.md b/src/components/typo/readme.md index c90c3f66..1e9535ec 100644 --- a/src/components/typo/readme.md +++ b/src/components/typo/readme.md @@ -62,6 +62,7 @@ - [bds-menu-separation](../menu/menu-separation) - [bds-nav-tree](../nav-tree) - [bds-nav-tree-item](../nav-tree) + - [bds-pagination](../pagination) - [bds-progress-bar](../progress-bar) - [bds-radio](../radio) - [bds-select](../selects/select) @@ -113,6 +114,7 @@ graph TD; bds-menu-separation --> bds-typo bds-nav-tree --> bds-typo bds-nav-tree-item --> bds-typo + bds-pagination --> bds-typo bds-progress-bar --> bds-typo bds-radio --> bds-typo bds-select --> bds-typo diff --git a/src/index.html b/src/index.html index 983bef29..8e709260 100644 --- a/src/index.html +++ b/src/index.html @@ -18,13 +18,16 @@ background: var(--color-surface-3, #f5f8f9); /* background: var(--color-background-2, #0a0f1a); */ margin: 0; - padding: 24px; + height: 100vh; } - Versão blip-ds 1.286.2 + + Versão blip-ds 1.286.2 + + From b75b6f4c1fe6cea65e21ecf5bbdc7d9a68ee7c84 Mon Sep 17 00:00:00 2001 From: WillianLomeu Date: Tue, 27 Aug 2024 14:05:41 -0300 Subject: [PATCH 2/2] feat(pagination): new pagination snippets --- src/components.d.ts | 4 + src/components/pagination/pagination.tsx | 14 +- src/components/pagination/readme.md | 7 +- src/snippets/pagination.stories.jsx | 600 +++++++++++++++++++++++ 4 files changed, 617 insertions(+), 8 deletions(-) create mode 100644 src/snippets/pagination.stories.jsx diff --git a/src/components.d.ts b/src/components.d.ts index 898743ae..90051386 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -5600,6 +5600,10 @@ declare namespace LocalJSX { "itemsPage"?: any; "language"?: string; "numberItems"?: number; + /** + * Evento emitido quando o valor da página atual é alterado. Pode ser escutado para realizar ações específicas ao mudar de página. + */ + "onBdsItemsPerPageChange"?: (event: BdsPaginationCustomEvent) => void; /** * Evento emitido quando o valor da página atual é alterado. Pode ser escutado para realizar ações específicas ao mudar de página. */ diff --git a/src/components/pagination/pagination.tsx b/src/components/pagination/pagination.tsx index 50a6df9d..0bf7d1e2 100644 --- a/src/components/pagination/pagination.tsx +++ b/src/components/pagination/pagination.tsx @@ -100,6 +100,11 @@ export class Pagination { * Pode ser escutado para realizar ações específicas ao mudar de página. */ @Event() bdsPaginationChange: EventEmitter; + /** + * Evento emitido quando o valor da página atual é alterado. + * Pode ser escutado para realizar ações específicas ao mudar de página. + */ + @Event() bdsItemsPerPageChange: EventEmitter; // Variável que armazena o número do primeiro item sendo exibido na página atual startItem: number; @@ -132,15 +137,14 @@ export class Pagination { try { this.itemsPage = JSON.parse(this.itemsPage.replace(/'/g, '"')); } catch (error) { - console.error('Failed to parse itemsPage:', error); this.itemsPage = []; } } } countItem() { - this.pages = this.numberItems / this.itemValue; - console.log(this.numberItems, this.itemValue, this.pages); + const pages = this.numberItems / this.itemValue; + this.pages = Math.ceil(pages); } countPage() { @@ -209,19 +213,19 @@ export class Pagination { this.updateItemRange(); } + @Watch('itemValue') itemSelected(index) { this.itemValue = index; this.itemsPerPage = index; this.openOptions(); this.countItem(); this.updateItemRange(); + this.bdsItemsPerPageChange.emit(this.itemsPerPage); } updateItemRange() { - console.log(this.value, this.itemsPerPage); this.startItem = (this.value - 1) * this.itemsPerPage + 1; this.endItem = Math.min(this.value * this.itemsPerPage, this.numberItems); - console.log(this.startItem, this.endItem); } get currentLanguage() { diff --git a/src/components/pagination/readme.md b/src/components/pagination/readme.md index ebcbf57f..da20510e 100644 --- a/src/components/pagination/readme.md +++ b/src/components/pagination/readme.md @@ -25,9 +25,10 @@ ## Events -| Event | Description | Type | -| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------ | -| `bdsPaginationChange` | Evento emitido quando o valor da página atual é alterado. Pode ser escutado para realizar ações específicas ao mudar de página. | `CustomEvent` | +| Event | Description | Type | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------ | +| `bdsItemsPerPageChange` | Evento emitido quando o valor da página atual é alterado. Pode ser escutado para realizar ações específicas ao mudar de página. | `CustomEvent` | +| `bdsPaginationChange` | Evento emitido quando o valor da página atual é alterado. Pode ser escutado para realizar ações específicas ao mudar de página. | `CustomEvent` | ## Dependencies diff --git a/src/snippets/pagination.stories.jsx b/src/snippets/pagination.stories.jsx new file mode 100644 index 00000000..44b530e4 --- /dev/null +++ b/src/snippets/pagination.stories.jsx @@ -0,0 +1,600 @@ +import React, { useState, h, useEffect } from 'react'; +import { + BdsTable, + BdsTableHeader, + BdsTableRow, + BdsTableTh, + BdsTableBody, + BdsTableCell, + BdsTypo, + BdsPagination, + BdsChipTag, + BdsCard, + BdsCardHeader, + BdsCardTitle, + BdsGrid, + BdsCardSubtitle, + BdsCardBody, + BdsList, + BdsListItem, +} from '../../blip-ds-react/dist/components'; + +export default { + title: 'Snippets/Pagination', +}; + +export const TableWithPagination = () => { + const data = [ + { + id: 1, + produto: 'Celular', + valor: '1500,00', + disponibilidade: 'disponível', + marca: 'Samsung', + estoque: 10, + categoria: 'Eletrônicos', + }, + { + id: 2, + produto: 'Notebook', + valor: '4000,00', + disponibilidade: 'indisponível', + marca: 'Dell', + estoque: 5, + categoria: 'Computadores', + }, + { + id: 3, + produto: 'Livros', + valor: '60,00', + disponibilidade: 'disponível', + marca: 'Penguin', + estoque: 20, + categoria: 'Livros', + }, + { + id: 4, + produto: 'Tablet', + valor: '1200,00', + disponibilidade: 'disponível', + marca: 'Apple', + estoque: 15, + categoria: 'Eletrônicos', + }, + { + id: 5, + produto: 'Headphones', + valor: '350,00', + disponibilidade: 'indisponível', + marca: 'Sony', + estoque: 8, + categoria: 'Acessórios', + }, + { + id: 6, + produto: 'Monitor', + valor: '800,00', + disponibilidade: 'disponível', + marca: 'LG', + estoque: 12, + categoria: 'Computadores', + }, + { + id: 7, + produto: 'Câmera', + valor: '2500,00', + disponibilidade: 'disponível', + marca: 'Canon', + estoque: 7, + categoria: 'Eletrônicos', + }, + { + id: 8, + produto: 'Teclado', + valor: '150,00', + disponibilidade: 'disponível', + marca: 'Microsoft', + estoque: 25, + categoria: 'Acessórios', + }, + { + id: 9, + produto: 'Mouse', + valor: '80,00', + disponibilidade: 'disponível', + marca: 'Logitech', + estoque: 30, + categoria: 'Acessórios', + }, + { + id: 10, + produto: 'Impressora', + valor: '600,00', + disponibilidade: 'indisponível', + marca: 'HP', + estoque: 4, + categoria: 'Computadores', + }, + { + id: 11, + produto: 'Micro-ondas', + valor: '400,00', + disponibilidade: 'disponível', + marca: 'Electrolux', + estoque: 14, + categoria: 'Eletrodomésticos', + }, + { + id: 12, + produto: 'Geladeira', + valor: '2000,00', + disponibilidade: 'disponível', + marca: 'Brastemp', + estoque: 6, + categoria: 'Eletrodomésticos', + }, + { + id: 13, + produto: 'Fogão', + valor: '900,00', + disponibilidade: 'disponível', + marca: 'Consul', + estoque: 9, + categoria: 'Eletrodomésticos', + }, + { + id: 14, + produto: 'Aspirador de pó', + valor: '350,00', + disponibilidade: 'disponível', + marca: 'Philips', + estoque: 11, + categoria: 'Eletrodomésticos', + }, + { + id: 15, + produto: 'Batedeira', + valor: '200,00', + disponibilidade: 'indisponível', + marca: 'Mondial', + estoque: 3, + categoria: 'Eletrodomésticos', + }, + { + id: 16, + produto: 'Fritadeira', + valor: '300,00', + disponibilidade: 'disponível', + marca: 'Arno', + estoque: 13, + categoria: 'Eletrodomésticos', + }, + { + id: 17, + produto: 'Cafeteira', + valor: '120,00', + disponibilidade: 'disponível', + marca: 'Nespresso', + estoque: 18, + categoria: 'Eletrodomésticos', + }, + { + id: 18, + produto: 'Sandwich Maker', + valor: '100,00', + disponibilidade: 'indisponível', + marca: 'Black+Decker', + estoque: 6, + categoria: 'Eletrodomésticos', + }, + { + id: 19, + produto: 'Torradeira', + valor: '80,00', + disponibilidade: 'disponível', + marca: 'Cadence', + estoque: 20, + categoria: 'Eletrodomésticos', + }, + { + id: 20, + produto: 'Liquidificador', + valor: '180,00', + disponibilidade: 'disponível', + marca: 'Arno', + estoque: 15, + categoria: 'Eletrodomésticos', + }, + { + id: 21, + produto: 'Máquina de costura', + valor: '700,00', + disponibilidade: 'disponível', + marca: 'Singer', + estoque: 8, + categoria: 'Eletrodomésticos', + }, + { + id: 22, + produto: 'Escova de cabelo', + valor: '60,00', + disponibilidade: 'disponível', + marca: 'Philips', + estoque: 22, + categoria: 'Beleza', + }, + { + id: 23, + produto: 'Secador de cabelo', + valor: '150,00', + disponibilidade: 'disponível', + marca: 'Taiff', + estoque: 12, + categoria: 'Beleza', + }, + { + id: 24, + produto: 'Chapinha', + valor: '100,00', + disponibilidade: 'disponível', + marca: 'Gama', + estoque: 16, + categoria: 'Beleza', + }, + { + id: 25, + produto: 'Kit de maquiagem', + valor: '250,00', + disponibilidade: 'disponível', + marca: 'Maybelline', + estoque: 10, + categoria: 'Beleza', + }, + { + id: 26, + produto: 'Perfume', + valor: '180,00', + disponibilidade: 'indisponível', + marca: 'Dior', + estoque: 5, + categoria: 'Beleza', + }, + { + id: 27, + produto: 'Creme para o rosto', + valor: '80,00', + disponibilidade: 'disponível', + marca: "L'Oréal", + estoque: 25, + categoria: 'Beleza', + }, + { + id: 28, + produto: 'Desodorante', + valor: '30,00', + disponibilidade: 'disponível', + marca: 'Nivea', + estoque: 40, + categoria: 'Beleza', + }, + { + id: 29, + produto: 'Shampoo', + valor: '50,00', + disponibilidade: 'disponível', + marca: 'Pantene', + estoque: 30, + categoria: 'Beleza', + }, + { + id: 30, + produto: 'Condicionador', + valor: '50,00', + disponibilidade: 'disponível', + marca: 'Elseve', + estoque: 28, + categoria: 'Beleza', + }, + { + id: 31, + produto: 'Sabonete', + valor: '20,00', + disponibilidade: 'disponível', + marca: 'Dove', + estoque: 50, + categoria: 'Beleza', + }, + { + id: 32, + produto: 'Creme para as mãos', + valor: '35,00', + disponibilidade: 'disponível', + marca: 'Avon', + estoque: 20, + categoria: 'Beleza', + }, + { + id: 33, + produto: 'Base', + valor: '120,00', + disponibilidade: 'disponível', + marca: 'MAC', + estoque: 18, + categoria: 'Beleza', + }, + { + id: 34, + produto: 'Corretivo', + valor: '90,00', + disponibilidade: 'disponível', + marca: 'Clinique', + estoque: 22, + categoria: 'Beleza', + }, + ]; + + const heading = ['Id', 'Produtos', 'Valor', 'Marca', 'Estoque', 'Categoria', 'Disponibilidade']; + + const numberPerPage = [5, 10, 20]; + + const [currentPage, setCurrentPage] = useState(1); + const [itemsPerPage, setItemsPerPage] = useState(numberPerPage[0]); + + const [paginatedData, setPaginatedData] = useState(data); + + useEffect(() => { + const startIndex = (currentPage - 1) * itemsPerPage; + const endIndex = startIndex + itemsPerPage; + setPaginatedData(data.slice(startIndex, endIndex)); + }, [currentPage, itemsPerPage]); + + const handlePaginationChange = (event) => { + setCurrentPage(event.detail); + }; + + const handleItemsPerPageChange = (newItemsPerPage) => { + setItemsPerPage(newItemsPerPage.detail); + setCurrentPage(1); + }; + + return ( + + + + + {heading.map((item, index) => ( + {item} + ))} + + + + {paginatedData.map((row, index) => ( + + + {row.id} + + + {row.produto} + + + {row.valor} + + + {row.marca} + + + {row.estoque} + + + {row.categoria} + + + {row.disponibilidade === 'disponível' ? ( + + {row.disponibilidade} + + ) : ( + + {row.disponibilidade} + + )} + + + ))} + + + + + ); +}; + +export const CardsWithPagination = () => { + const data = [ + { title: 'Celular', subtitle: 'Samsung', text: 'R$1500,00', disponibilidade: 'disponível' }, + { title: 'Notebook', subtitle: 'Dell', text: 'R$4000,00', disponibilidade: 'indisponível' }, + { title: 'Livros', subtitle: 'Penguin', text: 'R$60,00', disponibilidade: 'disponível' }, + { title: 'Tablet', subtitle: 'Apple', text: 'R$1200,00', disponibilidade: 'disponível' }, + { title: 'Headphones', subtitle: 'Sony', text: 'R$350,00', disponibilidade: 'indisponível' }, + { title: 'Monitor', subtitle: 'LG', text: 'R$800,00', disponibilidade: 'disponível' }, + { title: 'Câmera', subtitle: 'Canon', text: 'R$2500,00', disponibilidade: 'disponível' }, + { title: 'Teclado', subtitle: 'Microsoft', text: 'R$150,00', disponibilidade: 'disponível' }, + { title: 'Mouse', subtitle: 'Logitech', text: 'R$80,00', disponibilidade: 'disponível' }, + { title: 'Impressora', subtitle: 'HP', text: 'R$600,00', disponibilidade: 'indisponível' }, + { title: 'Micro-ondas', subtitle: 'Electrolux', text: 'R$400,00', disponibilidade: 'disponível' }, + { title: 'Geladeira', subtitle: 'Brastemp', text: 'R$2000,00', disponibilidade: 'disponível' }, + { title: 'Fogão', subtitle: 'Consul', text: 'R$900,00', disponibilidade: 'disponível' }, + { title: 'Aspirador de pó', subtitle: 'Philips', text: 'R$350,00', disponibilidade: 'disponível' }, + { title: 'Batedeira', subtitle: 'Mondial', text: 'R$200,00', disponibilidade: 'indisponível' }, + { title: 'Fritadeira', subtitle: 'Arno', text: 'R$300,00', disponibilidade: 'disponível' }, + { title: 'Cafeteira', subtitle: 'Nespresso', text: 'R$120,00', disponibilidade: 'disponível' }, + { title: 'Sandwich Maker', subtitle: 'Black+Decker', text: 'R$100,00', disponibilidade: 'indisponível' }, + { title: 'Torradeira', subtitle: 'Cadence', text: 'R$80,00', disponibilidade: 'disponível' }, + { title: 'Liquidificador', subtitle: 'Arno', text: 'R$180,00', disponibilidade: 'disponível' }, + { title: 'Máquina de costura', subtitle: 'Singer', text: 'R$700,00', disponibilidade: 'disponível' }, + { title: 'Escova de cabelo', subtitle: 'Philips', text: 'R$60,00', disponibilidade: 'disponível' }, + { title: 'Secador de cabelo', subtitle: 'Taiff', text: 'R$150,00', disponibilidade: 'disponível' }, + { title: 'Chapinha', subtitle: 'Gama', text: 'R$100,00', disponibilidade: 'disponível' }, + { title: 'Kit de maquiagem', subtitle: 'Maybelline', text: 'R$250,00', disponibilidade: 'disponível' }, + { title: 'Perfume', subtitle: 'Dior', text: 'R$180,00', disponibilidade: 'indisponível' }, + { title: 'Creme para o rosto', subtitle: "L'Oréal", text: 'R$80,00', disponibilidade: 'disponível' }, + { title: 'Desodorante', subtitle: 'Nivea', text: 'R$30,00', disponibilidade: 'disponível' }, + { title: 'Shampoo', subtitle: 'Pantene', text: 'R$50,00', disponibilidade: 'disponível' }, + { title: 'Condicionador', subtitle: 'Elseve', text: 'R$50,00', disponibilidade: 'disponível' }, + { title: 'Sabonete', subtitle: 'Dove', text: 'R$20,00', disponibilidade: 'disponível' }, + { title: 'Creme para as mãos', subtitle: 'Avon', text: 'R$35,00', disponibilidade: 'disponível' }, + { title: 'Base', subtitle: 'MAC', text: 'R$120,00', disponibilidade: 'disponível' }, + { title: 'Corretivo', subtitle: 'Clinique', text: 'R$90,00', disponibilidade: 'disponível' }, + ]; + + const numberPerPage = [5, 10, 20]; + + const [currentPage, setCurrentPage] = useState(1); + const [itemsPerPage, setItemsPerPage] = useState(numberPerPage[0]); + + const [paginatedData, setPaginatedData] = useState(data); + + useEffect(() => { + const startIndex = (currentPage - 1) * itemsPerPage; + const endIndex = startIndex + itemsPerPage; + setPaginatedData(data.slice(startIndex, endIndex)); + }, [currentPage, itemsPerPage]); + + const handlePaginationChange = (event) => { + setCurrentPage(event.detail); + }; + + const handleItemsPerPageChange = (newItemsPerPage) => { + setItemsPerPage(newItemsPerPage.detail); + setCurrentPage(1); + }; + + return ( + + + {paginatedData.map((obj, index) => ( + + + + + + + + + + {obj.text} + + + + ))} + + + + ); +}; + +export const ListWithPagination = () => { + const data = [ + { title: 'Celular', subtitle: 'Samsung', text: 'R$1500,00', disponibilidade: 'disponível' }, + { title: 'Notebook', subtitle: 'Dell', text: 'R$4000,00', disponibilidade: 'indisponível' }, + { title: 'Livros', subtitle: 'Penguin', text: 'R$60,00', disponibilidade: 'disponível' }, + { title: 'Tablet', subtitle: 'Apple', text: 'R$1200,00', disponibilidade: 'disponível' }, + { title: 'Headphones', subtitle: 'Sony', text: 'R$350,00', disponibilidade: 'indisponível' }, + { title: 'Monitor', subtitle: 'LG', text: 'R$800,00', disponibilidade: 'disponível' }, + { title: 'Câmera', subtitle: 'Canon', text: 'R$2500,00', disponibilidade: 'disponível' }, + { title: 'Teclado', subtitle: 'Microsoft', text: 'R$150,00', disponibilidade: 'disponível' }, + { title: 'Mouse', subtitle: 'Logitech', text: 'R$80,00', disponibilidade: 'disponível' }, + { title: 'Impressora', subtitle: 'HP', text: 'R$600,00', disponibilidade: 'indisponível' }, + { title: 'Micro-ondas', subtitle: 'Electrolux', text: 'R$400,00', disponibilidade: 'disponível' }, + { title: 'Geladeira', subtitle: 'Brastemp', text: 'R$2000,00', disponibilidade: 'disponível' }, + { title: 'Fogão', subtitle: 'Consul', text: 'R$900,00', disponibilidade: 'disponível' }, + { title: 'Aspirador de pó', subtitle: 'Philips', text: 'R$350,00', disponibilidade: 'disponível' }, + { title: 'Batedeira', subtitle: 'Mondial', text: 'R$200,00', disponibilidade: 'indisponível' }, + { title: 'Fritadeira', subtitle: 'Arno', text: 'R$300,00', disponibilidade: 'disponível' }, + { title: 'Cafeteira', subtitle: 'Nespresso', text: 'R$120,00', disponibilidade: 'disponível' }, + { title: 'Sandwich Maker', subtitle: 'Black+Decker', text: 'R$100,00', disponibilidade: 'indisponível' }, + { title: 'Torradeira', subtitle: 'Cadence', text: 'R$80,00', disponibilidade: 'disponível' }, + { title: 'Liquidificador', subtitle: 'Arno', text: 'R$180,00', disponibilidade: 'disponível' }, + { title: 'Máquina de costura', subtitle: 'Singer', text: 'R$700,00', disponibilidade: 'disponível' }, + { title: 'Escova de cabelo', subtitle: 'Philips', text: 'R$60,00', disponibilidade: 'disponível' }, + { title: 'Secador de cabelo', subtitle: 'Taiff', text: 'R$150,00', disponibilidade: 'disponível' }, + { title: 'Chapinha', subtitle: 'Gama', text: 'R$100,00', disponibilidade: 'disponível' }, + { title: 'Kit de maquiagem', subtitle: 'Maybelline', text: 'R$250,00', disponibilidade: 'disponível' }, + { title: 'Perfume', subtitle: 'Dior', text: 'R$180,00', disponibilidade: 'indisponível' }, + { title: 'Creme para o rosto', subtitle: "L'Oréal", text: 'R$80,00', disponibilidade: 'disponível' }, + { title: 'Desodorante', subtitle: 'Nivea', text: 'R$30,00', disponibilidade: 'disponível' }, + { title: 'Shampoo', subtitle: 'Pantene', text: 'R$50,00', disponibilidade: 'disponível' }, + { title: 'Condicionador', subtitle: 'Elseve', text: 'R$50,00', disponibilidade: 'disponível' }, + { title: 'Sabonete', subtitle: 'Dove', text: 'R$20,00', disponibilidade: 'disponível' }, + { title: 'Creme para as mãos', subtitle: 'Avon', text: 'R$35,00', disponibilidade: 'disponível' }, + { title: 'Base', subtitle: 'MAC', text: 'R$120,00', disponibilidade: 'disponível' }, + { title: 'Corretivo', subtitle: 'Clinique', text: 'R$90,00', disponibilidade: 'disponível' }, + ]; + + const numberPerPage = [5, 10, 20]; + + const [currentPage, setCurrentPage] = useState(1); + const [itemsPerPage, setItemsPerPage] = useState(numberPerPage[0]); + + const [paginatedData, setPaginatedData] = useState(data); + + useEffect(() => { + const startIndex = (currentPage - 1) * itemsPerPage; + const endIndex = startIndex + itemsPerPage; + setPaginatedData(data.slice(startIndex, endIndex)); + }, [currentPage, itemsPerPage]); + + const handlePaginationChange = (event) => { + setCurrentPage(event.detail); + }; + + const handleItemsPerPageChange = (newItemsPerPage) => { + setItemsPerPage(newItemsPerPage.detail); + setCurrentPage(1); + }; + + return ( + + + + {paginatedData.map((obj, index) => ( + + {obj.text} + {obj.subtitle} + {obj.disponibilidade === 'disponível' ? ( + + {obj.disponibilidade} + + ) : ( + + {obj.disponibilidade} + + )} + + ))} + + + + + ); +};