import React, { useState, useMemo } from "react"; import { base44 } from "@/api/base44Client"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Progress } from "@/components/ui/progress"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { Award, Search, Plus, AlertTriangle, CheckCircle2, Clock, XCircle, Download, Send, Eye, Edit2, ShieldCheck, FileText, Sparkles, Calendar, User, Building2, ChevronRight, Filter, Bell, TrendingUp } from "lucide-react"; import { format, differenceInDays, parseISO } from "date-fns"; import { useToast } from "@/components/ui/use-toast"; import { motion, AnimatePresence } from "framer-motion"; const REQUIRED_CERTIFICATIONS = ["Background Check", "RBS", "Food Handler"]; const CERT_CONFIG = { "Background Check": { color: "from-purple-500 to-purple-600", bgColor: "bg-purple-50", textColor: "text-purple-700", borderColor: "border-purple-200", icon: ShieldCheck, description: "Criminal background verification" }, "RBS": { color: "from-blue-500 to-blue-600", bgColor: "bg-blue-50", textColor: "text-blue-700", borderColor: "border-blue-200", icon: Award, description: "Responsible Beverage Server" }, "Food Handler": { color: "from-emerald-500 to-emerald-600", bgColor: "bg-emerald-50", textColor: "text-emerald-700", borderColor: "border-emerald-200", icon: FileText, description: "Food safety certification" }, }; export default function Certification() { const { toast } = useToast(); const queryClient = useQueryClient(); const [searchTerm, setSearchTerm] = useState(""); const [activeTab, setActiveTab] = useState("all"); const [certTypeFilter, setCertTypeFilter] = useState("all"); const [showAddModal, setShowAddModal] = useState(false); const [editingCert, setEditingCert] = useState(null); const [showReportModal, setShowReportModal] = useState(false); const [selectedEmployee, setSelectedEmployee] = useState(null); const { data: user } = useQuery({ queryKey: ['current-user-cert'], queryFn: () => base44.auth.me(), }); const { data: certifications = [] } = useQuery({ queryKey: ['certifications'], queryFn: () => base44.entities.Certification.list(), initialData: [], }); const { data: staff = [] } = useQuery({ queryKey: ['staff-for-cert'], queryFn: () => base44.entities.Staff.list(), initialData: [], }); const userRole = user?.user_role || user?.role || "admin"; const isVendor = userRole === "vendor"; const isProcurement = userRole === "procurement"; const calculateStatus = (expiryDate) => { if (!expiryDate) return "pending"; const days = differenceInDays(parseISO(expiryDate), new Date()); if (days < 0) return "expired"; if (days <= 30) return "expiring_soon"; return "current"; }; const processedCerts = useMemo(() => { return certifications.map(cert => ({ ...cert, days_until_expiry: cert.expiry_date ? differenceInDays(parseISO(cert.expiry_date), new Date()) : null, status: calculateStatus(cert.expiry_date), })); }, [certifications]); const employeeCertMap = useMemo(() => { const map = {}; staff.forEach(s => { map[s.id] = { employee_id: s.id, employee_name: s.employee_name, vendor_id: s.vendor_id, vendor_name: s.vendor_name, position: s.position, certifications: { "Background Check": null, "RBS": null, "Food Handler": null }, allCurrent: false, hasExpired: false, hasExpiringSoon: false, missingCount: 3, canWork: false, complianceScore: 0, }; }); processedCerts.forEach(cert => { const key = cert.employee_id; if (!map[key]) { map[key] = { employee_id: cert.employee_id, employee_name: cert.employee_name, vendor_id: cert.vendor_id, vendor_name: cert.vendor_name, position: "", certifications: { "Background Check": null, "RBS": null, "Food Handler": null }, allCurrent: false, hasExpired: false, hasExpiringSoon: false, missingCount: 3, canWork: false, complianceScore: 0, }; } if (REQUIRED_CERTIFICATIONS.includes(cert.certification_type)) { map[key].certifications[cert.certification_type] = cert; } }); Object.values(map).forEach(emp => { const certs = Object.values(emp.certifications); const validCerts = certs.filter(c => c && c.status === "current"); const expiredCerts = certs.filter(c => c && c.status === "expired"); const expiringSoonCerts = certs.filter(c => c && c.status === "expiring_soon"); const missingCerts = certs.filter(c => !c); emp.allCurrent = validCerts.length === 3; emp.hasExpired = expiredCerts.length > 0; emp.hasExpiringSoon = expiringSoonCerts.length > 0; emp.missingCount = missingCerts.length; emp.canWork = validCerts.length === 3 || (validCerts.length + expiringSoonCerts.length === 3); emp.complianceScore = Math.round(((validCerts.length + expiringSoonCerts.length * 0.5) / 3) * 100); }); return map; }, [processedCerts, staff]); const employeeList = Object.values(employeeCertMap); const filteredEmployees = useMemo(() => { let filtered = employeeList; if (isVendor && user?.vendor_id) { filtered = filtered.filter(e => e.vendor_id === user.vendor_id); } if (searchTerm) { filtered = filtered.filter(e => e.employee_name?.toLowerCase().includes(searchTerm.toLowerCase()) ); } if (activeTab === "compliant") filtered = filtered.filter(e => e.allCurrent); else if (activeTab === "expiring") filtered = filtered.filter(e => e.hasExpiringSoon); else if (activeTab === "expired") filtered = filtered.filter(e => e.hasExpired); else if (activeTab === "incomplete") filtered = filtered.filter(e => e.missingCount > 0); if (certTypeFilter !== "all") { filtered = filtered.filter(e => { const cert = e.certifications[certTypeFilter]; return cert !== null; }); } return filtered; }, [employeeList, searchTerm, activeTab, certTypeFilter, isVendor, user]); const stats = useMemo(() => { const total = employeeList.length; const compliant = employeeList.filter(e => e.allCurrent).length; const expiring = employeeList.filter(e => e.hasExpiringSoon).length; const expired = employeeList.filter(e => e.hasExpired).length; const incomplete = employeeList.filter(e => e.missingCount > 0).length; const avgCompliance = total > 0 ? Math.round(employeeList.reduce((sum, e) => sum + e.complianceScore, 0) / total) : 0; return { total, compliant, expiring, expired, incomplete, avgCompliance }; }, [employeeList]); const saveCertMutation = useMutation({ mutationFn: async (data) => { if (data.id) return base44.entities.Certification.update(data.id, data); return base44.entities.Certification.create(data); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['certifications'] }); setShowAddModal(false); setEditingCert(null); toast({ title: "✅ Certification saved" }); }, }); const sendExpiryAlert = async (cert) => { try { await base44.integrations.Core.SendEmail({ to: user?.email || "admin@company.com", subject: `⚠️ Certification Expiring: ${cert.employee_name} - ${cert.certification_type}`, body: `

Certification Expiring Alert

Employee: ${cert.employee_name}

Certification: ${cert.certification_type}

Expiry Date: ${format(parseISO(cert.expiry_date), 'MMM d, yyyy')}

Days Until Expiry: ${cert.days_until_expiry} days

` }); toast({ title: "✅ Alert sent" }); } catch (error) { toast({ title: "Failed to send alert", variant: "destructive" }); } }; const sendComplianceReport = async (clientEmail) => { const compliantEmployees = employeeList.filter(e => e.allCurrent); try { await base44.integrations.Core.SendEmail({ to: clientEmail, subject: "Staff Compliance Report", body: `

Staff Compliance Report

Generated: ${format(new Date(), 'MMM d, yyyy')}

Total Staff: ${stats.total}

Fully Compliant: ${stats.compliant}

Average Compliance: ${stats.avgCompliance}%


Compliant Staff

` }); toast({ title: "✅ Report sent" }); setShowReportModal(false); } catch (error) { toast({ title: "Failed to send report", variant: "destructive" }); } }; return (
{/* Hero Header */}

Certification Hub

Track & manage workforce compliance

{(isVendor || userRole === "admin") && ( )}
{/* Stats Row */}
Total Staff

{stats.total}

Compliant

{stats.compliant}

Expiring 30d

{stats.expiring}

Expired

{stats.expired}

Avg. Compliance

{stats.avgCompliance}%

{/* Filters Bar */}
setSearchTerm(e.target.value)} className="pl-10 h-11 bg-slate-50 border-slate-200 rounded-xl" />
All ✓ Compliant ⏰ 30 Days ✗ Expired Missing
{/* Employee Cards Grid */}
{filteredEmployees.length === 0 ? (

No employees found

Try adjusting your search or filters

) : ( filteredEmployees.map((emp, idx) => ( { setEditingCert({ employee_id: emp.employee_id, employee_name: emp.employee_name, vendor_id: emp.vendor_id, vendor_name: emp.vendor_name, certification_type: type, }); setShowAddModal(true); }} onEditCert={(cert) => { setEditingCert(cert); setShowAddModal(true); }} onSendAlert={sendExpiryAlert} showVendor={isProcurement || userRole === "admin"} /> )) )}
{/* Add/Edit Modal */} {editingCert?.id ? 'Update' : 'Add'} Certification {editingCert?.employee_name && ( For: {editingCert.employee_name} )} saveCertMutation.mutate(data)} onCancel={() => { setShowAddModal(false); setEditingCert(null); }} isLoading={saveCertMutation.isPending} /> {/* Report Modal */} Send Compliance Report setShowReportModal(false)} stats={stats} />
); } function EmployeeCertCard({ employee, onAddCert, onEditCert, onSendAlert, showVendor }) { const emp = employee; return ( {/* Header */}
{emp.employee_name?.charAt(0)}

{emp.employee_name}

{emp.position || "Staff Member"}

{emp.canWork ? "Can Work" : "Cannot Work"}
{/* Compliance Progress */}
Compliance Score {emp.complianceScore}%
{/* Certifications */}
{REQUIRED_CERTIFICATIONS.map(type => { const cert = emp.certifications[type]; const config = CERT_CONFIG[type]; const Icon = config.icon; return (

{type}

{cert ? (

{cert.status === "expired" ? "Expired" : `Expires: ${format(parseISO(cert.expiry_date), 'MMM d, yyyy')}`} {cert.days_until_expiry !== null && cert.days_until_expiry >= 0 && ` (${cert.days_until_expiry}d)`}

) : (

Not uploaded

)}
{cert ? ( <> {cert.status === "current" && ( )} {cert.status === "expiring_soon" && ( )} {cert.status === "expired" && ( )} ) : ( )}
); })}
{/* Footer */} {showVendor && emp.vendor_name && (
{emp.vendor_name}
)}
); } function CertificationForm({ certification, staff, onSave, onCancel, isLoading }) { const [formData, setFormData] = useState({ employee_id: certification?.employee_id || "", employee_name: certification?.employee_name || "", vendor_id: certification?.vendor_id || "", vendor_name: certification?.vendor_name || "", certification_type: certification?.certification_type || "", issue_date: certification?.issue_date || "", expiry_date: certification?.expiry_date || "", issuer: certification?.issuer || "", certificate_number: certification?.certificate_number || "", notes: certification?.notes || "", ...certification, }); const handleSubmit = (e) => { e.preventDefault(); onSave(formData); }; const handleStaffSelect = (staffId) => { const selectedStaff = staff.find(s => s.id === staffId); if (selectedStaff) { setFormData(prev => ({ ...prev, employee_id: staffId, employee_name: selectedStaff.employee_name, vendor_id: selectedStaff.vendor_id, vendor_name: selectedStaff.vendor_name, })); } }; return (
{!certification?.employee_id && (
)}
setFormData(prev => ({ ...prev, issue_date: e.target.value }))} className="mt-1.5" />
setFormData(prev => ({ ...prev, expiry_date: e.target.value }))} className="mt-1.5" required />
setFormData(prev => ({ ...prev, issuer: e.target.value }))} placeholder="e.g., California ABC" className="mt-1.5" />
setFormData(prev => ({ ...prev, certificate_number: e.target.value }))} placeholder="Certificate ID" className="mt-1.5" />
); } function ReportForm({ onSend, onCancel, stats }) { const [email, setEmail] = useState(""); return (

Report Preview

Total Staff

{stats.total}

Compliant

{stats.compliant}

Expiring Soon

{stats.expiring}

Expired

{stats.expired}

setEmail(e.target.value)} placeholder="client@company.com" className="mt-1.5" required />
); }