completed paginated Component

This commit is contained in:
PxlLoewe
2025-02-07 00:15:11 +01:00
parent be5128053f
commit 42023f9bb2
4 changed files with 102 additions and 17 deletions

View File

@@ -1,27 +1,41 @@
import SortableTable, { SortableTableProps } from './Table';
'use client';
import { useEffect, useState } from 'react';
import SortableTable, { Pagination, SortableTableProps } from './Table';
import { PrismaClient } from '@repo/db';
import { getData } from './pagiantedTableActions';
interface PaginatedTableProps<TData>
extends Omit<SortableTableProps<TData>, 'data'> {
prismaGetter: (
fnProps: {
cursor: number;
take: number;
} & any
) => Promise<any>;
prismaModel: keyof PrismaClient;
rowsPerPage?: number;
}
export async function PaginatedTable<TData>({
prismaGetter,
export function PaginatedTable<TData>({
prismaModel,
rowsPerPage = 10,
...restProps
}: PaginatedTableProps<TData>) {
const data = await prismaGetter({
cursor: 0,
take: 10,
});
const [data, setData] = useState<TData[]>([]);
const [page, setPage] = useState(0);
const [total, setTotal] = useState(0);
useEffect(() => {
getData(prismaModel, rowsPerPage, page * rowsPerPage).then((result) => {
if (result) {
setData(result.data);
setTotal(result.total);
}
});
}, [page]);
return (
<div>
<div className="space-y-4">
<SortableTable data={data} {...restProps} />
<Pagination
totalPages={Math.ceil(total / rowsPerPage)}
page={page}
setPage={setPage}
/>
</div>
);
}

View File

@@ -8,7 +8,7 @@ import {
SortingState,
flexRender,
} from '@tanstack/react-table';
import { ChevronDown, ChevronUp } from 'lucide-react'; // Icons for sorting
import { ArrowLeft, ArrowRight, ChevronDown, ChevronUp } from 'lucide-react'; // Icons for sorting
export interface SortableTableProps<TData> {
data: TData[];
@@ -73,3 +73,44 @@ export default function SortableTable<TData>({
</div>
);
}
export const Pagination = ({
page,
totalPages,
setPage,
}: {
page: number;
totalPages: number;
setPage: (page: number) => void;
}) => {
if (totalPages === 0) return null;
return (
<div className="join w-full justify-end">
<button
className="join-item btn"
disabled={page === 0}
onClick={() => setPage(page - 1)}
>
<ArrowLeft size={16} />
</button>
<select
className="select join-item"
value={page}
onChange={(e) => setPage(Number(e.target.value))}
>
{Array.from({ length: totalPages }).map((_, i) => (
<option key={i} value={i}>
{i + 1}
</option>
))}
</select>
<button
className="join-item btn"
disabled={page === totalPages - 1}
onClick={() => page < totalPages && setPage(page + 1)}
>
<ArrowRight size={16} />
</button>
</div>
);
};

View File

@@ -0,0 +1,24 @@
'use server';
import { PrismaClient } from '@repo/db';
export const getData = async (
prismaModelName: keyof PrismaClient,
take: number,
skip: number
) => {
const prisma = new PrismaClient();
if (
!prismaModelName ||
!prisma[prismaModelName] ||
!('findMany' in prisma[prismaModelName])
)
return;
const model = prisma[prismaModelName] as any;
if (!model.findMany || !model.count) return;
const data = await model.findMany({
take,
skip,
});
const total = await model.count();
return { data, total };
};

View File

@@ -1,6 +1,6 @@
import Link from 'next/link';
import { PrismaClient } from '@repo/db';
import { PaginatedTable } from '../app/_components/PaginatedTable';
import { PaginatedTable } from './_components/PaginatedTable';
export default async function Home() {
const prisma = new PrismaClient();
@@ -12,12 +12,17 @@ export default async function Home() {
<button className="btn">Logout</button>
</Link>
<PaginatedTable
prismaGetter={prisma.user.findMany}
rowsPerPage={10}
prismaModel={'user'}
columns={[
{
header: 'ID',
accessorKey: 'id',
},
{
header: 'Email',
accessorKey: 'email',
},
{
header: 'First Name',
accessorKey: 'firstname',
@@ -25,6 +30,7 @@ export default async function Home() {
{
header: 'Last Name',
accessorKey: 'lastname',
footer: 'Total',
},
]}
/>