import { useSuspenseQuery } from "@tanstack/react-query"; import { flexRender, getCoreRowModel, getFilteredRowModel, getSortedRowModel, type ColumnDef, type ColumnFiltersState, type SortingState, useReactTable, } from "@tanstack/react-table"; import { HardDrive, Plus, RotateCcw } from "lucide-react"; import { useState } from "react"; import { listVolumesOptions } from "~/client/api-client/@tanstack/react-query.gen"; import { DataTableSortHeader } from "~/client/components/data-table-sort-header"; import { EmptyState } from "~/client/components/empty-state"; import { StatusDot } from "~/client/components/status-dot"; import { Button } from "~/client/components/ui/button"; import { Card } from "~/client/components/ui/card"; import { Input } from "~/client/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "~/client/components/ui/select"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/client/components/ui/table"; import { VolumeIcon } from "~/client/components/volume-icon"; import type { VolumeStatus } from "~/client/lib/types"; import { useNavigate } from "@tanstack/react-router"; import { cn } from "~/client/lib/utils"; const getVolumeStatusVariant = (status: VolumeStatus): "success" | "neutral" | "error" | "warning" => { const statusMap = { mounted: "success" as const, unmounted: "neutral" as const, error: "error" as const, unknown: "warning" as const, }; return statusMap[status]; }; type VolumeRow = { shortId: string; name: string; type: "directory" | "nfs" | "smb" | "webdav" | "sftp" | "rclone"; status: VolumeStatus; }; const volumeColumns: ColumnDef[] = [ { accessorKey: "name", header: ({ column }) => , cell: ({ row }) => (
{row.original.name}
), }, { accessorKey: "type", header: ({ column }) => ( ), cell: ({ row }) => , filterFn: (row, id, value) => row.getValue(id) === value, }, { accessorKey: "status", header: ({ column }) => ( ), cell: ({ row }) => , filterFn: (row, id, value) => row.getValue(id) === value, }, ]; export function VolumesPage() { const [columnFilters, setColumnFilters] = useState([]); const [sorting, setSorting] = useState([]); const navigate = useNavigate(); const { data } = useSuspenseQuery({ ...listVolumesOptions() }); const table = useReactTable({ data, columns: volumeColumns, state: { columnFilters, sorting }, onColumnFiltersChange: setColumnFilters, onSortingChange: setSorting, getCoreRowModel: getCoreRowModel(), getFilteredRowModel: getFilteredRowModel(), getSortedRowModel: getSortedRowModel(), }); const rows = table.getRowModel().rows; const hasFilters = columnFilters.length > 0; const clearFilters = () => table.resetColumnFilters(); const hasNoVolumes = data.length === 0; const hasNoFilteredVolumes = rows.length === 0 && !hasNoVolumes; if (hasNoVolumes) { return ( navigate({ to: "/volumes/create" })}> Create Volume } /> ); } const search = (table.getColumn("name")?.getFilterValue() as string) ?? ""; const status = (table.getColumn("status")?.getFilterValue() as string) ?? ""; const type = (table.getColumn("type")?.getFilterValue() as string) ?? ""; return (
table.getColumn("name")?.setFilterValue(e.target.value)} /> {hasFilters && ( )}
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} ))} ))}

No volumes match your filters.

{rows.map((row) => ( navigate({ to: `/volumes/${row.original.shortId}` })} > {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} ))}
{hasNoFilteredVolumes ? ( "No volumes match filters." ) : ( {rows.length} volume {rows.length > 1 ? "s" : ""} )}
); }