From 3cce6ea23537dc49945ae5e342a786b50ff9e18e Mon Sep 17 00:00:00 2001 From: gearnode Date: Wed, 19 Feb 2025 13:43:18 +0100 Subject: [PATCH] Use dedicated pagination hook Signed-off-by: gearnode --- apps/console/src/pages/VendorListPage.tsx | 206 +++++++-------- .../VendorListPagePaginationQuery.graphql.ts | 102 +++++--- .../VendorListPageQuery.graphql.ts | 243 ++++++++---------- .../VendorListPage_vendors.graphql.ts | 23 +- 4 files changed, 278 insertions(+), 296 deletions(-) diff --git a/apps/console/src/pages/VendorListPage.tsx b/apps/console/src/pages/VendorListPage.tsx index 7d08f2c33..e2546114b 100644 --- a/apps/console/src/pages/VendorListPage.tsx +++ b/apps/console/src/pages/VendorListPage.tsx @@ -6,6 +6,7 @@ import { useQueryLoader, useMutation, ConnectionHandler, + usePaginationFragment, } from "react-relay"; import { useSearchParams } from "react-router"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; @@ -20,38 +21,46 @@ import { Helmet } from "react-helmet-async"; import { VendorListPageCreateVendorMutation } from "./__generated__/VendorListPageCreateVendorMutation.graphql"; import { VendorListPageDeleteVendorMutation } from "./__generated__/VendorListPageDeleteVendorMutation.graphql"; import { toast } from "@/hooks/use-toast"; +import { VendorListPagePaginationQuery } from "./__generated__/VendorListPagePaginationQuery.graphql"; +import { VendorListPage_vendors$key } from "./__generated__/VendorListPage_vendors.graphql"; const ITEMS_PER_PAGE = 25; const vendorListPageQuery = graphql` - query VendorListPageQuery( - $first: Int - $after: CursorKey - $last: Int - $before: CursorKey - ) { + query VendorListPageQuery($first: Int, $after: CursorKey, $last: Int, $before: CursorKey) { currentOrganization: node(id: "AZSfP_xAcAC5IAAAAAAltA") { id ... on Organization { - vendors(first: $first, after: $after, last: $last, before: $before) - @connection(key: "VendorListPageQuery_vendors") { - edges { - node { - id - name - createdAt - updatedAt - } - cursor - } - pageInfo { - hasNextPage - hasPreviousPage - startCursor - endCursor - } + ...VendorListPage_vendors + } + } + } +`; + +const vendorListFragment = graphql` + fragment VendorListPage_vendors on Organization + @refetchable(queryName: "VendorListPagePaginationQuery") { + id + vendors( + first: $first + after: $after + last: $last + before: $before + ) @connection(key: "VendorListPage_vendors") { + edges { + node { + id + name + createdAt + updatedAt } } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } } } `; @@ -103,52 +112,46 @@ const vendorsList = [ ]; function LoadAboveButton({ - pageInfo, - isPending, - onPageChange, + isLoading, + hasMore, + onLoadMore, }: { - pageInfo: { - hasNextPage: boolean; - hasPreviousPage: boolean; - } | null | undefined; - isPending: boolean; - onPageChange: (direction: "prev") => void; + isLoading: boolean; + hasMore: boolean; + onLoadMore: () => void; }) { return (
); } function LoadBelowButton({ - pageInfo, - isPending, - onPageChange, + isLoading, + hasMore, + onLoadMore, }: { - pageInfo: { - hasNextPage: boolean; - hasPreviousPage: boolean; - } | null | undefined; - isPending: boolean; - onPageChange: (direction: "next") => void; + isLoading: boolean; + hasMore: boolean; + onLoadMore: () => void; }) { return (
); @@ -156,17 +159,10 @@ function LoadBelowButton({ function VendorListContent({ queryRef, - onPageChange, }: { queryRef: PreloadedQuery; - onPageChange: (params: { - first?: number; - after?: string; - last?: number; - before?: string; - }) => void; }) { - const data = usePreloadedQuery(vendorListPageQuery, queryRef); + const data = usePreloadedQuery(vendorListPageQuery, queryRef); const [searchParams, setSearchParams] = useSearchParams(); const [isPending, startTransition] = useTransition(); const [searchTerm, setSearchTerm] = useState(""); @@ -174,41 +170,24 @@ function VendorListContent({ const [createVendor] = useMutation(createVendorMutation); const [deleteVendor] = useMutation(deleteVendorMutation); - const vendors = data.currentOrganization.vendors?.edges.map((edge) => edge.node) ?? []; - const pageInfo = data.currentOrganization.vendors?.pageInfo; + const { + data: vendorsConnection, + loadNext, + loadPrevious, + hasNext, + hasPrevious, + isLoadingNext, + isLoadingPrevious, + } = usePaginationFragment(vendorListFragment, data.currentOrganization); + + const vendors = vendorsConnection.vendors.edges.map((edge) => edge.node) ?? []; + const pageInfo = vendorsConnection.vendors.pageInfo; const fuse = new Fuse(vendorsList, { keys: ["name"], threshold: 0.3, }); - const handlePageChange = (direction: "next" | "prev") => { - if (!pageInfo) return; - - if (direction === "next" && !pageInfo.hasNextPage) return; - if (direction === "prev" && !pageInfo.hasPreviousPage) return; - - startTransition(() => { - const params = - direction === "next" - ? { first: ITEMS_PER_PAGE, after: pageInfo.endCursor } - : { last: ITEMS_PER_PAGE, before: pageInfo.startCursor }; - - setSearchParams((prev) => { - if (direction === "next") { - prev.set("after", pageInfo.endCursor!); - prev.delete("before"); - } else { - prev.set("before", pageInfo.startCursor!); - prev.delete("after"); - } - return prev; - }); - - onPageChange(params); - }); - }; - return (
@@ -299,9 +278,18 @@ function VendorListContent({
handlePageChange("prev")} + isLoading={isLoadingPrevious} + hasMore={hasPrevious} + onLoadMore={() => { + startTransition(() => { + setSearchParams((prev) => { + prev.set("before", pageInfo?.startCursor || ""); + prev.delete("after"); + return prev; + }); + loadPrevious(ITEMS_PER_PAGE); + }); + }} />
@@ -378,9 +366,18 @@ function VendorListContent({
handlePageChange("next")} + isLoading={isLoadingNext} + hasMore={hasNext} + onLoadMore={() => { + startTransition(() => { + setSearchParams((prev) => { + prev.set("after", pageInfo?.endCursor || ""); + prev.delete("before"); + return prev; + }); + loadNext(ITEMS_PER_PAGE); + }); + }} />
); @@ -417,29 +414,7 @@ export default function VendorListPage() { last: before ? ITEMS_PER_PAGE : undefined, before: before || undefined, }); - }, [loadQuery, searchParams]); - - const handlePageChange = ({ - first, - after, - last, - before, - }: { - first?: number; - after?: string; - last?: number; - before?: string; - }) => { - loadQuery( - { - first, - after, - last, - before, - }, - { fetchPolicy: "network-only" }, - ); - }; + }, [loadQuery]); if (!queryRef) { return ; @@ -451,10 +426,7 @@ export default function VendorListPage() { Vendors - Probo Console }> - + ); diff --git a/apps/console/src/pages/__generated__/VendorListPagePaginationQuery.graphql.ts b/apps/console/src/pages/__generated__/VendorListPagePaginationQuery.graphql.ts index 2d4ae47c5..8c9b9151b 100644 --- a/apps/console/src/pages/__generated__/VendorListPagePaginationQuery.graphql.ts +++ b/apps/console/src/pages/__generated__/VendorListPagePaginationQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<87314e850c396bef91d3fa31ec8a04b8>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -12,8 +12,10 @@ import { ConcreteRequest } from 'relay-runtime'; import { FragmentRefs } from "relay-runtime"; export type VendorListPagePaginationQuery$variables = { after?: any | null | undefined; + before?: any | null | undefined; first?: number | null | undefined; id: string; + last?: number | null | undefined; }; export type VendorListPagePaginationQuery$data = { readonly node: { @@ -26,66 +28,90 @@ export type VendorListPagePaginationQuery = { }; const node: ConcreteRequest = (function(){ -var v0 = [ - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "after" - }, - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "first" - }, - { - "defaultValue": null, - "kind": "LocalArgument", - "name": "id" - } -], -v1 = [ +var v0 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "after" +}, +v1 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "before" +}, +v2 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "first" +}, +v3 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "id" +}, +v4 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "last" +}, +v5 = [ { "kind": "Variable", "name": "id", "variableName": "id" } ], -v2 = { +v6 = { "alias": null, "args": null, "kind": "ScalarField", "name": "__typename", "storageKey": null }, -v3 = { +v7 = { "alias": null, "args": null, "kind": "ScalarField", "name": "id", "storageKey": null }, -v4 = [ +v8 = [ { "kind": "Variable", "name": "after", "variableName": "after" }, + { + "kind": "Variable", + "name": "before", + "variableName": "before" + }, { "kind": "Variable", "name": "first", "variableName": "first" + }, + { + "kind": "Variable", + "name": "last", + "variableName": "last" } ]; return { "fragment": { - "argumentDefinitions": (v0/*: any*/), + "argumentDefinitions": [ + (v0/*: any*/), + (v1/*: any*/), + (v2/*: any*/), + (v3/*: any*/), + (v4/*: any*/) + ], "kind": "Fragment", "metadata": null, "name": "VendorListPagePaginationQuery", "selections": [ { "alias": null, - "args": (v1/*: any*/), + "args": (v5/*: any*/), "concreteType": null, "kind": "LinkedField", "name": "node", @@ -105,26 +131,32 @@ return { }, "kind": "Request", "operation": { - "argumentDefinitions": (v0/*: any*/), + "argumentDefinitions": [ + (v0/*: any*/), + (v1/*: any*/), + (v2/*: any*/), + (v4/*: any*/), + (v3/*: any*/) + ], "kind": "Operation", "name": "VendorListPagePaginationQuery", "selections": [ { "alias": null, - "args": (v1/*: any*/), + "args": (v5/*: any*/), "concreteType": null, "kind": "LinkedField", "name": "node", "plural": false, "selections": [ - (v2/*: any*/), - (v3/*: any*/), + (v6/*: any*/), + (v7/*: any*/), { "kind": "InlineFragment", "selections": [ { "alias": null, - "args": (v4/*: any*/), + "args": (v8/*: any*/), "concreteType": "VendorConnection", "kind": "LinkedField", "name": "vendors", @@ -146,7 +178,7 @@ return { "name": "node", "plural": false, "selections": [ - (v3/*: any*/), + (v7/*: any*/), { "alias": null, "args": null, @@ -168,7 +200,7 @@ return { "name": "updatedAt", "storageKey": null }, - (v2/*: any*/) + (v6/*: any*/) ], "storageKey": null }, @@ -226,7 +258,7 @@ return { }, { "alias": null, - "args": (v4/*: any*/), + "args": (v8/*: any*/), "filters": null, "handle": "connection", "key": "VendorListPage_vendors", @@ -243,16 +275,16 @@ return { ] }, "params": { - "cacheID": "73f269ef13a930c0629d857caae56a34", + "cacheID": "3ce437d0d8e4415db28f78cf8c9aac7c", "id": null, "metadata": {}, "name": "VendorListPagePaginationQuery", "operationKind": "query", - "text": "query VendorListPagePaginationQuery(\n $after: CursorKey\n $first: Int\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...VendorListPage_vendors\n id\n }\n}\n\nfragment VendorListPage_vendors on Organization {\n vendors(first: $first, after: $after) {\n edges {\n node {\n id\n name\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n id\n}\n" + "text": "query VendorListPagePaginationQuery(\n $after: CursorKey\n $before: CursorKey\n $first: Int\n $last: Int\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...VendorListPage_vendors\n id\n }\n}\n\nfragment VendorListPage_vendors on Organization {\n id\n vendors(first: $first, after: $after, last: $last, before: $before) {\n edges {\n node {\n id\n name\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n}\n" } }; })(); -(node as any).hash = "753e6b32cc21645852de27cf6f23c769"; +(node as any).hash = "7f084d24023bc4dd68d22cdd6e75f174"; export default node; diff --git a/apps/console/src/pages/__generated__/VendorListPageQuery.graphql.ts b/apps/console/src/pages/__generated__/VendorListPageQuery.graphql.ts index 2b85d7228..e9c078388 100644 --- a/apps/console/src/pages/__generated__/VendorListPageQuery.graphql.ts +++ b/apps/console/src/pages/__generated__/VendorListPageQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<874e734a238db8fc4ab486da7d49ceee>> + * @generated SignedSource<<23fdb7f13c0e5f5c25485a6c4800dcb5>> * @lightSyntaxTransform * @nogrep */ @@ -9,6 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; +import { FragmentRefs } from "relay-runtime"; export type VendorListPageQuery$variables = { after?: any | null | undefined; before?: any | null | undefined; @@ -18,23 +19,7 @@ export type VendorListPageQuery$variables = { export type VendorListPageQuery$data = { readonly currentOrganization: { readonly id: string; - readonly vendors?: { - readonly edges: ReadonlyArray<{ - readonly cursor: any; - readonly node: { - readonly createdAt: any; - readonly id: string; - readonly name: string; - readonly updatedAt: any; - }; - }>; - readonly pageInfo: { - readonly endCursor: any | null | undefined; - readonly hasNextPage: boolean; - readonly hasPreviousPage: boolean; - readonly startCursor: any | null | undefined; - }; - }; + readonly " $fragmentSpreads": FragmentRefs<"VendorListPage_vendors">; }; }; export type VendorListPageQuery = { @@ -85,99 +70,6 @@ v6 = { "storageKey": null }, v7 = [ - { - "alias": null, - "args": null, - "concreteType": "VendorEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "Vendor", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v5/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "createdAt", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "updatedAt", - "storageKey": null - }, - (v6/*: any*/) - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "cursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "PageInfo", - "kind": "LinkedField", - "name": "pageInfo", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "hasNextPage", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "hasPreviousPage", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "startCursor", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "endCursor", - "storageKey": null - } - ], - "storageKey": null - } -], -v8 = [ { "kind": "Variable", "name": "after", @@ -224,14 +116,9 @@ return { "kind": "InlineFragment", "selections": [ { - "alias": "vendors", "args": null, - "concreteType": "VendorConnection", - "kind": "LinkedField", - "name": "__VendorListPageQuery_vendors_connection", - "plural": false, - "selections": (v7/*: any*/), - "storageKey": null + "kind": "FragmentSpread", + "name": "VendorListPage_vendors" } ], "type": "Organization", @@ -270,20 +157,112 @@ return { "selections": [ { "alias": null, - "args": (v8/*: any*/), + "args": (v7/*: any*/), "concreteType": "VendorConnection", "kind": "LinkedField", "name": "vendors", "plural": false, - "selections": (v7/*: any*/), + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "VendorEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Vendor", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v5/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "updatedAt", + "storageKey": null + }, + (v6/*: any*/) + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "cursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "PageInfo", + "kind": "LinkedField", + "name": "pageInfo", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasNextPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasPreviousPage", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "startCursor", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "endCursor", + "storageKey": null + } + ], + "storageKey": null + } + ], "storageKey": null }, { "alias": null, - "args": (v8/*: any*/), + "args": (v7/*: any*/), "filters": null, "handle": "connection", - "key": "VendorListPageQuery_vendors", + "key": "VendorListPage_vendors", "kind": "LinkedHandle", "name": "vendors" } @@ -297,28 +276,16 @@ return { ] }, "params": { - "cacheID": "079490495e96d3609a263570f185673b", + "cacheID": "b910bb15ebb2e9b5aae2f20e0f5266db", "id": null, - "metadata": { - "connection": [ - { - "count": null, - "cursor": null, - "direction": "bidirectional", - "path": [ - "currentOrganization", - "vendors" - ] - } - ] - }, + "metadata": {}, "name": "VendorListPageQuery", "operationKind": "query", - "text": "query VendorListPageQuery(\n $first: Int\n $after: CursorKey\n $last: Int\n $before: CursorKey\n) {\n currentOrganization: node(id: \"AZSfP_xAcAC5IAAAAAAltA\") {\n __typename\n id\n ... on Organization {\n vendors(first: $first, after: $after, last: $last, before: $before) {\n edges {\n node {\n id\n name\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n}\n" + "text": "query VendorListPageQuery(\n $first: Int\n $after: CursorKey\n $last: Int\n $before: CursorKey\n) {\n currentOrganization: node(id: \"AZSfP_xAcAC5IAAAAAAltA\") {\n __typename\n id\n ... on Organization {\n ...VendorListPage_vendors\n }\n }\n}\n\nfragment VendorListPage_vendors on Organization {\n id\n vendors(first: $first, after: $after, last: $last, before: $before) {\n edges {\n node {\n id\n name\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n}\n" } }; })(); -(node as any).hash = "9613eb9b1e34b2ebffda69c5909f5f5b"; +(node as any).hash = "a1f88bf5287abaffb051993051d0e2a7"; export default node; diff --git a/apps/console/src/pages/__generated__/VendorListPage_vendors.graphql.ts b/apps/console/src/pages/__generated__/VendorListPage_vendors.graphql.ts index 5ec0b3af9..7ddcdac5b 100644 --- a/apps/console/src/pages/__generated__/VendorListPage_vendors.graphql.ts +++ b/apps/console/src/pages/__generated__/VendorListPage_vendors.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<98591652ea931191ef7210e363e0adad>> + * @generated SignedSource<<36562961e8a3be3e68279a6d56f3ef1a>> * @lightSyntaxTransform * @nogrep */ @@ -52,18 +52,26 @@ return { "kind": "RootArgument", "name": "after" }, + { + "kind": "RootArgument", + "name": "before" + }, { "kind": "RootArgument", "name": "first" + }, + { + "kind": "RootArgument", + "name": "last" } ], "kind": "Fragment", "metadata": { "connection": [ { - "count": "first", - "cursor": "after", - "direction": "forward", + "count": null, + "cursor": null, + "direction": "bidirectional", "path": (v0/*: any*/) } ], @@ -73,7 +81,10 @@ return { "count": "first", "cursor": "after" }, - "backward": null, + "backward": { + "count": "last", + "cursor": "before" + }, "path": (v0/*: any*/) }, "fragmentPathInResult": [ @@ -203,6 +214,6 @@ return { }; })(); -(node as any).hash = "f61c6a2996a9fe95b71d9c0c2fe0530c"; +(node as any).hash = "7f084d24023bc4dd68d22cdd6e75f174"; export default node;