import React, { useState } from "react"; import { base44 } from "@/api/base44Client"; import { useQuery } from "@tanstack/react-query"; import { Link } from "react-router-dom"; import { createPageUrl } from "@/utils"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { UserPlus, Users, LayoutGrid, List as ListIcon, Phone, MapPin, Calendar, Star } from "lucide-react"; import FilterBar from "@/components/staff/FilterBar"; import StaffCard from "@/components/staff/StaffCard"; import EmployeeCard from "@/components/staff/EmployeeCard"; import PageHeader from "@/components/common/PageHeader"; export default function StaffDirectory() { const [searchTerm, setSearchTerm] = useState(""); const [departmentFilter, setDepartmentFilter] = useState("all"); const [locationFilter, setLocationFilter] = useState("all"); const [viewMode, setViewMode] = useState("grid"); // "grid" or "list" const { data: user } = useQuery({ queryKey: ['current-user'], queryFn: () => base44.auth.me(), }); const { data: staff, isLoading } = useQuery({ queryKey: ['staff'], queryFn: () => base44.entities.Staff.list('-created_date'), initialData: [], }); const { data: events } = useQuery({ queryKey: ['events-for-staff-filter'], queryFn: () => base44.entities.Event.list(), initialData: [], enabled: !!user }); const visibleStaff = React.useMemo(() => { const userRole = user?.user_role || user?.role; if (['admin', 'procurement'].includes(userRole)) { return staff; } if (['operator', 'sector'].includes(userRole)) { return staff; } if (userRole === 'vendor') { return staff.filter(s => s.vendor_id === user?.id || s.vendor_name === user?.company_name || s.created_by === user?.email ); } if (userRole === 'client') { const clientEvents = events.filter(e => e.client_email === user?.email || e.business_name === user?.company_name || e.created_by === user?.email ); const assignedStaffIds = new Set(); clientEvents.forEach(event => { if (event.assigned_staff) { event.assigned_staff.forEach(assignment => { if (assignment.staff_id) { assignedStaffIds.add(assignment.staff_id); } }); } }); return staff.filter(s => assignedStaffIds.has(s.id)); } if (userRole === 'workforce') { return staff; } return staff; }, [staff, user, events]); const uniqueDepartments = [...new Set(visibleStaff.map(s => s.department).filter(Boolean))]; const uniqueLocations = [...new Set(visibleStaff.map(s => s.hub_location).filter(Boolean))]; const filteredStaff = visibleStaff.filter(member => { const matchesSearch = !searchTerm || member.employee_name?.toLowerCase().includes(searchTerm.toLowerCase()) || member.position?.toLowerCase().includes(searchTerm.toLowerCase()) || member.manager?.toLowerCase().includes(searchTerm.toLowerCase()); const matchesDepartment = departmentFilter === "all" || member.department === departmentFilter; const matchesLocation = locationFilter === "all" || member.hub_location === locationFilter; return matchesSearch && matchesDepartment && matchesLocation; }); const canAddStaff = ['admin', 'procurement', 'operator', 'sector', 'vendor'].includes(user?.user_role || user?.role); const getPageTitle = () => { const userRole = user?.user_role || user?.role; if (userRole === 'vendor') return "My Staff Directory"; if (userRole === 'client') return "Event Staff Directory"; if (userRole === 'workforce') return "Team Directory"; return "Staff Directory"; }; const getPageSubtitle = () => { const userRole = user?.user_role || user?.role; if (userRole === 'vendor') return `${filteredStaff.length} of your staff members`; if (userRole === 'client') return `${filteredStaff.length} staff assigned to your events`; if (userRole === 'workforce') return `${filteredStaff.length} team members`; return `${filteredStaff.length} ${filteredStaff.length === 1 ? 'member' : 'members'} found`; }; const getCoverageColor = (percentage) => { if (!percentage) return "bg-red-100 text-red-700"; if (percentage >= 90) return "bg-green-100 text-green-700"; if (percentage >= 50) return "bg-yellow-100 text-yellow-700"; return "bg-red-100 text-red-700"; }; return (
) : null } />
{isLoading ? (
{[...Array(9)].map((_, i) => (
))}
) : filteredStaff.length > 0 ? ( <> {viewMode === "grid" && (
{filteredStaff.map((member) => ( ))}
)} {viewMode === "list" && (
{filteredStaff.map((member) => ( ))}
Employee Primary Skill Secondary Skill Rating Reliability Coverage Cancellations Manager Location
{member.employee_name?.charAt(0) || '?'}

{member.employee_name}

{member.contact_number && (

{member.contact_number}

)}
{member.position || '—'} {member.position_2 || '—'}
{member.rating ? member.rating.toFixed(1) : '0.0'}
= 90 ? 'bg-green-100 text-green-700' : (member.reliability_score || 0) >= 70 ? 'bg-yellow-100 text-yellow-700' : (member.reliability_score || 0) >= 50 ? 'bg-orange-100 text-orange-700' : 'bg-red-100 text-red-700' } font-semibold`}> {member.reliability_score || 0}% {member.shift_coverage_percentage || 0}% 0 ? "text-red-600 border-red-300" : "text-slate-600"}> {member.cancellation_count || 0} {member.manager || '—'} {member.hub_location && (
{member.hub_location}
)}
)} ) : (

No Staff Members Found

{visibleStaff.length === 0 ? "No staff members available to display" : "Try adjusting your filters"}

{canAddStaff && ( )}
)}
); }