"use client"; import React, { useState, useMemo } from "react"; import { AgGridReact } from "ag-grid-react"; import { ColDef, ModuleRegistry, AllCommunityModule } from "ag-grid-community"; import "ag-grid-community/styles/ag-grid.css"; import "ag-grid-community/styles/ag-theme-alpine.css"; import { formatDate } from "@/lib/utils"; ModuleRegistry.registerModules([AllCommunityModule]); interface User { id: string; email: string; firstName: string; lastName: string; role: string; phone?: string; createdAt: Date; client?: { id: string; membershipType: string; membershipStatus: string; joinDate: Date; lastVisit?: Date; }; } interface UserGridProps { users: User[]; onUserSelect?: (user: User) => void; onEditUser?: (user: User) => void; onDeleteUser?: (user: User) => void; onBulkDelete?: (users: User[]) => void; loading?: boolean; } export function UserGrid({ users, onUserSelect, onEditUser, onDeleteUser, onBulkDelete, loading = false, }: UserGridProps) { const [selectedUsers, setSelectedUsers] = useState([]); const [searchQuery, setSearchQuery] = useState(""); const columnDefs: ColDef[] = useMemo( () => [ { headerName: "Name", valueGetter: (params) => `${params.data?.firstName} ${params.data?.lastName}`, filter: "agTextColumnFilter", sortable: true, minWidth: 150, }, { headerName: "Email", field: "email", filter: "agTextColumnFilter", sortable: true, minWidth: 200, }, { headerName: "Role", field: "role", filter: "agTextColumnFilter", sortable: true, cellRenderer: (params: any) => { const roleColors = { admin: "bg-purple-100 text-purple-800", trainer: "bg-blue-100 text-blue-800", client: "bg-green-100 text-green-800", }; const colorClass = roleColors[params.value as keyof typeof roleColors] || "bg-gray-100 text-gray-800"; return `${params.value}`; }, minWidth: 120, }, { headerName: "Phone", field: "phone", filter: "agTextColumnFilter", sortable: true, minWidth: 130, }, { headerName: "Membership", valueGetter: (params) => params.data?.client?.membershipType || "N/A", filter: "agTextColumnFilter", sortable: true, cellRenderer: (params: any) => { if (!params.value || params.value === "N/A") return "N/A"; const membershipColors = { vip: "bg-yellow-100 text-yellow-800", premium: "bg-blue-100 text-blue-800", basic: "bg-gray-100 text-gray-800", }; const colorClass = membershipColors[params.value as keyof typeof membershipColors] || "bg-gray-100 text-gray-800"; return `${params.value}`; }, minWidth: 120, }, { headerName: "Status", valueGetter: (params) => params.data?.client?.membershipStatus || "N/A", filter: "agTextColumnFilter", sortable: true, cellRenderer: (params: any) => { if (!params.value || params.value === "N/A") return "N/A"; const statusColors = { active: "bg-green-100 text-green-800", inactive: "bg-red-100 text-red-800", suspended: "bg-yellow-100 text-yellow-800", }; const colorClass = statusColors[params.value as keyof typeof statusColors] || "bg-gray-100 text-gray-800"; return `${params.value}`; }, minWidth: 120, }, { headerName: "Join Date", valueGetter: (params) => params.data?.client?.joinDate || params.data?.createdAt, filter: "agDateColumnFilter", sortable: true, valueFormatter: (params: any) => formatDate(new Date(params.value)), minWidth: 120, }, { headerName: "Last Visit", valueGetter: (params) => params.data?.client?.lastVisit, filter: "agDateColumnFilter", sortable: true, valueFormatter: (params: any) => params.value ? formatDate(new Date(params.value)) : "Never", minWidth: 120, }, ], [], ); const defaultColDef: ColDef = useMemo( () => ({ flex: 1, resizable: true, floatingFilter: true, suppressMenu: true, }), [], ); const gridRef = React.useRef>(null); const gridOptions = { theme: "legacy" as const, columnDefs, defaultColDef, rowData: users, rowSelection: { mode: "multiRow" as const }, onSelectionChanged: () => { const selectedNodes = gridRef.current?.api.getSelectedNodes(); const selectedData = selectedNodes ?.map((node) => node.data) .filter((data): data is User => data !== undefined) || []; setSelectedUsers(selectedData); if (selectedData.length === 1 && onUserSelect) { onUserSelect(selectedData[0]); } }, suppressRowClickSelection: false, animateRows: true, loading: loading, pagination: true, paginationPageSize: 20, paginationPageSizeSelector: [10, 20, 50, 100], quickFilterText: searchQuery, }; const handleEdit = () => { if (selectedUsers.length === 1 && onEditUser) { onEditUser(selectedUsers[0]); } }; const handleDelete = () => { if (selectedUsers.length === 1 && onDeleteUser) { onDeleteUser(selectedUsers[0]); } }; const handleBulkDelete = () => { if (selectedUsers.length > 0 && onBulkDelete) { onBulkDelete(selectedUsers); } }; return (
setSearchQuery(e.target.value)} />
{...gridOptions} ref={gridRef} />
); }