import React, { useState, useEffect } from "react"; import { base44 } from "@/api/base44Client"; import { useQuery } from "@tanstack/react-query"; import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, } from "@/components/ui/dialog"; import { BarChart3, TrendingUp, TrendingDown, AlertTriangle, CheckCircle2, DollarSign, Award, Shield, Target, Coffee, ArrowRight, Clock, AlertCircle, Activity, Users, FileText, ChevronRight, Edit, X, Calendar, Package, RefreshCw, Printer, Mail, Download, User, Menu, HelpCircle } from "lucide-react"; import { format } from "date-fns"; import { createPageUrl } from "@/utils"; import { Link } from "react-router-dom"; import { LineChart, Line, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, AreaChart, Area, PieChart, Pie, Cell } from 'recharts'; const MARKET_AVERAGES = { "Banquet Captain": 47.76, "Server": 41.56, "Cook": 44.58, "Line Cook": 44.58, "Full Bartender": 47.76, "Sous Chef": 59.75, "Executive Chef": 70.60, "Dishwasher/ Steward": 38.38, "Prep Cook": 37.98, "Barback": 36.13, "Busser": 39.23, }; const COLORS = ['#0A39DF', '#10b981', '#f59e0b', '#8b5cf6', '#ec4899', '#ef4444', '#3b82f6']; // Safe date formatter const safeFormatDate = (dateString, formatStr) => { if (!dateString) return "N/A"; try { const date = new Date(dateString); if (isNaN(date.getTime())) return "N/A"; return format(date, formatStr); } catch { return "N/A"; } }; export default function Reports() { const [greeting, setGreeting] = useState(""); const [reviewVendor, setReviewVendor] = useState(null); const [showReviewDialog, setShowReviewDialog] = useState(false); useEffect(() => { const hour = new Date().getHours(); if (hour < 12) { setGreeting("Good Morning"); } else if (hour < 18) { setGreeting("Good Afternoon"); } else { setGreeting("Good Evening"); } }, []); const { data: user } = useQuery({ queryKey: ['current-user-reports'], queryFn: () => base44.auth.me(), }); const { data: rates = [] } = useQuery({ queryKey: ['vendor-rates-analysis'], queryFn: () => base44.entities.VendorRate.list(), initialData: [], }); const { data: events = [] } = useQuery({ queryKey: ['events-analysis'], queryFn: () => base44.entities.Event.list('-date'), initialData: [], }); const { data: staff = [] } = useQuery({ queryKey: ['staff-analysis'], queryFn: () => base44.entities.Staff.list(), initialData: [], }); const userRole = user?.user_role || user?.role || "admin"; // Filter data based on user role const getFilteredEvents = () => { if (userRole === "client") { return events.filter(e => e.client_email === user?.email || e.business_name === user?.company_name || e.created_by === user?.email ); } if (userRole === "vendor") { return events.filter(e => e.vendor_name === user?.company_name); } // For admin, operator, sector (to see own shifts), return all or adjust based on specific needs // For workforce, events might not be directly relevant unless they are assigned to them // For now, return all for admin/operator/sector if no specific event filtering return events; }; const getFilteredStaff = () => { if (userRole === "vendor") { return staff.filter(s => s.vendor_name === user?.company_name); } if (userRole === "workforce") { // Assuming employee_name matches full_name or created_by matches email return staff.filter(s => s.employee_name === user?.full_name || s.created_by === user?.email); } // For admin, client (to see all staff for their events), operator, sector return staff; }; const filteredEvents = getFilteredEvents(); const filteredStaff = getFilteredStaff(); // Analyze vendor performance (used by admin/procurement) const analyzeVendors = () => { const vendorStats = {}; rates.forEach(rate => { if (!vendorStats[rate.vendor_name]) { vendorStats[rate.vendor_name] = { name: rate.vendor_name, totalServices: 0, activeServices: 0, avgMarkup: 0, avgVendorFee: 0, underpriced: 0, overpriced: 0, optimal: 0, complianceIssues: 0, markups: [], fees: [], underpricedServices: [], complianceIssueServices: [] }; } const vendor = vendorStats[rate.vendor_name]; vendor.totalServices++; if (rate.is_active) vendor.activeServices++; vendor.markups.push(rate.markup_percentage); vendor.fees.push(rate.vendor_fee_percentage); // Check minimum wage compliance if (rate.employee_wage < 16.50) { vendor.complianceIssues++; vendor.complianceIssueServices.push({ ...rate, issue: 'Below minimum wage', currentWage: rate.employee_wage, requiredWage: 16.50, difference: (16.50 - rate.employee_wage).toFixed(2) }); } // Price analysis const marketAvg = MARKET_AVERAGES[rate.role_name]; if (marketAvg) { const diff = ((rate.client_rate - marketAvg) / marketAvg) * 100; if (diff < -15) { vendor.underpriced++; vendor.underpricedServices.push({ ...rate, issue: 'Underpriced', marketAverage: marketAvg, currentRate: rate.client_rate, percentageBelow: Math.abs(diff).toFixed(1), potentialRevenue: ((marketAvg - rate.client_rate) * 160).toFixed(0) // Assuming 160 hours/month }); } else if (diff > 20) { vendor.overpriced++; } else if (diff >= -5 && diff <= 10) { vendor.optimal++; } } }); // Calculate averages Object.values(vendorStats).forEach(vendor => { vendor.avgMarkup = vendor.markups.length > 0 ? (vendor.markups.reduce((a, b) => a + b, 0) / vendor.markups.length).toFixed(1) : 0; vendor.avgVendorFee = vendor.fees.length > 0 ? (vendor.fees.reduce((a, b) => a + b, 0) / vendor.fees.length).toFixed(1) : 0; }); return Object.values(vendorStats); }; const vendorAnalysis = analyzeVendors(); const topPerformers = vendorAnalysis .filter(v => v.optimal > 0) .sort((a, b) => b.optimal - a.optimal) .slice(0, 3); const underperformers = vendorAnalysis .filter(v => v.complianceIssues > 0 || v.underpriced > v.optimal) .sort((a, b) => (b.complianceIssues + b.underpriced) - (a.complianceIssues + a.underpriced)) .slice(0, 3); const underchargingVendors = vendorAnalysis .filter(v => v.underpriced > 2) .sort((a, b) => b.underpriced - a.underpriced) .slice(0, 3); const complianceIssues = vendorAnalysis .filter(v => v.complianceIssues > 0) .sort((a, b) => b.complianceIssues - a.complianceIssues); const totalVendors = vendorAnalysis.length; const totalServices = rates.length; const activeServices = rates.filter(r => r.is_active).length; const totalCompliance = rates.filter(r => r.employee_wage >= 16.50).length; const complianceRate = totalServices > 0 ? ((totalCompliance / totalServices) * 100).toFixed(1) : 0; const revenueOpportunities = underchargingVendors.reduce((sum, v) => sum + (v.underpriced * 5000), 0); // Placeholder revenue opportunity const handleReviewVendor = (vendor) => { setReviewVendor(vendor); setShowReviewDialog(true); }; const renderAdminProcurementReports = () => { return ( <> {/* Key Metrics */}
Active

