feat: add entry links to Tag template

This commit is contained in:
Thomas Bishop 2025-07-29 17:56:00 +01:00
parent 8ab2aa77a6
commit c098bfc044
2 changed files with 142 additions and 102 deletions

View file

@ -1,113 +1,112 @@
import { import {
flexRender, flexRender,
getCoreRowModel, getCoreRowModel,
useReactTable, useReactTable,
getPaginationRowModel, getPaginationRowModel,
SortingState, getSortedRowModel,
getSortedRowModel,
} from "@tanstack/react-table" } from "@tanstack/react-table"
import { Button } from "./ui/button" import { Button } from "./ui/button"
import { import {
Table, Table,
TableBody, TableBody,
TableCell, TableCell,
TableHead, TableHead,
TableHeader, TableHeader,
TableRow, TableRow,
} from "@/components/ui/table" } from "@/components/ui/table"
import { useState } from "react" import { useState } from "react"
export function DataTable({ columns, data, loading }) { export function DataTable({ columns, data, loading }) {
const [sorting, setSorting] = useState([]) const [sorting, setSorting] = useState([])
const table = useReactTable({ const table = useReactTable({
data, data,
columns, columns,
getCoreRowModel: getCoreRowModel(), getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(), getPaginationRowModel: getPaginationRowModel(),
onSortingChange: setSorting, onSortingChange: setSorting,
getSortedRowModel: getSortedRowModel(), getSortedRowModel: getSortedRowModel(),
state: { state: {
sorting, sorting,
}, },
}) })
const pageCount = table.getPageCount() const pageCount = table.getPageCount()
const currentPage = table.getState().pagination?.pageIndex const currentPage = table.getState().pagination?.pageIndex
return ( return (
<div> <div>
<div className="rounded-none border"> <div className="rounded-none border">
<Table> <Table>
<TableHeader> <TableHeader>
{table.getHeaderGroups().map((headerGroup) => ( {table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}> <TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => { {headerGroup.headers.map((header) => {
return ( return (
<TableHead key={header.id}> <TableHead key={header.id}>
{header.isPlaceholder {header.isPlaceholder
? null ? null
: flexRender( : flexRender(
header.column.columnDef.header, header.column.columnDef.header,
header.getContext(), header.getContext(),
)} )}
</TableHead> </TableHead>
) )
})} })}
</TableRow> </TableRow>
))} ))}
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{table.getRowModel().rows?.length ? ( {table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => ( table.getRowModel().rows.map((row) => (
<TableRow key={row.id} data-state={row.getIsSelected() && "selected"}> <TableRow key={row.id} data-state={row.getIsSelected() && "selected"}>
{row.getVisibleCells().map((cell) => ( {row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}> <TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())} {flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell> </TableCell>
))} ))}
</TableRow> </TableRow>
)) ))
) : loading ? ( ) : loading ? (
<TableRow> <TableRow>
<TableCell colSpan={columns.length} className="h-24 text-center"> <TableCell colSpan={columns.length} className="h-24 text-center">
Loading... Loading...
</TableCell> </TableCell>
</TableRow> </TableRow>
) : ( ) : (
<TableRow> <TableRow>
<TableCell colSpan={columns.length} className="h-24 text-center"> <TableCell colSpan={columns.length} className="h-24 text-center">
No results. No results.
</TableCell> </TableCell>
</TableRow> </TableRow>
)} )}
</TableBody> </TableBody>
</Table> </Table>
</div> </div>
<div className="flex items-center justify-end space-x-2 py-4 gap-2"> <div className="flex items-center justify-end space-x-2 py-4 gap-2">
<div> <div>
<span className="text-sm text-muted-foreground">{`${currentPage + 1} of ${pageCount}`}</span> <span className="text-sm text-muted-foreground">{`${currentPage + 1} of ${pageCount}`}</span>
</div> </div>
<div> <div>
<Button <Button
className="rounded-none" className="rounded-none"
variant="outline" variant="outline"
size="sm" size="sm"
onClick={() => table.previousPage()} onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()} disabled={!table.getCanPreviousPage()}
> >
Previous Previous
</Button> </Button>
<Button <Button
variant="outline" variant="outline"
className="rounded-none" className="rounded-none"
size="sm" size="sm"
onClick={() => table.nextPage()} onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()} disabled={!table.getCanNextPage()}
> >
Next Next
</Button> </Button>
</div> </div>
</div> </div>
</div> </div>
) )
} }

View file

@ -1,7 +1,47 @@
import { useParams } from "react-router" import { useParams } from "react-router"
import Page from "./Page" import Page from "./Page"
import { useQuery } from "@tanstack/react-query"
import api from "@/api/eolas-api"
import { DataTable } from "@/components/DataTable"
import { ArrowUpDown } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Link } from "react-router"
const columns = [
{
accessorKey: "entry_title",
header: ({ column }) => {
return (
<Button
variant="ghost"
className="rounded-none"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Title
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
)
},
cell: ({ cell, row }) => {
return (
<Link to={`/entries/${row.original.entry_title}`}>
<span className="text-foreground underline-offset-3 underline hover:text-gray-700 dark:hover:text-green-300">
{row.original.entry_title.replace(/_/g, " ")}
</span>
</Link>
)
},
},
]
export default function Tag() { export default function Tag() {
const { tag } = useParams() const { tag } = useParams()
const { data, isLoading } = useQuery({
queryKey: [`entries_for_tag_${tag}`],
queryFn: () => api.get(`/entries/tag/${tag}`).then((res) => res.data),
})
return ( return (
<Page <Page
titleComponent={ titleComponent={
@ -10,6 +50,7 @@ export default function Tag() {
<span>{tag}</span> <span>{tag}</span>
</> </>
} }
pageBody={<DataTable columns={columns} data={data?.data || []} loading={isLoading} />}
/> />
) )
} }