'use client'; import { useState, useEffect } from 'react'; import { Department, Squad, StaffMember, SCOPE_DEFINITIONS } from '@/lib/types/staff'; import { getStaff, getDepartments, getSquads, updateStaffRole, moveStaff, deactivateStaff } from '@/lib/actions/staff-management'; import { getEffectiveScopes } from '@/lib/auth/permissions'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; import { InviteStaffDialog } from '../dialogs/InviteStaffDialog'; import { toast } from 'sonner'; import { Loader2, Search, MoreHorizontal, UserCog, ArrowRightLeft, UserX, Crown, Shield, ShieldCheck, Eye } from 'lucide-react'; export function StaffDirectory() { const [staff, setStaff] = useState([]); const [departments, setDepartments] = useState([]); const [squads, setSquads] = useState([]); const [loading, setLoading] = useState(true); const [search, setSearch] = useState(''); const [filterDept, setFilterDept] = useState('all'); const [filterRole, setFilterRole] = useState('all'); const loadData = async () => { setLoading(true); try { const [staffRes, deptRes, sqRes] = await Promise.all([getStaff(), getDepartments(), getSquads()]); if (staffRes.success) setStaff(staffRes.data); if (deptRes.success) setDepartments(deptRes.data); if (sqRes.success) setSquads(sqRes.data); } finally { setLoading(false); } }; useEffect(() => { loadData(); }, []); const getDeptName = (id: string | null) => departments.find(d => d.id === id)?.name || '—'; const getDeptColor = (id: string | null) => departments.find(d => d.id === id)?.color || '#666'; const getSquadName = (id: string | null) => squads.find(s => s.id === id)?.name || '—'; const handleRoleChange = async (staffId: string, newRole: 'MANAGER' | 'MEMBER') => { const res = await updateStaffRole(staffId, newRole); if (res.success) { toast.success(res.message); loadData(); } else toast.error(res.message); }; const handleMove = async (staffId: string, newSquadId: string) => { const res = await moveStaff(staffId, newSquadId); if (res.success) { toast.success(res.message); loadData(); } else toast.error(res.message); }; const handleDeactivate = async (staffId: string) => { const res = await deactivateStaff(staffId); if (res.success) { toast.success('Staff deactivated'); loadData(); } else toast.error(res.message); }; const filtered = staff.filter(s => { if (search && !s.name.toLowerCase().includes(search.toLowerCase()) && !s.email.toLowerCase().includes(search.toLowerCase())) return false; if (filterDept !== 'all' && s.departmentId !== filterDept) return false; if (filterRole !== 'all' && s.role !== filterRole) return false; return true; }); if (loading) { return (
Loading staff directory...
); } return (
{/* Header */}

Staff Directory

{staff.filter(s => s.status === 'active').length} active, {staff.filter(s => s.status === 'invited').length} invited

{/* Filters */}
setSearch(e.target.value)} className="pl-9" />
{/* Table */}
{filtered.map(member => ( ))} {filtered.length === 0 && ( )}
Name Email Department Squad Role Status Actions
{member.name.split(' ').map(n => n[0]).join('')}
{member.name}
{member.email} {member.departmentId ? ( {getDeptName(member.departmentId)} ) : } {getSquadName(member.squadId)} {member.role === 'SUPER_ADMIN' && Super Admin} {member.role === 'MANAGER' && Manager} {member.role === 'MEMBER' && Member} {member.status === 'active' && Active} {member.status === 'invited' && Invited} {member.status === 'deactivated' && Deactivated} {member.role !== 'SUPER_ADMIN' && ( Manage handleRoleChange(member.id, member.role === 'MANAGER' ? 'MEMBER' : 'MANAGER')}> {member.role === 'MANAGER' ? 'Demote to Member' : 'Promote to Manager'} Move to Squad {squads.filter(s => s.id !== member.squadId).map(sq => ( handleMove(member.id, sq.id)}> {sq.name} ))} {member.status !== 'deactivated' && ( handleDeactivate(member.id)}> Deactivate )} )}
No staff found.
); }