From 52ff79b02d34d3f6762d980579a1b508dd3f8ca6 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Mon, 24 Jul 2023 17:43:23 +0100 Subject: [PATCH] Added tanstack react table with dynamic pagination --- .../[slug]/components/propertyTable.tsx | 56 +++++++++- .../components/propertyTableColumns.tsx | 17 ++- .../components/propertyTablePagination.tsx | 105 ++++++++++++++++++ src/app/portfolio/[slug]/page.tsx | 41 ++----- 4 files changed, 179 insertions(+), 40 deletions(-) create mode 100644 src/app/portfolio/[slug]/components/propertyTablePagination.tsx diff --git a/src/app/portfolio/[slug]/components/propertyTable.tsx b/src/app/portfolio/[slug]/components/propertyTable.tsx index 2b6bbb25..730cc61b 100644 --- a/src/app/portfolio/[slug]/components/propertyTable.tsx +++ b/src/app/portfolio/[slug]/components/propertyTable.tsx @@ -5,6 +5,7 @@ import { SortingState, flexRender, getCoreRowModel, + getPaginationRowModel, getSortedRowModel, useReactTable, } from "@tanstack/react-table"; @@ -18,10 +19,32 @@ import { TableRow, } from "@/app/shadcn_components/ui/table"; import { useState } from "react"; +import { DataTablePagination } from "./propertyTablePagination"; +import { Property } from "./propertyTableColumns"; +import React from "react"; interface DataTableProps { - columns: ColumnDef[]; - data: TData[]; + columns: ColumnDef[]; + data: Property[]; +} + +function fetchData(offset: number) { + // Because this is a client component, this will be handled with react query + let properties: Property[] = []; + for (let i = offset; i <= offset + 20; i++) { + properties.push({ + id: i, + portfolioId: 1, + address: `${i}23 Fake Street`, + postcode: `AB${i} 2CD`, + loadingStatus: Math.random() < 0.5 ? "complete" : "loading", + status: "assessment", + targetEpc: "C", + cost: 1000, + }); + } + + return properties; } export default function DataTable({ @@ -29,15 +52,34 @@ export default function DataTable({ columns, }: DataTableProps) { const [sorting, setSorting] = useState([]); + const [tableData, setTableData] = useState(data); + const [offset, setOffset] = useState(0); + const [currentPageIndex, setCurrentPageIndex] = useState(0); + + // add page change handlers for DataTablePagination + const loadPaginatedData = () => { + const newData = fetchData(offset); + if (newData) { + console.log("loadPaginatedData"); + setTableData([...tableData, ...newData]); + setOffset(offset + 1); + return true; + } + + return false; + }; const table = useReactTable({ - data, + data: tableData, columns, getCoreRowModel: getCoreRowModel(), onSortingChange: setSorting, getSortedRowModel: getSortedRowModel(), + getPaginationRowModel: getPaginationRowModel(), + state: { sorting, + pagination: { pageIndex: currentPageIndex, pageSize: 7 }, }, }); @@ -49,7 +91,7 @@ export default function DataTable({ {headerGroup.headers.map((header) => { return ( - + {header.isPlaceholder ? null : flexRender( @@ -85,6 +127,12 @@ export default function DataTable({ )} + ); } diff --git a/src/app/portfolio/[slug]/components/propertyTableColumns.tsx b/src/app/portfolio/[slug]/components/propertyTableColumns.tsx index c967776c..f30f166c 100644 --- a/src/app/portfolio/[slug]/components/propertyTableColumns.tsx +++ b/src/app/portfolio/[slug]/components/propertyTableColumns.tsx @@ -13,6 +13,7 @@ import { Button } from "@/app/shadcn_components/ui/button"; import { ArrowUpDown, MoreHorizontal } from "lucide-react"; import StatusBadge from "@/app/components/StatusBadge"; import { HomeIcon } from "@heroicons/react/20/solid"; +import { formatNumber } from "@/app/utils"; export type Property = { id: number; @@ -22,6 +23,7 @@ export type Property = { loadingStatus: string; status: string; targetEpc: string; + cost: number; }; export const columns: ColumnDef[] = [ @@ -80,15 +82,11 @@ export const columns: ColumnDef[] = [ const cost = parseFloat(row.getValue("cost")); const loadingStatus = row.original.loadingStatus; - console.log("loadingStatus", loadingStatus); if (loadingStatus === "loading") { return
; } - const formatted = new Intl.NumberFormat("en-UK", { - style: "currency", - currency: "GBP", - }).format(cost); + const formatted = "£" + formatNumber(cost); return (
@@ -137,7 +135,7 @@ export const columns: ColumnDef[] = [ Actions navigator.clipboard.writeText(payment.id)} - className="cursor-pointer" + className="text-gray-700 cursor-pointer" > [] = [ Building Passport + + + Settings + { + table: Table; + loadPaginatedData: () => void; + currentPageIndex: number; + setCurrentPageIndex: (index: number) => void; +} + +export function DataTablePagination({ + table, + loadPaginatedData, + currentPageIndex, + setCurrentPageIndex, +}: DataTablePaginationProps) { + // Check if the user has reached the last page + + const requestMoreData = () => { + // Check if the next page is the last one + if ( + table.getState().pagination.pageIndex + 1 === + table.getPageCount() - 1 + ) { + console.log("requesting more data"); + loadPaginatedData(); + } + }; + + const goToFinalPage = () => { + console.log("Go to final page"); + // Check if the next page is the last one + loadPaginatedData(); + }; + + return ( +
+
+
+ Page {table.getState().pagination.pageIndex + 1} of{" "} + {table.getPageCount()} +
+
+ + + + +
+
+
+ ); +} diff --git a/src/app/portfolio/[slug]/page.tsx b/src/app/portfolio/[slug]/page.tsx index 5bee4f72..46405dc4 100644 --- a/src/app/portfolio/[slug]/page.tsx +++ b/src/app/portfolio/[slug]/page.tsx @@ -10,20 +10,12 @@ import { Toolbar } from "@/app/components/portfolio/Toolbar"; import DataTable from "@/app/portfolio/[slug]/components/propertyTable"; import { columns, - Payment, + Property, } from "@/app/portfolio/[slug]/components/propertyTableColumns"; // We enfore caching of data for 60 seconds export const revalidate = 60; -type Property = { - id: string; - address: string; - postcode: string; - loadingStatus: string; - status: (typeof PortfolioStatus)[number]; -}; - function EmptyPropertyState() { return (
@@ -223,31 +215,20 @@ export default async function Page({ // TODO: TEMP // let properties: Property[]; - let properties: {}[]; + let properties: Property[] = []; if (pageStatus === "loading") { - properties = [ - { - id: 1, - portfolioId: portfolioId, - address: "123 Fake Street", - postcode: "AB1 2CD", - loadingStatus: "loading", + for (let i = 1; i <= 20; i++) { + properties.push({ + id: i, + portfolioId: 1, + address: `${i}23 Fake Street`, + postcode: `AB${i} 2CD`, + loadingStatus: Math.random() < 0.5 ? "complete" : "loading", status: "assessment", targetEpc: "C", - }, - { - id: 2, - portfolioId: portfolioId, - address: "223 Fake Street", - postcode: "AB1 2CD", - loadingStatus: "complete", cost: 1000, - status: "assessment", - targetEpc: "C", - }, - ]; - } else { - properties = []; + }); + } } return (