"use client"; import { Button } from "@app/components/ui/button"; import { ControlledDataTable, type ExtendedColumnDef } from "@app/components/ui/controlled-data-table"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@app/components/ui/dropdown-menu"; import { useNavigationContext } from "@app/hooks/useNavigationContext"; import { toast } from "@app/hooks/useToast"; import { getNextSortOrder, getSortDirection } from "@app/lib/sortColumn"; import { type PaginationState } from "@tanstack/react-table"; import { ArrowDown01Icon, ArrowRight, ArrowUp10Icon, ChevronsUpDownIcon, MoreHorizontal } from "lucide-react"; import moment from "moment"; import { useTranslations } from "next-intl"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { useMemo, useTransition } from "react"; import { useDebouncedCallback } from "use-debounce"; export type OrgRow = { orgId: string; name: string; subnet: string | null; createdAt: string | null; userCount: number; siteCount: number; resourceCount: number; }; type OrgTableProps = { orgs: OrgRow[]; pagination: PaginationState; rowCount: number; }; export default function OrgsTable({ orgs, pagination, rowCount }: OrgTableProps) { const router = useRouter(); const t = useTranslations(); const { navigate: filter, isNavigating: isFiltering, searchParams } = useNavigationContext(); const [isRefreshing, startTransition] = useTransition(); function refreshData() { startTransition(async () => { try { router.refresh(); } catch (error) { toast({ title: t("error"), description: t("refreshError"), variant: "destructive" }); } }); } function toggleSort(column: string) { const newSearch = getNextSortOrder(column, searchParams); filter({ searchParams: newSearch }); } function sortableHeader(column: string, label: string) { const sortOrder = getSortDirection(column, searchParams); const Icon = sortOrder === "asc" ? ArrowDown01Icon : sortOrder === "desc" ? ArrowUp10Icon : ChevronsUpDownIcon; return ( ); } const columns = useMemo[]>(() => { return [ { accessorKey: "name", friendlyName: t("name"), enableHiding: false, header: () => sortableHeader("name", t("name")) }, { accessorKey: "createdAt", friendlyName: t("createdAt"), header: () => sortableHeader("createdAt", t("createdAt")), cell: ({ row }) => { const createdAt = row.original.createdAt; return ( {createdAt ? moment(createdAt).format("lll") : "-"} ); } }, { accessorKey: "orgId", friendlyName: t("orgId"), header: () => {t("orgId")} }, { accessorKey: "subnet", friendlyName: t("subnet"), header: () => {t("subnet")}, cell: ({ row }) => {row.original.subnet || "-"} }, { accessorKey: "userCount", friendlyName: t("users"), header: () => {t("users")}, cell: ({ row }) => ( {row.original.userCount} ) }, { accessorKey: "siteCount", friendlyName: t("sites"), header: () => {t("sites")}, cell: ({ row }) => ( {row.original.siteCount} ) }, { accessorKey: "resourceCount", friendlyName: t("resources"), header: () => {t("resources")}, cell: ({ row }) => ( {row.original.resourceCount} ) }, { id: "actions", enableHiding: false, header: () => , cell: ({ row }) => { const orgRow = row.original; return (
); } } ]; }, [t, searchParams]); const handlePaginationChange = (newPage: PaginationState) => { searchParams.set("page", (newPage.pageIndex + 1).toString()); searchParams.set("pageSize", newPage.pageSize.toString()); filter({ searchParams }); }; const handleSearchChange = useDebouncedCallback((query: string) => { searchParams.set("query", query); searchParams.delete("page"); filter({ searchParams }); }, 300); return ( ); }