'use client'; import { useEffect, useMemo, useRef, useState } from 'react'; import { useRouter } from 'next/navigation'; import { Search, Filter, Loader2, Mail, Phone, MapPin, Plus, RefreshCw, Download, FileSpreadsheet, ChevronDown, MoreVertical, ExternalLink, } from 'lucide-react'; import { toast } from 'sonner'; import { userService, UserResponse } from '@/services/api/userService'; import { ViewModeToggle } from '@/components/ui/ViewModeToggle'; import { CustomSelect } from '@/components/ui/CustomSelect'; import { TablePagination, useClientPagination } from '@/components/ui/TablePagination'; const ROLES = [ { id: '01KXRF5VQ1GQ58RDRX45BY9X1D', name: 'Super Admin' }, { id: '01KXRF5VQ2X83NF2950KTMZT45', name: 'Admin' }, { id: '01KXRF5VQ2X83NF2950KTMZT46', name: 'Technician' }, { id: '01KXRF5VQ3QPM1CJZ679R152CQ', name: 'Sales' }, { id: '01KXRF5VQ4Z7YXKKX83VSR532Q', name: 'Customer Support' }, ]; const DEPARTMENTS = [ { id: '01KXRF5VQ5NB1GN907TGZZ3C9Q', name: 'Administration' }, { id: '01KXRF5VQ6D0NJC1RT6422QT0Y', name: 'Technical Repair' }, { id: '01KXRF5VQ6D0NJC1RT6422QT0Z', name: 'Sales & Billing' }, { id: '01KXRF5VQ74CRWS1951WETKC38', name: 'Support Desk' }, ]; const DESIGNATIONS = [ { id: '01KXRF5VQ8GXRR9JEMNW6VS215', name: 'General Administrator' }, { id: '01KXRF5VQ92Q2DA0VED445M6PJ', name: 'Senior Technician' }, { id: '01KXRF5VQ92Q2DA0VED445M6PK', name: 'Junior Technician' }, { id: '01KXRF5VQ92Q2DA0VED445M6PM', name: 'Billing Representative' }, ]; export default function StaffDirectoryPage() { const router = useRouter(); const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [search, setSearch] = useState(''); const [roleFilter, setRoleFilter] = useState(''); const [sortBy, setSortBy] = useState('name'); const [viewMode, setViewMode] = useState<'table' | 'grid'>('grid'); const [showFilters, setShowFilters] = useState(false); const [draftRole, setDraftRole] = useState(''); const [draftSort, setDraftSort] = useState('name'); const [openMenuId, setOpenMenuId] = useState(null); const filterRef = useRef(null); const fetchUsers = async () => { setLoading(true); try { const data = await userService.getAll(0, 100); setUsers(data); } catch { toast.error('Failed to load staff directory'); } finally { setLoading(false); } }; useEffect(() => { fetchUsers(); }, []); useEffect(() => { if (!showFilters) return; const onPointerDown = (event: MouseEvent) => { if (!filterRef.current?.contains(event.target as Node)) setShowFilters(false); }; document.addEventListener('mousedown', onPointerDown); return () => document.removeEventListener('mousedown', onPointerDown); }, [showFilters]); useEffect(() => { if (!openMenuId) return; const onPointerDown = () => setOpenMenuId(null); document.addEventListener('mousedown', onPointerDown); return () => document.removeEventListener('mousedown', onPointerDown); }, [openMenuId]); const getRoleName = (roleId: string) => ROLES.find((r) => r.id === roleId)?.name || 'Staff Member'; const getDeptName = (deptId: string) => DEPARTMENTS.find((d) => d.id === deptId)?.name || 'Operations'; const getDesigName = (desigId: string) => DESIGNATIONS.find((d) => d.id === desigId)?.name || ''; const sortedUsers = useMemo(() => { const q = search.trim().toLowerCase(); const filtered = users.filter((u) => { const fullName = `${u.first_name} ${u.last_name}`.toLowerCase(); const roleName = getRoleName(u.role_id).toLowerCase(); const matchesSearch = !q || fullName.includes(q) || u.email.toLowerCase().includes(q) || (u.phone || '').toLowerCase().includes(q) || roleName.includes(q); const matchesRole = roleFilter ? u.role_id === roleFilter : true; return matchesSearch && matchesRole; }); return [...filtered].sort((a, b) => { if (sortBy === 'role') { return getRoleName(a.role_id).localeCompare(getRoleName(b.role_id)); } return `${a.first_name} ${a.last_name}`.localeCompare(`${b.first_name} ${b.last_name}`); }); }, [users, search, roleFilter, sortBy]); const pager = useClientPagination(sortedUsers); const filtersActive = Boolean(roleFilter); const handleExportCSV = () => { const headers = ['Name', 'Role', 'Department', 'Email', 'Phone', 'Status']; const rows = sortedUsers.map((u) => [ `${u.first_name} ${u.last_name}`, getRoleName(u.role_id), getDeptName(u.department_id), u.email, u.phone || '', u.is_active ? 'Active' : 'Inactive', ]); const csv = [headers, ...rows] .map((row) => row.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(',')) .join('\n'); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = 'staff-directory.csv'; link.click(); URL.revokeObjectURL(url); }; const dataCardShell = 'crm-radius-section border border-border bg-card shadow-[0_1px_3px_rgba(16,24,40,0.06)] overflow-visible min-w-0'; const labelClass = 'block text-[11px] font-semibold text-muted-foreground uppercase mb-1.5'; const primaryButton = 'inline-flex items-center justify-center gap-2 h-9 px-4 crm-radius-control bg-primary hover:bg-primary/90 text-white text-[13px] font-semibold cursor-pointer disabled:opacity-50'; const secondaryButton = 'inline-flex items-center justify-center gap-2 h-9 px-4 crm-radius-control border border-border bg-card text-foreground text-[13px] font-medium hover:bg-muted cursor-pointer disabled:opacity-50'; const initials = (user: UserResponse) => `${user.first_name.charAt(0).toUpperCase()}${user.last_name.charAt(0).toUpperCase()}`; return (

Staff Directory

{users.length}
{showFilters && (
({ value: r.id, label: r.name })), ]} />
)}
setSearch(e.target.value)} className="w-full h-9 pl-8 pr-3 crm-radius-control border border-border bg-card text-[13px] text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-primary transition-colors" />
{loading ? (
) : sortedUsers.length === 0 ? (
No staff found matching your criteria.
) : viewMode === 'grid' ? (
{pager.items.map((user) => { const roleName = getRoleName(user.role_id); const title = getDesigName(user.designation_id) || roleName; return (
{initials(user)}

{user.first_name} {user.last_name}

{title}

e.stopPropagation()}> {openMenuId === user.user_id && (
)}

{user.email}

{user.phone || '—'}

{getDeptName(user.department_id)}

{user.is_active ? 'Active' : 'Inactive'} {roleName}
{user.phone && ( )}
{initials(user)}
); })}
) : (
{pager.items.map((user) => ( ))}
Staff member Role Department Email Last activity
{initials(user)}
{user.first_name} {user.last_name}
{getRoleName(user.role_id)} {getDeptName(user.department_id)} {user.email} {user.last_activity || 'No recent activity'}
)}
); }