MIF_E31221222/sigap-website/app/protected/(admin-pages)/_components/users/column.tsx

233 lines
7.3 KiB
TypeScript

"use client";
import { useMemo } from "react";
import { type ColumnDef } from "@tanstack/react-table";
import { ArrowUpDown, Filter, MoreVertical } from "lucide-react";
import { Button } from "@/app/_components/ui/button";
import { Checkbox } from "@/app/_components/ui/checkbox";
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/app/_components/ui/dropdown-menu";
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/app/_components/ui/avatar";
import { User } from "@/types/user";
interface ColumnOptions {
openEditSheet: (user: User) => void;
handleRoleFilter: (role: string) => void;
handleStatusFilter: (status: string) => void;
}
export const useColumns = ({
openEditSheet,
handleRoleFilter,
handleStatusFilter,
}: ColumnOptions) => {
// Use useMemo to prevent unnecessary re-creation of columns array
const columns = useMemo<ColumnDef<User>[]>(
() => [
{
id: "select",
header: ({ table }) => (
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && "indeterminate")
}
onCheckedChange={(value) =>
table.toggleAllPageRowsSelected(!!value)
}
aria-label="Select all"
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="Select row"
/>
),
enableSorting: false,
enableHiding: false,
},
{
accessorKey: "usersColoumn",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() =>
column.toggleSorting(column.getIsSorted() === "asc")
}
>
Users
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
cell: ({ row }) => {
const user = row.original;
return (
<div className="flex items-center space-x-4">
<Avatar>
<AvatarImage
src={user.avatar}
alt={`${user.firstName} ${user.lastName}`}
/>
<AvatarFallback>
{user.firstName[0]}
{user.lastName[0]}
</AvatarFallback>
</Avatar>
<div>
<div className="font-medium">
{user.firstName} {user.lastName}
</div>
<div className="text-sm text-muted-foreground">
{user.email}
</div>
</div>
</div>
);
},
filterFn: (row, id, filterValue) => {
const searchTerm = filterValue.toLowerCase();
const user = row.original;
return (
user.firstName.toLowerCase().includes(searchTerm) ||
user.lastName.toLowerCase().includes(searchTerm) ||
user.email.toLowerCase().includes(searchTerm)
);
},
},
{
accessorKey: "role",
header: ({ column }) => {
return (
<div className="flex items-center space-x-2">
<span>Role</span>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="sm" className="h-8 w-8 p-0">
<Filter className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Filter by Role</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => handleRoleFilter("all")}>
All
</DropdownMenuItem>
<DropdownMenuItem onClick={() => handleRoleFilter("admin")}>
Admin
</DropdownMenuItem>
<DropdownMenuItem onClick={() => handleRoleFilter("staff")}>
Staff
</DropdownMenuItem>
<DropdownMenuItem onClick={() => handleRoleFilter("user")}>
User
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
);
},
},
{
accessorKey: "status",
header: ({ column }) => {
return (
<div className="flex items-center space-x-2">
<span>Status</span>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="sm" className="h-8 w-8 p-0">
<Filter className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Filter by Status</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => handleStatusFilter("all")}>
All
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => handleStatusFilter("active")}
>
Active
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => handleStatusFilter("inactive")}
>
Inactive
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
);
},
cell: ({ row }) => {
const status = row.getValue("status") as string;
return (
<div
className={`capitalize ${status === "active" ? "text-green-600" : "text-red-600"}`}
>
{status}
</div>
);
},
},
{
accessorKey: "lastSignedIn",
header: "Last Sign In",
},
{
id: "actions",
cell: ({ row }) => {
const user = row.original;
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open menu</span>
<MoreVertical className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem
onClick={() => navigator.clipboard.writeText(user.id)}
>
Copy user ID
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => openEditSheet(user)}>
Edit user
</DropdownMenuItem>
<DropdownMenuItem className="text-red-600">
Delete user
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
],
[openEditSheet, handleRoleFilter, handleStatusFilter]
);
return columns;
};