feat(ui): stub WIP list table

This commit is contained in:
Collin Barrett 2025-06-17 17:47:46 -05:00
parent 3e8bfd769f
commit 009e1ad795
2 changed files with 120 additions and 2 deletions

View file

@ -1,3 +1,16 @@
export default function Home() {
return <main className="p-8 gap-16 sm:p-20"></main>;
import { FilterlistTable, Filterlist } from "@/components/filterlist-table";
const getFilterlists = async (): Promise<Filterlist[]> => {
const res = await fetch("https://api.filterlists.com/lists");
if (!res.ok) throw new Error("Failed to fetch lists");
return res.json();
};
export default async function Home() {
const filterlists = await getFilterlists();
return (
<main className="pt-4 p-8 gap-16 sm:p-20 sm:pt-8">
<FilterlistTable filterlists={filterlists} />
</main>
);
}

View file

@ -0,0 +1,105 @@
"use client";
import * as React from "react";
import {
ColumnDef,
useReactTable,
getCoreRowModel,
flexRender,
} from "@tanstack/react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
export type Filterlist = {
id: number;
name: string;
};
interface FilterlistTableProps {
filterlists: Filterlist[];
}
const columns: ColumnDef<Filterlist>[] = [
{
accessorKey: "name",
header: "Name",
cell: (info) => info.getValue(),
},
];
export function FilterlistTable({ filterlists }: FilterlistTableProps) {
const [page, setPage] = React.useState(0);
const pageSize = 10;
const pageCount = Math.ceil(filterlists.length / pageSize);
const pagedData = React.useMemo(
() => filterlists.slice(page * pageSize, (page + 1) * pageSize),
[filterlists, page, pageSize],
);
const table = useReactTable({
data: pagedData,
columns,
getCoreRowModel: getCoreRowModel(),
});
return (
<div className="space-y-2">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows.map((row) => (
<TableRow key={row.id}>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
<div className="flex items-center justify-between gap-2">
<Button
variant="outline"
size="sm"
onClick={() => setPage((p) => Math.max(0, p - 1))}
disabled={page === 0}
>
Previous
</Button>
<span className="text-sm">
Page {page + 1} of {pageCount}
</span>
<Button
variant="outline"
size="sm"
onClick={() => setPage((p) => Math.min(pageCount - 1, p + 1))}
disabled={page >= pageCount - 1}
>
Next
</Button>
</div>
</div>
);
}