import type { ColumnDef, FilterFn } from '@tanstack/vue-table' import { ArrowUpDown, Pencil, Trash2 } from '@lucide/vue' import { h } from 'vue' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from '@/components/ui/tooltip' export interface User { id: string email: string username: string status: string profile: { full_name: string phone: string | null address: string | null pob: string | null dob: string | null } | null created_at: string } const statusConfig: Record = { ACTIVE: { label: 'Aktif', class: 'border-emerald-500 text-emerald-600 bg-emerald-50' }, ONBOARDING: { label: 'Onboarding', class: 'border-blue-500 text-blue-600 bg-blue-50' }, INACTIVE: { label: 'Nonaktif', class: 'border-gray-500 text-gray-600 bg-gray-50' }, SUSPENDED: { label: 'Ditangguhkan', class: 'border-orange-500 text-orange-600 bg-orange-50' }, DISABLED: { label: 'Dinonaktifkan', class: 'border-red-500 text-red-600 bg-red-50' }, } const searchFilter: FilterFn = (row, _columnId, filterValue) => { const search = (filterValue as string).toLowerCase() const email = (row.original.email as string).toLowerCase() const username = (row.original.username as string).toLowerCase() const name = (row.original.profile?.full_name ?? '').toLowerCase() return email.includes(search) || username.includes(search) || name.includes(search) } export function getColumns(callbacks: { onEdit: (user: User) => void onDelete: (user: User) => void }): ColumnDef[] { return [ { id: 'search', accessorFn: row => row.email, header: 'Akun', cell: ({ row }) => h('div', { class: 'flex flex-col' }, [ h('span', { class: 'font-medium' }, row.original.email), h('span', { class: 'text-xs text-muted-foreground' }, `@${row.original.username}`), ]), filterFn: searchFilter, enableHiding: false, }, { accessorFn: row => row.profile?.full_name ?? '-', id: 'full_name', header: 'Nama Lengkap', cell: ({ row }) => h('div', { class: 'text-muted-foreground' }, row.original.profile?.full_name ?? '-'), }, { accessorFn: row => row.profile?.phone ?? '-', id: 'phone', header: 'No. Telepon', cell: ({ row }) => h('div', { class: 'text-muted-foreground' }, row.original.profile?.phone ?? '-'), }, { accessorKey: 'status', header: 'Status', cell: ({ row }) => { const cfg = statusConfig[row.original.status] ?? { label: row.original.status, class: '' } return h(Badge, { variant: 'outline', class: cfg.class, }, () => cfg.label) }, }, { id: 'actions', header: ' ', size: 0, minSize: 0, enableHiding: false, cell: ({ row }) => { const user = row.original return h(TooltipProvider, null, () => h('div', { class: 'flex items-center gap-1' }, [ h(Tooltip, null, () => [ h(TooltipTrigger, { asChild: true }, () => h(Button, { variant: 'ghost', size: 'icon', class: 'h-8 w-8 text-yellow-500', onClick: () => callbacks.onEdit(user), }, () => h(Pencil, { class: 'h-4 w-4' }) ) ), h(TooltipContent, null, () => 'Edit'), ]), h(Tooltip, null, () => [ h(TooltipTrigger, { asChild: true }, () => h(Button, { variant: 'ghost', size: 'icon', class: 'h-8 w-8 text-destructive', onClick: () => callbacks.onDelete(user), }, () => h(Trash2, { class: 'h-4 w-4' }) ) ), h(TooltipContent, null, () => 'Hapus'), ]), ]) ) }, }, ] }