{totalVendors}

Active Vendors

Services

{activeServices}

Active Services

= 95 ? 'bg-green-50' : 'bg-amber-50'} rounded-lg flex items-center justify-center`}> = 95 ? 'text-green-600' : 'text-amber-600'}`} />
= 95 ? 'text-green-700 border-green-200 bg-green-50' : 'text-amber-700 border-amber-200 bg-amber-50'}> {complianceRate >= 95 ? "Compliant" : "Review"}

{complianceRate}%

Wage Compliance

Potential

${(revenueOpportunities / 1000).toFixed(0)}K

Revenue Opportunity

{/* Executive Summary */} Executive Summary
{topPerformers.length > 0 && (

Top Performer

{topPerformers[0].name} is performing excellently with {topPerformers[0].optimal} optimally-priced services, maintaining competitive market rates while ensuring profitability.

)} {underperformers.length > 0 && (

Action Required

{underperformers[0].name} requires attention {underperformers[0].complianceIssues > 0 ? ( — {underperformers[0].complianceIssues} compliance {underperformers[0].complianceIssues === 1 ? 'issue' : 'issues'} detected and must be addressed immediately. ) : ( for pricing strategy optimization to improve market competitiveness. )}

)} {complianceIssues.length > 0 && (

Compliance Alert

{complianceIssues.length} {complianceIssues.length === 1 ? 'vendor has' : 'vendors have'} wage compliance issues below the California minimum wage ($16.50/hr) requiring immediate correction.

)} {underchargingVendors.length > 0 && (

Revenue Opportunity

${(revenueOpportunities / 1000).toFixed(0)}K in potential annual revenue identified through price optimization across {underchargingVendors.length} vendors with {underchargingVendors.reduce((sum, v) => sum + v.underpriced, 0)} underpriced services.

)}

