"use client"; import { useState } from "react"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { useRouter } from "next/navigation"; import { ColumnDef } from "@tanstack/react-table"; import { Badge } from "@/shared/components/ds/badge"; import { Button } from "@/shared/components/ui/button"; import { MoreHorizontal, Eye, Edit, Trash, ChevronsUpDown, ChevronUp, ChevronDown, } from "lucide-react"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/shared/components/ui/dropdown-menu"; import Image from "next/image"; import { getFileThumbnailUrl } from "@/shared/utils/file"; import newsApi from "@/shared/services/news"; import { toast } from "sonner"; import { hasPermission } from "@/shared/config/role"; import { useAuthSession } from "@/shared/hooks/use-session"; import { DeleteDialog } from "../../_components/delete-dialog"; import { News } from "@/shared/types/news"; // adjust the path if needed interface ColumnConfig { id: string; header: string; accessor?: keyof News; // eslint-disable-next-line @typescript-eslint/no-explicit-any accessorFn?: (row: News) => any; sortable?: boolean; // eslint-disable-next-line @typescript-eslint/no-explicit-any cell?: (value: any) => React.ReactNode; } const COLUMN_CONFIGS: ColumnConfig[] = [ { id: "name", header: "Judul Konten", accessor: "name", sortable: true, }, { id: "thumbnail", header: "Thumbnail", accessor: "thumbnail", sortable: false, cell: (value) => value ? (
Thumbnail
) : null, }, { id: "is_active", header: "Status", accessor: "is_active", sortable: true, cell: (value) => ( {value ? "Aktif" : "Tidak Aktif"} ), }, ]; export const useNewsColumns = (): ColumnDef[] => { const router = useRouter(); const [newsToDelete, setNewsToDelete] = useState(null); const queryClient = useQueryClient(); const { session } = useAuthSession(); const userRole = session?.user?.role; const deleteMutation = useMutation({ mutationFn: async (id: string) => { return await newsApi.deleteNews(id); }, onSuccess: () => { toast.success("Berhasil menghapus konten"); queryClient.invalidateQueries({ queryKey: ["news"] }); setNewsToDelete(null); }, onError: (error) => { toast.error("Gagal menghapus konten"); console.error("Error deleting news:", error); }, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any const renderSortableHeader = (column: any, label: string) => ( ); const baseColumns = COLUMN_CONFIGS.map((config) => { const column: ColumnDef = { id: config.id, header: ({ column }) => config.sortable ? renderSortableHeader(column, config.header) : config.header, ...(config.accessor && { accessorKey: config.accessor }), ...(config.accessorFn && { accessorFn: config.accessorFn }), cell: ({ row }) => { const value = row.getValue(config.id); return config.cell ? ( config.cell(value) ) : (
{value as React.ReactNode}
); }, enableSorting: config.sortable !== false, enableHiding: config.id !== "select" && config.id !== "actions", }; return column; }); if ( userRole && (hasPermission(userRole, "news", "read") || hasPermission(userRole, "news", "update") || hasPermission(userRole, "news", "delete")) ) { baseColumns.push({ id: "actions", enableHiding: false, cell: ({ row }) => { const news = row.original; return ( <> Aksi {hasPermission(userRole, "news", "read") && ( router.push(`/admin/news/detail/${news.id}`)} className="flex items-center gap-2" > Lihat Detail )} {hasPermission(userRole, "news", "update") && ( router.push(`/admin/news/edit/${news.id}`)} className="flex items-center gap-2" > Edit Konten )} {hasPermission(userRole, "news", "delete") && ( <> setNewsToDelete(news)} className="flex items-center gap-2 text-destructive focus:text-destructive" > Hapus Konten )} {newsToDelete && newsToDelete?.id === news.id && ( deleteMutation.mutate(newsToDelete.id!)} onCancel={() => setNewsToDelete(null)} open={true} /> )} ); }, }); } return baseColumns; };