"use client"; import { Button } from "@app/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@app/components/ui/dropdown-menu"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { useNavigationContext } from "@app/hooks/useNavigationContext"; import { toast } from "@app/hooks/useToast"; import { createApiClient, formatAxiosError } from "@app/lib/api"; import { type PaginationState } from "@tanstack/react-table"; import { ArrowDown01Icon, ArrowUp10Icon, ChevronsUpDownIcon, MoreHorizontal, PencilIcon, PencilLineIcon } from "lucide-react"; import { useTranslations } from "next-intl"; import { usePathname, useRouter } from "next/navigation"; import { useActionState, useMemo, useState, useTransition } from "react"; import { useDebouncedCallback } from "use-debounce"; import { ControlledDataTable, type ExtendedColumnDef } from "./ui/controlled-data-table"; import { LabelBadge } from "./label-badge"; import { getNextSortOrder, getSortDirection } from "@app/lib/sortColumn"; import { cn } from "@app/lib/cn"; import ConfirmDeleteDialog from "./ConfirmDeleteDialog"; import { CreateOrgLabelDialog } from "./CreateOrgLabelDialog"; import { EditOrgLabelDialog } from "./EditOrgLabelDialog"; export type LabelRow = { labelId: number; name: string; color: string; }; type OrgLabelsTableProps = { labels: LabelRow[]; pagination: PaginationState; orgId: string; rowCount: number; }; export default function OrgLabelsTable({ labels, orgId, pagination, rowCount }: OrgLabelsTableProps) { const router = useRouter(); const { navigate: filter, isNavigating: isFiltering, searchParams } = useNavigationContext(); const [selectedLabel, setSelectedLabel] = useState(null); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); const [isEditModalOpen, setIsEditModalOpen] = useState(false); const [isRefreshing, startTransition] = useTransition(); const api = createApiClient(useEnvContext()); const t = useTranslations(); function refreshData() { startTransition(async () => { try { router.refresh(); } catch { toast({ title: t("error"), description: t("refreshError"), variant: "destructive" }); } }); } 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); const columns = useMemo[]>( () => [ { accessorKey: "name", enableHiding: false, header: () => { return {t("name")}; }, cell: ({ row }) => (
{row.original.name}
) }, { accessorKey: "actions", enableHiding: false, header: () => { return {t("actions")}; }, cell: ({ row }) => ( { setSelectedLabel(row.original); setIsEditModalOpen(true); }} > {t("edit")} { setSelectedLabel(row.original); setIsDeleteModalOpen(true); }} > {t("delete")} ) } ], [searchParams, t] ); function deleteLabel(label: LabelRow) { startTransition(async () => { await api .delete(`/org/${orgId}/label/${label.labelId}`) .catch((e) => { toast({ variant: "destructive", title: t("labelErrorDelete"), description: formatAxiosError(e, t("labelErrorDelete")) }); }) .then(() => { router.refresh(); setIsDeleteModalOpen(false); }); }); } return ( <> {selectedLabel && ( <> { setIsDeleteModalOpen(val); setSelectedLabel(null); }} dialog={

{t("labelQuestionRemove")}

{t("labelMessageRemove")}

} buttonText={t("labelDeleteConfirm")} onConfirm={async () => deleteLabel(selectedLabel)} string={selectedLabel.name} title={t("labelDelete")} /> startTransition(() => router.refresh()) } label={selectedLabel} /> )} startTransition(() => router.refresh())} /> setIsCreateModalOpen(true)} tableId="org-labels-table" searchPlaceholder={t("labelSearch")} pagination={pagination} onPaginationChange={handlePaginationChange} searchQuery={searchParams.get("query")?.toString()} onSearch={handleSearchChange} onRefresh={refreshData} isRefreshing={isRefreshing || isFiltering} rowCount={rowCount} /> ); }