Overall Status

Network health is {complianceRate >= 95 ? "excellent" : "stable"} with {activeServices} active services across {totalVendors} vendors. {complianceRate >= 95 ? "Continue monitoring for sustained performance." : "Recommend focusing on compliance corrections and pricing optimization."}

{/* Top Performers */} {topPerformers.length > 0 && (
Top Performing Vendors {topPerformers.length} Vendors
{topPerformers.map((vendor, idx) => (
#{idx + 1}

{vendor.name}

{vendor.optimal} Optimal
{vendor.activeServices} Active
{vendor.avgMarkup}% Markup

A+

Performance

))}
)} {/* Action Required */} {underperformers.length > 0 && (
Attention Required {underperformers.length} Vendors
{underperformers.map((vendor, idx) => (

{vendor.name}

{vendor.complianceIssues > 0 && ( {vendor.complianceIssues} Compliance {vendor.complianceIssues === 1 ? 'Issue' : 'Issues'} )} {vendor.underpriced > vendor.optimal && ( {vendor.underpriced} Underpriced )}
))}
)} {/* Revenue Opportunities */} {underchargingVendors.length > 0 && (
Revenue Optimization Opportunities

${(revenueOpportunities / 1000).toFixed(0)}K

Annual Potential

{underchargingVendors.map((vendor, idx) => (

{vendor.name}

{vendor.underpriced} services below market rate

${(vendor.underpriced * 5000 / 1000).toFixed(0)}K
))}
Recommendation

Adjusting {underchargingVendors.reduce((sum, v) => sum + v.underpriced, 0)} underpriced services to competitive market rates could generate ${(revenueOpportunities / 1000).toFixed(0)}K in additional annual revenue without impacting client competitiveness.

)} {/* Compliance Issues */} {complianceIssues.length > 0 && (
Compliance Violations Critical
{complianceIssues.map((vendor, idx) => (

{vendor.name}

{vendor.complianceIssues} {vendor.complianceIssues === 1 ? 'service' : 'services'} below minimum wage ($16.50/hr)

Legal Risk: High
))}
Legal Risk Assessment

These services must be corrected immediately to comply with California minimum wage laws ($16.50/hr). Non-compliance may result in penalties, lawsuits, and reputational damage.

)} ); }; const renderClientReports = () => { const totalSpend = filteredEvents.reduce((sum, e) => sum + (e.total || 0), 0); const avgOrderSize = filteredEvents.length > 0 ? totalSpend / filteredEvents.length : 0; const completedOrders = filteredEvents.filter(e => e.status === "Completed").length; const completionRate = filteredEvents.length > 0 ? ((completedOrders / filteredEvents.length) * 100).toFixed(1) : 0; // Monthly spending trend const monthlySpendMap = filteredEvents.reduce((acc, event) => { if (!event.date) return acc; try { const date = new Date(event.date); if (isNaN(date.getTime())) return acc; // Skip invalid dates const monthYear = format(date, 'MMM yyyy'); if (!acc[monthYear]) acc[monthYear] = 0; acc[monthYear] += event.total || 0; } catch { // Skip invalid dates } return acc; }, {}); const spendingTrend = Object.entries(monthlySpendMap) .sort(([a], [b]) => new Date(a).getTime() - new Date(b).getTime()) // Sort by date .map(([month, spend]) => ({ month, spend: spend })) .slice(-6); // Last 6 months // Order status breakdown const statusBreakdown = filteredEvents.reduce((acc, event) => { const status = event.status || "Unknown"; acc[status] = (acc[status] || 0) + 1; return acc; }, {}); const statusData = Object.entries(statusBreakdown).map(([name, value]) => ({ name, value })); return ( <> {/* Client Metrics */}
Total

{filteredEvents.length}

Total Orders

Spend

${(totalSpend / 1000).toFixed(1)}K

Total Spend

Average

${avgOrderSize.toFixed(0)}

Avg Order Size

{completionRate}%

{completedOrders}

Completed Orders

{/* Client Charts */}
Monthly Spending Trend `$${value.toFixed(2)}`} /> Order Status Breakdown `${name} ${(percent * 100).toFixed(0)}%`} outerRadius={80} fill="#8884d8" dataKey="value" > {statusData.map((entry, index) => ( ))}
); }; const renderVendorReports = () => { const totalOrders = filteredEvents.length; const completedOrders = filteredEvents.filter(e => e.status === "Completed").length; const fillRate = totalOrders > 0 ? ((completedOrders / totalOrders) * 100).toFixed(1) : 0; const totalRevenue = filteredEvents.reduce((sum, e) => sum + (e.total || 0), 0); const avgRating = filteredStaff.length > 0 ? (filteredStaff.reduce((sum, s) => sum + (s.rating || 0), 0) / filteredStaff.length).toFixed(1) : 0; return ( <>
Orders

{totalOrders}

Total Orders

{fillRate}%

{fillRate}%

Fill Rate

Revenue

${(totalRevenue / 1000).toFixed(1)}K

Total Revenue

{avgRating}/5

{avgRating}

Avg Staff Rating

); }; const renderWorkforceReports = () => { // For workforce, assuming filteredStaff contains only the current user's staff data const myStats = filteredStaff.find(s => s.employee_name === user?.full_name || s.created_by === user?.email) || {}; const totalShifts = myStats.total_shifts || 0; const myRating = myStats.rating || 0; const coverage = myStats.shift_coverage_percentage || 0; const cancellations = myStats.cancellation_count || 0; return ( <>
Shifts

{totalShifts}

Total Shifts

{myRating}/5

{myRating}

My Rating

{coverage}%

{coverage}%

Coverage Rate

Total

{cancellations}

Cancellations

); }; const renderOperatorSectorReports = () => { const totalOrders = filteredEvents.length; const activeOrders = filteredEvents.filter(e => e.status === "Active" || e.status === "Confirmed").length; const completedOrders = filteredEvents.filter(e => e.status === "Completed").length; const totalStaff = filteredStaff.length; const avgCoverage = filteredStaff.length > 0 ? Math.round(filteredStaff.reduce((sum, s) => sum + (s.shift_coverage_percentage || 0), 0) / filteredStaff.length) : 0; return ( <>
Total

{totalOrders}

Total Orders

Active

{activeOrders}

Active Orders

Done

{completedOrders}

Completed

{avgCoverage}%

{totalStaff}

Total Staff

); }; return (
{/* Header */}

{greeting}

Data as of {safeFormatDate(new Date(), 'MMM dd, yyyy, h:mm a')}

{/* Right Side: Action Icons + User Menu */}
{/* Action Icons */}
{/* Divider */}
{/* User Profile */} {/* Menu Icon */} {/* Help */}
{/* Role-specific reports */} {(userRole === "admin" || userRole === "procurement") && renderAdminProcurementReports()} {userRole === "client" && renderClientReports()} {userRole === "vendor" && renderVendorReports()} {userRole === "workforce" && renderWorkforceReports()} {(userRole === "operator" || userRole === "sector") && renderOperatorSectorReports()}
{/* Review Vendor Dialog */} Review Required: {reviewVendor?.name} Review and fix the issues below to optimize vendor performance {reviewVendor && (
{/* Compliance Issues */} {reviewVendor.complianceIssueServices.length > 0 && (

Compliance Issues ({reviewVendor.complianceIssueServices.length})

{reviewVendor.complianceIssueServices.map((service, idx) => (

{service.role_name}

{service.category}

Current Wage

${service.currentWage.toFixed(2)}/hr

Minimum Required

${service.requiredWage.toFixed(2)}/hr

Increase Needed

+${service.difference}/hr

⚠️ Legal Risk

This wage is below California minimum wage ($16.50/hr). Immediate correction required to avoid penalties.

))}
)} {/* Underpriced Services */} {reviewVendor.underpricedServices.length > 0 && (

Underpriced Services ({reviewVendor.underpricedServices.length})

{reviewVendor.underpricedServices.map((service, idx) => (

{service.role_name}

{service.category}

Current Rate

${service.currentRate.toFixed(2)}/hr

Market Average

${service.marketAverage.toFixed(2)}/hr

Below Market

{service.percentageBelow}%

💰 Revenue Opportunity

Adjusting to market rate could generate ~${service.potentialRevenue}/month additional revenue for this service.

))}
)} {/* Action Summary */}

Next Steps

    {reviewVendor.complianceIssueServices.length > 0 && (
  • Fix {reviewVendor.complianceIssueServices.length} compliance {reviewVendor.complianceIssueServices.length === 1 ? 'issue' : 'issues'} immediately
  • )} {reviewVendor.underpricedServices.length > 0 && (
  • Review and adjust {reviewVendor.underpricedServices.length} underpriced {reviewVendor.underpricedServices.length === 1 ? 'service' : 'services'}
  • )}
  • Update vendor rate card to reflect market standards
{/* Action Buttons */}
)}
); }