← full-stack-fastapi-template / frontend/src/routes/_layout/items.tsx
| 1 | import { useSuspenseQuery } from "@tanstack/react-query" |
| 2 | import { createFileRoute } from "@tanstack/react-router" |
| 3 | import { Search } from "lucide-react" |
| 4 | import { Suspense } from "react" |
| 5 | |
| 6 | import { ItemsService } from "@/client" |
| 7 | import { DataTable } from "@/components/Common/DataTable" |
| 8 | import AddItem from "@/components/Items/AddItem" |
| 9 | import { columns } from "@/components/Items/columns" |
| 10 | import PendingItems from "@/components/Pending/PendingItems" |
| 11 | |
| 12 | function getItemsQueryOptions() { |
| 13 | return { |
| 14 | queryFn: () => ItemsService.readItems({ skip: 0, limit: 100 }), |
| 15 | queryKey: ["items"], |
| 16 | } |
| 17 | } |
| 18 | |
| 19 | export const Route = createFileRoute("/_layout/items")({ |
| 20 | component: Items, |
| 21 | head: () => ({ |
| 22 | meta: [ |
| 23 | { |
| 24 | title: "Items - FastAPI Template", |
| 25 | }, |
| 26 | ], |
| 27 | }), |
| 28 | }) |
| 29 | |
| 30 | function ItemsTableContent() { |
| 31 | const { data: items } = useSuspenseQuery(getItemsQueryOptions()) |
| 32 | |
| 33 | if (items.data.length === 0) { |
| 34 | return ( |
| 35 | <div className="flex flex-col items-center justify-center text-center py-12"> |
| 36 | <div className="rounded-full bg-muted p-4 mb-4"> |
| 37 | <Search className="h-8 w-8 text-muted-foreground" /> |
| 38 | </div> |
| 39 | <h3 className="text-lg font-semibold">You don't have any items yet</h3> |
| 40 | <p className="text-muted-foreground">Add a new item to get started</p> |
| 41 | </div> |
| 42 | ) |
| 43 | } |
| 44 | |
| 45 | return <DataTable columns={columns} data={items.data} /> |
| 46 | } |
| 47 | |
| 48 | function ItemsTable() { |
| 49 | return ( |
| 50 | <Suspense fallback={<PendingItems />}> |
| 51 | <ItemsTableContent /> |
| 52 | </Suspense> |
| 53 | ) |
| 54 | } |
| 55 | |
| 56 | function Items() { |
| 57 | return ( |
| 58 | <div className="flex flex-col gap-6"> |
| 59 | <div className="flex items-center justify-between"> |
| 60 | <div> |
| 61 | <h1 className="text-2xl font-bold tracking-tight">Items</h1> |
| 62 | <p className="text-muted-foreground">Create and manage your items</p> |
| 63 | </div> |
| 64 | <AddItem /> |
| 65 | </div> |
| 66 | <ItemsTable /> |
| 67 | </div> |
| 68 | ) |
| 69 | } |
| 70 |