"use client"; import { type ColumnDef } from "@tanstack/react-table"; import { formatDistanceToNow } from "date-fns"; import { MoreHorizontal, Eye, Edit, Trash2, Copy, User, Mail, TestTube, } from "lucide-react"; import Link from "next/link"; import { Badge } from "~/components/ui/badge"; import { Button } from "~/components/ui/button"; import { Checkbox } from "~/components/ui/checkbox"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "~/components/ui/dropdown-menu"; import { DataTableColumnHeader } from "~/components/ui/data-table-column-header"; import { toast } from "sonner"; export type Participant = { id: string; participantCode: string; email: string | null; name: string | null; consentGiven: boolean; consentDate: Date | null; createdAt: Date; trialCount: number; userRole?: "owner" | "researcher" | "wizard" | "observer"; canEdit?: boolean; canDelete?: boolean; }; function ParticipantActionsCell({ participant }: { participant: Participant }) { const handleDelete = async () => { if ( window.confirm( `Are you sure you want to delete participant "${participant.name ?? participant.participantCode}"?`, ) ) { try { // TODO: Implement delete participant mutation toast.success("Participant deleted successfully"); } catch { toast.error("Failed to delete participant"); } } }; const handleCopyId = () => { void navigator.clipboard.writeText(participant.id); toast.success("Participant ID copied to clipboard"); }; const handleCopyCode = () => { void navigator.clipboard.writeText(participant.participantCode); toast.success("Participant code copied to clipboard"); }; return ( Open menu Actions View Details {participant.canEdit && ( Edit Participant )} Copy Participant ID Copy Participant Code {!participant.consentGiven && ( Send Consent Form )} {participant.canDelete && ( <> Delete Participant > )} ); } export const participantsColumns: ColumnDef[] = [ { id: "select", header: ({ table }) => ( table.toggleAllPageRowsSelected(!!value)} aria-label="Select all" /> ), cell: ({ row }) => ( row.toggleSelected(!!value)} aria-label="Select row" /> ), enableSorting: false, enableHiding: false, }, { accessorKey: "participantCode", header: ({ column }) => ( ), cell: ({ row }) => ( {row.getValue("participantCode")} ), }, { accessorKey: "name", header: ({ column }) => ( ), cell: ({ row }) => { const name = row.getValue("name") as string | null; const email = row.original.email; return ( {name ?? "No name provided"} {email && ( {email} )} ); }, }, { accessorKey: "consentGiven", header: ({ column }) => ( ), cell: ({ row }) => { const consentGiven = row.getValue("consentGiven"); const consentDate = row.original.consentDate; if (consentGiven) { return ( Consented ); } return ( Pending ); }, filterFn: (row, id, value) => { const consentGiven = row.getValue(id) as boolean; if (value === "consented") return !!consentGiven; if (value === "pending") return !consentGiven; return true; }, }, { accessorKey: "trialCount", header: ({ column }) => ( ), cell: ({ row }) => { const trialCount = row.getValue("trialCount") as number; return ( {trialCount as number} ); }, }, { accessorKey: "createdAt", header: ({ column }) => ( ), cell: ({ row }) => { const date = row.getValue("createdAt") as Date; return ( {formatDistanceToNow(date, { addSuffix: true })} ); }, }, { id: "actions", header: "Actions", cell: ({ row }) => , enableSorting: false, enableHiding: false, }, ];