From 97b42e6e891670db6c71e634e16c2df9063a1638 Mon Sep 17 00:00:00 2001 From: Icaro Oliveira Date: Fri, 2 Aug 2024 09:18:44 -0300 Subject: [PATCH 1/3] feat: Implement pagination for sellers in OrganizationDetailsSellers component --- .../OrganizationDetailsSellers.tsx | 108 ++++++++++++++---- react/graphql/getSellersPaginated.graphql | 14 +++ 2 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 react/graphql/getSellersPaginated.graphql diff --git a/react/admin/OrganizationDetails/OrganizationDetailsSellers.tsx b/react/admin/OrganizationDetails/OrganizationDetailsSellers.tsx index 914affbc..0f386b58 100644 --- a/react/admin/OrganizationDetails/OrganizationDetailsSellers.tsx +++ b/react/admin/OrganizationDetails/OrganizationDetailsSellers.tsx @@ -1,11 +1,12 @@ -import React, { Fragment, useEffect, useState } from 'react' +import React, { Fragment, useState } from 'react' import { FormattedMessage, useIntl } from 'react-intl' import { PageBlock, Table } from 'vtex.styleguide' import { useQuery } from 'react-apollo' +import { useToast } from '@vtex/admin-ui' import { organizationMessages as messages } from '../utils/messages' import { organizationBulkAction } from '../utils/organizationBulkAction' -import GET_SELLERS from '../../graphql/getSellers.graphql' +import GET_SELLERS_PAGINATED from '../../graphql/getSellersPaginated.graphql' export interface Seller { sellerId: string @@ -17,6 +18,8 @@ export interface SellerItem { name: string } +const pageSize = 25 + const OrganizationDetailsSellers = ({ getSchema, sellersState, @@ -30,37 +33,50 @@ const OrganizationDetailsSellers = ({ * Hooks */ const { formatMessage } = useIntl() + const toast = useToast() /** * States */ - const [sellerOptions, setSellerOptions] = useState([] as Seller[]) + const [sellerOptions, setSellerOptions] = useState([]) - /** - * Queries - */ - const { data: sellersData, loading } = useQuery(GET_SELLERS) + const [from, setFrom] = useState(0) + const [to, setTo] = useState(25) /** - * Effects + * Queries */ - useEffect(() => { - if (!sellersData?.getSellers?.length) { - return + const { data: sellersData, loading, refetch } = useQuery<{ + getSellersPaginated: { + pagination: { + page: number + pageSize: number + total: number + } + items: SellerItem[] } + }>(GET_SELLERS_PAGINATED, { + variables: { page: from, pageSize: to }, + onCompleted: data => { + if (!data?.getSellersPaginated?.items) { + return + } - const options = [] as Seller[] + const options = data.getSellersPaginated.items.map( + ({ name, id }: SellerItem) => ({ + name, + sellerId: id, + }) + ) - sellersData.getSellers.forEach(({ name, id }: SellerItem) => { - if (!options.find(option => option.sellerId === id)) { - options.push({ name, sellerId: id }) - } - }) - options.sort( - (a: Seller, b: Seller) => a.name?.localeCompare(b.name ?? '') ?? 0 - ) - setSellerOptions(options) - }, [sellersData]) + setSellerOptions(options) + }, + onError: error => { + toast({ variant: 'critical', message: error.message }) + }, + }) + + const totalItems = sellersData?.getSellersPaginated?.pagination?.total ?? 0 /** * Functions @@ -96,6 +112,40 @@ const OrganizationDetailsSellers = ({ setSellersState((prevState: any) => [...prevState, ...newSellers]) } + const handlePrev = () => { + if (from === 0) return + + setFrom(Math.max(from - pageSize, 0)) + setTo(Math.max(to - pageSize, pageSize)) + + refetch({ + page: from, + pageSize: to, + }) + } + + const handleNext = () => { + if (totalItems === to) return + + setFrom(from + pageSize) + setTo(to + pageSize) + + refetch({ + page: from, + pageSize: to, + }) + } + + const handleRowsChange = (newPageSize: number) => { + setFrom(0) + setTo(newPageSize) + + refetch({ + page: 0, + pageSize: newPageSize, + }) + } + return ( @@ -107,7 +157,6 @@ const OrganizationDetailsSellers = ({ fullWidth schema={getSchema()} items={sellersState} - loading={loading} bulkActions={organizationBulkAction( handleRemoveSellers, messages.removeFromOrg, @@ -115,12 +164,14 @@ const OrganizationDetailsSellers = ({ )} /> +

diff --git a/react/graphql/getSellersPaginated.graphql b/react/graphql/getSellersPaginated.graphql new file mode 100644 index 00000000..9553a233 --- /dev/null +++ b/react/graphql/getSellersPaginated.graphql @@ -0,0 +1,14 @@ +query GetSellersPaginated($page: Int, $pageSize: Int) { + getSellersPaginated(args: { page: $page, pageSize: $pageSize }) { + pagination { + page + pageSize + total + } + items { + id + name + email + } + } +} From 14c9784f9672576964adb7b36c8c848b595d3e75 Mon Sep 17 00:00:00 2001 From: Icaro Oliveira Date: Fri, 2 Aug 2024 09:19:59 -0300 Subject: [PATCH 2/3] docs: update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65698332..25a4e806 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Fixed +- Implement pagination for sellers in Organization Details page + ## [1.33.0] - 2024-07-18 ### Feat From 0f19e52423af8006eb543aff6c53d53374eca6cf Mon Sep 17 00:00:00 2001 From: Icaro Oliveira Date: Mon, 5 Aug 2024 15:55:09 -0300 Subject: [PATCH 3/3] feat: implement pagination for sellers in OrganizationDetailsSellers component --- .../OrganizationDetailsSellers.tsx | 78 +++++++++---------- react/graphql/getSellersPaginated.graphql | 2 +- 2 files changed, 39 insertions(+), 41 deletions(-) diff --git a/react/admin/OrganizationDetails/OrganizationDetailsSellers.tsx b/react/admin/OrganizationDetails/OrganizationDetailsSellers.tsx index 0f386b58..44d33155 100644 --- a/react/admin/OrganizationDetails/OrganizationDetailsSellers.tsx +++ b/react/admin/OrganizationDetails/OrganizationDetailsSellers.tsx @@ -18,7 +18,16 @@ export interface SellerItem { name: string } -const pageSize = 25 +interface GetSellersPaginatedQueryResponse { + getSellersPaginated: { + items: SellerItem[] + pagination: { + page: number + pageSize: number + total: number + } + } +} const OrganizationDetailsSellers = ({ getSchema, @@ -32,31 +41,22 @@ const OrganizationDetailsSellers = ({ /** * Hooks */ - const { formatMessage } = useIntl() const toast = useToast() + const { formatMessage } = useIntl() /** * States */ + const [variables, setVariables] = useState({ page: 1, pageSize: 25 }) const [sellerOptions, setSellerOptions] = useState([]) - const [from, setFrom] = useState(0) - const [to, setTo] = useState(25) - /** * Queries */ - const { data: sellersData, loading, refetch } = useQuery<{ - getSellersPaginated: { - pagination: { - page: number - pageSize: number - total: number - } - items: SellerItem[] - } - }>(GET_SELLERS_PAGINATED, { - variables: { page: from, pageSize: to }, + const { data: sellersData, loading, refetch } = useQuery< + GetSellersPaginatedQueryResponse + >(GET_SELLERS_PAGINATED, { + variables, onCompleted: data => { if (!data?.getSellersPaginated?.items) { return @@ -112,37 +112,32 @@ const OrganizationDetailsSellers = ({ setSellersState((prevState: any) => [...prevState, ...newSellers]) } - const handlePrev = () => { - if (from === 0) return + const handleNext = () => { + if (variables.page * variables.pageSize >= totalItems) return - setFrom(Math.max(from - pageSize, 0)) - setTo(Math.max(to - pageSize, pageSize)) + setVariables(prev => ({ ...prev, page: prev.page + 1 })) - refetch({ - page: from, - pageSize: to, - }) + refetch({ page: variables.page + 1, pageSize: variables.pageSize }) } - const handleNext = () => { - if (totalItems === to) return + const handlePrev = () => { + if (variables.page === 1) return - setFrom(from + pageSize) - setTo(to + pageSize) + setVariables(prev => ({ ...prev, page: prev.page - 1 })) - refetch({ - page: from, - pageSize: to, - }) + refetch({ page: variables.page - 1, pageSize: variables.pageSize }) } - const handleRowsChange = (newPageSize: number) => { - setFrom(0) - setTo(newPageSize) + const handleRowsChange = (e: React.ChangeEvent) => { + const { + target: { value }, + } = e + + setVariables({ page: 1, pageSize: +value }) refetch({ - page: 0, - pageSize: newPageSize, + page: 1, + pageSize: +value, }) } @@ -183,12 +178,15 @@ const OrganizationDetailsSellers = ({ onNextClick: handleNext, onPrevClick: handlePrev, onRowsChange: handleRowsChange, - currentItemFrom: from + 1, - currentItemTo: Math.min(to, totalItems), + currentItemFrom: (variables.page - 1) * variables.pageSize + 1, + currentItemTo: Math.min( + variables.page * variables.pageSize, + totalItems + ), textShowRows: formatMessage(messages.showRows), textOf: formatMessage(messages.of), - totalItems, rowsOptions: [25, 50, 100], + totalItems, }} /> diff --git a/react/graphql/getSellersPaginated.graphql b/react/graphql/getSellersPaginated.graphql index 9553a233..70533aa4 100644 --- a/react/graphql/getSellersPaginated.graphql +++ b/react/graphql/getSellersPaginated.graphql @@ -1,5 +1,5 @@ query GetSellersPaginated($page: Int, $pageSize: Int) { - getSellersPaginated(args: { page: $page, pageSize: $pageSize }) { + getSellersPaginated(page: $page, pageSize: $pageSize) { pagination { page pageSize