feat(scripts/prepare-export.js): replace require with import statements feat(scripts/prepare-export.js): use fileURLToPath to define __dirname feat(scripts/prepare-export.js): refactor patch application for clarity feat(scripts/prepare-export.js): add global import fix for components feat(scripts/prepare-export.js): fix component imports using regex feat(scripts/prepare-export.js): add main function to execute patches feat(scripts/prepare-export.js): mock base44 client for local development feat(scripts/prepare-export.js): add company logo field to business modal feat(scripts/prepare-export.js): add AI order assistant component feat(scripts/prepare-export.js): enhance event form with new features feat(scripts/prepare-export.js): add event form wizard component feat(scripts/prepare-export.js): add safe date formatter to message thread feat(DocumentViewer.jsx): Implement signature capture and acknowledgment feature feat(DocumentViewer.jsx): Add signature pad for capturing digital signatures feat(DocumentViewer.jsx): Enable saving signature to user profile feat(DocumentViewer.jsx): Implement acknowledgment functionality with signature and notes feat(DocumentViewer.jsx): Add UI elements for signer name input and signature pad feat(DocumentViewer.jsx): Implement signature adoption from saved profile feat(DocumentViewer.jsx): Improve UI and UX for document review process feat(UpcomingOrdersCard.jsx): Create new component to display upcoming orders feat(UpcomingOrdersCard.jsx): Implement progress bar and status indicators feat(UpcomingOrdersCard.jsx): Add ETA calculation and display feat(UpcomingOrdersCard.jsx): Improve UI and UX for upcoming order display feat(ActivityLog.jsx): Implement safe date formatting to handle invalid dates feat(ClientDashboard.jsx): Implement client dashboard with key metrics and quick actions feat(ClientDashboard.jsx): Add analytics cards for cost, labor, and sales feat(ClientDashboard.jsx): Implement quick reorder functionality feat(ClientDashboard.jsx): Add spending trend chart feat(ClientDashboard.jsx): Improve UI and UX for client dashboard feat(ClientOrders.jsx): Implement client orders page with filtering and quick actions feat(ClientOrders.jsx): Add status badges and event details feat(ClientOrders.jsx): Improve UI and UX for client orders page feat(CreateEvent.jsx): Implement event creation page with AI assistant and form wizard feat(CreateEvent.jsx): Add AI assistant for extracting event data feat(CreateEvent.jsx): Implement form wizard for event creation feat(CreateEvent.jsx): Improve UI and UX for event creation page feat(EditBusiness.jsx): Add company logo URL input to edit business page feat(EditBusiness.jsx): Improve UI and UX for edit business page feat(EventDetail.jsx): Implement safe date formatting to handle invalid dates feat(PartnerManagement.jsx): enhance partner management page with consolidated business directory and operator metrics feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from business entities feat(PartnerManagement.jsx): add consolidated business directory from feat(ProcurementDashboard.jsx): add supplier onboarding tab with filtering and detail panel feat(ProcurementDashboard.jsx): implement supplier onboarding tab with filtering and detail panel feat(ProcurementDashboard.jsx): add document status badges and actions in supplier detail panel feat(ProcurementDashboard.jsx): add compliance health indicator to supplier detail panel feat(ProcurementDashboard.jsx): add document request functionality with toast notifications feat(ProcurementDashboard.jsx): add clear filters button and active filters display feat(ProcurementDashboard.jsx): improve supplier table UI and add empty state feat(ProcurementDashboard.jsx): add document type filter to supplier onboarding tab feat(ProcurementDashboard.jsx): add state filter to supplier onboarding tab feat(ProcurementDashboard.jsx): add document status and type filtering to onboarding tab feat(ProcurementDashboard.jsx): add summary counts for onboarding tab based on filtered suppliers feat(ProcurementDashboard.jsx): add document status and type filtering to onboarding tab feat(ProcurementDashboard.jsx): add document status and type filtering to onboarding tab feat(Reports.jsx): add safe date formatting to handle invalid dates feat(SmartVendorOnboarding.jsx): implement NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA signing step with signature capture feat(SmartVendorOnboarding.jsx): add NDA feat(VendorDashboard.jsx): overhaul vendor dashboard with new UI/UX feat(VendorDashboard.jsx): add AI insights and rapid orders sections feat(VendorDashboard.jsx): implement sales vs payroll chart and client analysis feat(VendorDashboard.jsx): enhance top performers and gold vendors sections feat(VendorDashboard.jsx): improve quick actions and today's metrics feat(VendorDashboard.jsx): integrate total revenue card and staff assignment feat(VendorOrders.jsx): enhance vendor orders page with rapid request support feat(VendorOrders.jsx): add rapid request badge and filter feat(WorkforceShifts.jsx): add safe date formatting to handle invalid dates
748 lines
34 KiB
JavaScript
748 lines
34 KiB
JavaScript
import React, { useState } from "react";
|
|
import { base44 } from "@/api/base44Client";
|
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
import { Link, useNavigate } 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 { Calendar, Plus, Clock, DollarSign, MessageSquare, RefreshCw, ArrowRight, Users, CloudOff, MapPin, AlertTriangle, Package, Download, TrendingUp, TrendingDown, BarChart3, Sparkles } from "lucide-react";
|
|
import { format, parseISO, differenceInDays, startOfMonth, endOfMonth, subMonths } from "date-fns";
|
|
import { useToast } from "@/components/ui/use-toast";
|
|
import { LineChart, Line, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
|
|
|
|
export default function ClientDashboard() {
|
|
const navigate = useNavigate();
|
|
const queryClient = useQueryClient();
|
|
const { toast } = useToast();
|
|
const [reorderingId, setReorderingId] = useState(null);
|
|
|
|
const { data: user } = useQuery({
|
|
queryKey: ['current-user'],
|
|
queryFn: () => base44.auth.me(),
|
|
});
|
|
|
|
const { data: events } = useQuery({
|
|
queryKey: ['client-events'],
|
|
queryFn: async () => {
|
|
const allEvents = await base44.entities.Event.list('-date');
|
|
const clientEvents = allEvents.filter(e =>
|
|
e.client_email === user?.email ||
|
|
e.business_name === user?.company_name ||
|
|
e.created_by === user?.email
|
|
);
|
|
|
|
if (clientEvents.length === 0) {
|
|
return allEvents.filter(e => e.status === "Completed");
|
|
}
|
|
|
|
return clientEvents;
|
|
},
|
|
initialData: [],
|
|
enabled: !!user
|
|
});
|
|
|
|
const createEventMutation = useMutation({
|
|
mutationFn: (eventData) => base44.entities.Event.create(eventData),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['client-events'] });
|
|
toast({
|
|
title: "✅ Order Created",
|
|
description: "Your reorder has been created successfully",
|
|
});
|
|
setReorderingId(null);
|
|
},
|
|
onError: () => {
|
|
toast({
|
|
title: "❌ Failed to Create Order",
|
|
description: "Please try again",
|
|
variant: "destructive",
|
|
});
|
|
setReorderingId(null);
|
|
},
|
|
});
|
|
|
|
// Enhanced Analytics Calculations
|
|
const todayOrders = events.filter(e => {
|
|
const eventDate = new Date(e.date);
|
|
const today = new Date();
|
|
return eventDate.toDateString() === today.toDateString();
|
|
});
|
|
|
|
const activeOrders = events.filter(e => e.status === "Active" || e.status === "Confirmed").length;
|
|
const completedOrders = events.filter(e => e.status === "Completed");
|
|
const totalSpending = completedOrders.reduce((sum, e) => sum + (e.total || 0), 0);
|
|
const needsAttention = events.filter(e => e.status === "Pending" || e.status === "Draft").length;
|
|
|
|
// Monthly spending trend (last 6 months)
|
|
const last6Months = Array.from({ length: 6 }, (_, i) => {
|
|
const date = subMonths(new Date(), 5 - i);
|
|
return {
|
|
month: format(date, 'MMM'),
|
|
fullDate: date
|
|
};
|
|
});
|
|
|
|
const spendingTrend = last6Months.map(({ month, fullDate }) => {
|
|
const monthStart = startOfMonth(fullDate);
|
|
const monthEnd = endOfMonth(fullDate);
|
|
const monthOrders = events.filter(e => {
|
|
const eventDate = new Date(e.date);
|
|
return eventDate >= monthStart && eventDate <= monthEnd && e.status === "Completed";
|
|
});
|
|
const spend = monthOrders.reduce((sum, e) => sum + (e.total || 0), 0);
|
|
const orderCount = monthOrders.length;
|
|
const staffCount = monthOrders.reduce((sum, e) => sum + (e.requested || 0), 0);
|
|
return { month, spend, orderCount, staffCount };
|
|
});
|
|
|
|
// Cost breakdown by category
|
|
const currentMonth = new Date().getMonth();
|
|
const currentYear = new Date().getFullYear();
|
|
const thisMonthOrders = events.filter(e => {
|
|
const eventDate = new Date(e.date);
|
|
return eventDate.getMonth() === currentMonth &&
|
|
eventDate.getFullYear() === currentYear &&
|
|
e.status === "Completed";
|
|
});
|
|
|
|
const lastMonthOrders = events.filter(e => {
|
|
const eventDate = new Date(e.date);
|
|
const lastMonth = subMonths(new Date(), 1);
|
|
return eventDate.getMonth() === lastMonth.getMonth() &&
|
|
eventDate.getFullYear() === lastMonth.getFullYear() &&
|
|
e.status === "Completed";
|
|
});
|
|
|
|
const thisMonthSpend = thisMonthOrders.reduce((sum, e) => sum + (e.total || 0), 0);
|
|
const lastMonthSpend = lastMonthOrders.reduce((sum, e) => sum + (e.total || 0), 0);
|
|
const spendChange = lastMonthSpend > 0 ? ((thisMonthSpend - lastMonthSpend) / lastMonthSpend) * 100 : 0;
|
|
|
|
// Labor analytics
|
|
const totalStaffHired = completedOrders.reduce((sum, e) => sum + (e.requested || 0), 0);
|
|
const thisMonthStaff = thisMonthOrders.reduce((sum, e) => sum + (e.requested || 0), 0);
|
|
const lastMonthStaff = lastMonthOrders.reduce((sum, e) => sum + (e.requested || 0), 0);
|
|
const staffChange = lastMonthStaff > 0 ? ((thisMonthStaff - lastMonthStaff) / lastMonthStaff) * 100 : 0;
|
|
|
|
const avgStaffPerOrder = completedOrders.length > 0 ? totalStaffHired / completedOrders.length : 0;
|
|
const costPerStaff = totalStaffHired > 0 ? totalSpending / totalStaffHired : 0;
|
|
|
|
// Sales analytics
|
|
const avgOrderValue = completedOrders.length > 0 ? totalSpending / completedOrders.length : 0;
|
|
|
|
// Upcoming
|
|
const upcomingEvents = events
|
|
.filter(e => {
|
|
const eventDate = new Date(e.date);
|
|
const today = new Date();
|
|
return eventDate > today && e.status !== "Canceled";
|
|
})
|
|
.sort((a, b) => new Date(a.date) - new Date(b.date))
|
|
.slice(0, 5);
|
|
|
|
// Frequent orders
|
|
const pastOrders = events.filter(e => e.status === "Completed");
|
|
const orderFrequency = pastOrders.reduce((acc, event) => {
|
|
const key = event.event_name;
|
|
if (!acc[key]) {
|
|
acc[key] = {
|
|
event,
|
|
count: 0,
|
|
lastOrdered: event.date,
|
|
totalSpent: 0,
|
|
avgCost: 0,
|
|
totalStaff: 0
|
|
};
|
|
}
|
|
acc[key].count++;
|
|
acc[key].totalSpent += (event.total || 0);
|
|
acc[key].totalStaff += (event.requested || 0);
|
|
if (new Date(event.date) > new Date(acc[key].lastOrdered)) {
|
|
acc[key].lastOrdered = event.date;
|
|
acc[key].event = event;
|
|
}
|
|
return acc;
|
|
}, {});
|
|
|
|
Object.values(orderFrequency).forEach(item => {
|
|
item.avgCost = item.count > 0 ? item.totalSpent / item.count : 0;
|
|
});
|
|
|
|
const frequentOrders = Object.values(orderFrequency)
|
|
.sort((a, b) => b.count - a.count)
|
|
.slice(0, 3);
|
|
|
|
const totalReorders = frequentOrders.reduce((sum, item) => sum + item.count, 0);
|
|
const timeSavedMinutes = totalReorders * 15;
|
|
const timeSavedHours = Math.floor(timeSavedMinutes / 60);
|
|
const remainingMinutes = timeSavedMinutes % 60;
|
|
|
|
const handleQuickReorder = (event) => {
|
|
setReorderingId(event.id);
|
|
|
|
const reorderData = {
|
|
event_name: event.event_name,
|
|
business_id: event.business_id,
|
|
business_name: event.business_name,
|
|
hub: event.hub,
|
|
status: "Draft",
|
|
requested: event.requested,
|
|
shifts: event.shifts,
|
|
notes: `Reorder of: ${event.event_name}`,
|
|
};
|
|
|
|
createEventMutation.mutate(reorderData);
|
|
};
|
|
|
|
const handleRefresh = () => {
|
|
window.location.reload();
|
|
};
|
|
|
|
const hour = new Date().getHours();
|
|
const greeting = hour < 12 ? "Good morning" : hour < 18 ? "Good afternoon" : "Good evening";
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50/30 to-slate-50">
|
|
<div className="max-w-[1600px] mx-auto p-6 space-y-6">
|
|
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-3xl font-bold text-[#1C323E] mb-1">
|
|
{greeting}, {user?.full_name?.split(' ')[0] || 'Client'}
|
|
</h1>
|
|
<p className="text-slate-600">Here's what's happening with your orders</p>
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<Button variant="outline" onClick={handleRefresh}>
|
|
<CloudOff className="w-4 h-4 mr-2" />
|
|
Refresh
|
|
</Button>
|
|
<Button className="bg-[#0A39DF] hover:bg-[#0A39DF]/90">
|
|
<Download className="w-4 h-4 mr-2" />
|
|
Export
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Hero Stats - 4 Cards */}
|
|
<div className="grid grid-cols-4 gap-4">
|
|
<Link to={createPageUrl("CreateEvent")}>
|
|
<Card className="bg-gradient-to-br from-[#0A39DF] to-[#1C323E] border-0 shadow-lg hover:shadow-xl transition-all cursor-pointer group">
|
|
<CardContent className="p-6">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div className="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center">
|
|
<Plus className="w-6 h-6 text-white" />
|
|
</div>
|
|
<ArrowRight className="w-5 h-5 text-white/60 group-hover:text-white group-hover:translate-x-1 transition-all" />
|
|
</div>
|
|
<p className="text-white/80 text-sm mb-2">Create New</p>
|
|
<p className="text-2xl font-bold text-white">Order Now</p>
|
|
</CardContent>
|
|
</Card>
|
|
</Link>
|
|
|
|
<Card className="bg-white border-slate-200 shadow-sm hover:shadow-md transition-all">
|
|
<CardContent className="p-6">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div className="w-12 h-12 bg-blue-50 rounded-xl flex items-center justify-center">
|
|
<Calendar className="w-6 h-6 text-blue-600" />
|
|
</div>
|
|
<Badge className="bg-blue-50 text-blue-700">{todayOrders.length > 0 ? 'Active' : 'None'}</Badge>
|
|
</div>
|
|
<p className="text-slate-600 text-sm mb-2">Today's Orders</p>
|
|
<p className="text-3xl font-bold text-[#1C323E]">{todayOrders.length}</p>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card className="bg-white border-slate-200 shadow-sm hover:shadow-md transition-all">
|
|
<CardContent className="p-6">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div className="w-12 h-12 bg-purple-50 rounded-xl flex items-center justify-center">
|
|
<Package className="w-6 h-6 text-purple-600" />
|
|
</div>
|
|
<Badge className="bg-green-50 text-green-700">Active</Badge>
|
|
</div>
|
|
<p className="text-slate-600 text-sm mb-2">In Progress</p>
|
|
<p className="text-3xl font-bold text-[#1C323E]">{activeOrders}</p>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{needsAttention > 0 ? (
|
|
<Link to={createPageUrl("ClientOrders")}>
|
|
<Card className="bg-gradient-to-br from-amber-500 to-orange-600 border-0 shadow-lg hover:shadow-xl transition-all cursor-pointer group">
|
|
<CardContent className="p-6">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div className="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center">
|
|
<AlertTriangle className="w-6 h-6 text-white" />
|
|
</div>
|
|
<ArrowRight className="w-5 h-5 text-white/60 group-hover:text-white group-hover:translate-x-1 transition-all" />
|
|
</div>
|
|
<p className="text-white/90 text-sm mb-2">Needs Attention</p>
|
|
<p className="text-3xl font-bold text-white">{needsAttention}</p>
|
|
</CardContent>
|
|
</Card>
|
|
</Link>
|
|
) : (
|
|
<Card className="bg-white border-slate-200 shadow-sm">
|
|
<CardContent className="p-6">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div className="w-12 h-12 bg-green-50 rounded-xl flex items-center justify-center">
|
|
<Sparkles className="w-6 h-6 text-green-600" />
|
|
</div>
|
|
<Badge className="bg-green-50 text-green-700">All Clear</Badge>
|
|
</div>
|
|
<p className="text-slate-600 text-sm mb-2">Status</p>
|
|
<p className="text-2xl font-bold text-[#1C323E]">All Good!</p>
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
</div>
|
|
|
|
{/* Main Content Grid */}
|
|
<div className="grid grid-cols-3 gap-6">
|
|
|
|
{/* Left Column - Analytics (2 cols) */}
|
|
<div className="col-span-2 space-y-6">
|
|
|
|
{/* Big Analytics Cards */}
|
|
<div className="grid grid-cols-3 gap-4">
|
|
{/* Cost Analysis */}
|
|
<Card className="bg-white border-slate-200 shadow-sm">
|
|
<CardContent className="p-6">
|
|
<div className="flex items-center gap-3 mb-6">
|
|
<div className="w-12 h-12 bg-gradient-to-br from-green-400 to-emerald-500 rounded-xl flex items-center justify-center shadow-lg">
|
|
<DollarSign className="w-6 h-6 text-white" />
|
|
</div>
|
|
<div>
|
|
<p className="text-xs text-slate-500 uppercase tracking-wide">Cost</p>
|
|
<p className="font-bold text-[#1C323E]">Analysis</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-4">
|
|
<div>
|
|
<p className="text-xs text-slate-500 mb-1">This Month</p>
|
|
<div className="flex items-end gap-2">
|
|
<p className="text-3xl font-bold text-[#1C323E]">
|
|
${(thisMonthSpend / 1000).toFixed(1)}k
|
|
</p>
|
|
{spendChange !== 0 && (
|
|
<div className={`flex items-center gap-1 mb-1 ${spendChange > 0 ? 'text-green-600' : 'text-red-600'}`}>
|
|
{spendChange > 0 ? <TrendingUp className="w-4 h-4" /> : <TrendingDown className="w-4 h-4" />}
|
|
<span className="text-sm font-semibold">{Math.abs(spendChange).toFixed(0)}%</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pt-4 border-t border-slate-100 space-y-2">
|
|
<div className="flex items-center justify-between text-sm">
|
|
<span className="text-slate-600">Avg Order</span>
|
|
<span className="font-bold text-[#1C323E]">${Math.round(avgOrderValue).toLocaleString()}</span>
|
|
</div>
|
|
<div className="flex items-center justify-between text-sm">
|
|
<span className="text-slate-600">Cost/Staff</span>
|
|
<span className="font-bold text-[#1C323E]">${Math.round(costPerStaff)}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pt-2">
|
|
<ResponsiveContainer width="100%" height={60}>
|
|
<LineChart data={spendingTrend.slice(-6)}>
|
|
<Line
|
|
type="monotone"
|
|
dataKey="spend"
|
|
stroke="#10b981"
|
|
strokeWidth={3}
|
|
dot={false}
|
|
/>
|
|
</LineChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Labor Summary */}
|
|
<Card className="bg-white border-slate-200 shadow-sm">
|
|
<CardContent className="p-6">
|
|
<div className="flex items-center gap-3 mb-6">
|
|
<div className="w-12 h-12 bg-gradient-to-br from-blue-400 to-indigo-500 rounded-xl flex items-center justify-center shadow-lg">
|
|
<Users className="w-6 h-6 text-white" />
|
|
</div>
|
|
<div>
|
|
<p className="text-xs text-slate-500 uppercase tracking-wide">Labor</p>
|
|
<p className="font-bold text-[#1C323E]">Summary</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-4">
|
|
<div>
|
|
<p className="text-xs text-slate-500 mb-1">This Month</p>
|
|
<div className="flex items-end gap-2">
|
|
<p className="text-3xl font-bold text-[#1C323E]">{thisMonthStaff}</p>
|
|
{staffChange !== 0 && (
|
|
<div className={`flex items-center gap-1 mb-1 ${staffChange > 0 ? 'text-blue-600' : 'text-red-600'}`}>
|
|
{staffChange > 0 ? <TrendingUp className="w-4 h-4" /> : <TrendingDown className="w-4 h-4" />}
|
|
<span className="text-sm font-semibold">{Math.abs(staffChange).toFixed(0)}%</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pt-4 border-t border-slate-100 space-y-2">
|
|
<div className="flex items-center justify-between text-sm">
|
|
<span className="text-slate-600">Total Staff</span>
|
|
<span className="font-bold text-[#1C323E]">{totalStaffHired}</span>
|
|
</div>
|
|
<div className="flex items-center justify-between text-sm">
|
|
<span className="text-slate-600">Avg/Order</span>
|
|
<span className="font-bold text-[#1C323E]">{Math.round(avgStaffPerOrder)}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pt-2">
|
|
<ResponsiveContainer width="100%" height={60}>
|
|
<BarChart data={spendingTrend.slice(-6)}>
|
|
<Bar dataKey="staffCount" fill="#3b82f6" radius={[6, 6, 0, 0]} />
|
|
</BarChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Sales Analytics */}
|
|
<Card className="bg-white border-slate-200 shadow-sm">
|
|
<CardContent className="p-6">
|
|
<div className="flex items-center gap-3 mb-6">
|
|
<div className="w-12 h-12 bg-gradient-to-br from-purple-400 to-pink-500 rounded-xl flex items-center justify-center shadow-lg">
|
|
<BarChart3 className="w-6 h-6 text-white" />
|
|
</div>
|
|
<div>
|
|
<p className="text-xs text-slate-500 uppercase tracking-wide">Sales</p>
|
|
<p className="font-bold text-[#1C323E]">Analytics</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-4">
|
|
<div>
|
|
<p className="text-xs text-slate-500 mb-1">This Month</p>
|
|
<div className="flex items-end gap-2">
|
|
<p className="text-3xl font-bold text-[#1C323E]">{thisMonthOrders.length}</p>
|
|
<span className="text-sm text-slate-500 mb-1">orders</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pt-4 border-t border-slate-100 space-y-2">
|
|
<div className="flex items-center justify-between text-sm">
|
|
<span className="text-slate-600">Total Orders</span>
|
|
<span className="font-bold text-[#1C323E]">{events.length}</span>
|
|
</div>
|
|
<div className="flex items-center justify-between text-sm">
|
|
<span className="text-slate-600">Completed</span>
|
|
<span className="font-bold text-[#1C323E]">{completedOrders.length}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pt-2">
|
|
<ResponsiveContainer width="100%" height={60}>
|
|
<LineChart data={spendingTrend.slice(-6)}>
|
|
<Line
|
|
type="monotone"
|
|
dataKey="orderCount"
|
|
stroke="#a855f7"
|
|
strokeWidth={3}
|
|
dot={false}
|
|
/>
|
|
</LineChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* 6-Month Trend */}
|
|
<Card className="bg-white border-slate-200 shadow-sm">
|
|
<CardContent className="p-6">
|
|
<div className="flex items-center justify-between mb-6">
|
|
<div>
|
|
<h3 className="font-bold text-[#1C323E] mb-1">Spending Trend</h3>
|
|
<p className="text-sm text-slate-600">Last 6 months overview</p>
|
|
</div>
|
|
<Badge variant="outline" className="text-xs">6 Months</Badge>
|
|
</div>
|
|
<ResponsiveContainer width="100%" height={200}>
|
|
<LineChart data={spendingTrend}>
|
|
<CartesianGrid strokeDasharray="3 3" stroke="#e2e8f0" />
|
|
<XAxis
|
|
dataKey="month"
|
|
tick={{ fontSize: 12 }}
|
|
stroke="#94a3b8"
|
|
/>
|
|
<YAxis
|
|
tick={{ fontSize: 12 }}
|
|
stroke="#94a3b8"
|
|
tickFormatter={(value) => `$${(value / 1000).toFixed(0)}k`}
|
|
/>
|
|
<Tooltip
|
|
contentStyle={{
|
|
fontSize: '14px',
|
|
backgroundColor: 'white',
|
|
border: '1px solid #e2e8f0',
|
|
borderRadius: '12px',
|
|
padding: '12px'
|
|
}}
|
|
formatter={(value) => [`$${Math.round(value).toLocaleString()}`, 'Spend']}
|
|
/>
|
|
<Line
|
|
type="monotone"
|
|
dataKey="spend"
|
|
stroke="#0A39DF"
|
|
strokeWidth={4}
|
|
dot={{ fill: '#0A39DF', r: 5 }}
|
|
activeDot={{ r: 7 }}
|
|
/>
|
|
</LineChart>
|
|
</ResponsiveContainer>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Quick Reorder */}
|
|
<Card className="bg-white border-slate-200 shadow-sm">
|
|
<CardContent className="p-6">
|
|
<div className="flex items-center justify-between mb-6">
|
|
<div>
|
|
<h3 className="font-bold text-[#1C323E] mb-1 flex items-center gap-2">
|
|
<RefreshCw className="w-5 h-5 text-[#0A39DF]" />
|
|
Order it again
|
|
</h3>
|
|
<p className="text-sm text-slate-600">
|
|
One tap to reorder • Saved {timeSavedHours}h {remainingMinutes}m
|
|
</p>
|
|
</div>
|
|
<Badge variant="outline">Top 3</Badge>
|
|
</div>
|
|
|
|
{frequentOrders.length > 0 ? (
|
|
<div className="grid grid-cols-3 gap-4">
|
|
{frequentOrders.map((item, index) => {
|
|
const { event, count, avgCost, totalStaff, lastOrdered } = item;
|
|
const isReordering = reorderingId === event.id;
|
|
const medals = [
|
|
{ icon: "🥇", color: "from-yellow-400 to-amber-500" },
|
|
{ icon: "🥈", color: "from-slate-400 to-slate-500" },
|
|
{ icon: "🥉", color: "from-amber-600 to-orange-700" }
|
|
];
|
|
const medal = medals[index];
|
|
|
|
return (
|
|
<div
|
|
key={event.id}
|
|
className="relative p-5 rounded-2xl bg-gradient-to-br from-slate-50 to-white border-2 border-slate-200 hover:border-[#0A39DF] hover:shadow-lg transition-all"
|
|
>
|
|
<div className="absolute -top-3 -left-3">
|
|
<div className={`w-12 h-12 bg-gradient-to-br ${medal.color} rounded-xl flex items-center justify-center text-2xl shadow-lg`}>
|
|
{medal.icon}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pt-4">
|
|
<Badge variant="outline" className="mb-3 text-xs font-semibold">
|
|
Ordered {count}x
|
|
</Badge>
|
|
|
|
<h4 className="font-bold text-sm text-[#1C323E] mb-3 line-clamp-2 min-h-[2.5rem]">
|
|
{event.event_name}
|
|
</h4>
|
|
|
|
{event.hub && (
|
|
<div className="flex items-center gap-1.5 mb-4 text-xs text-slate-600">
|
|
<MapPin className="w-3.5 h-3.5 text-slate-400" />
|
|
<span className="truncate">{event.hub}</span>
|
|
</div>
|
|
)}
|
|
|
|
<div className="grid grid-cols-2 gap-3 mb-4 p-3 bg-white rounded-xl border border-slate-100">
|
|
<div>
|
|
<p className="text-[10px] text-slate-500 mb-1">Avg Cost</p>
|
|
<p className="text-lg font-bold text-[#1C323E]">
|
|
${(avgCost / 1000).toFixed(1)}k
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-[10px] text-slate-500 mb-1">Staff</p>
|
|
<p className="text-lg font-bold text-[#1C323E]">
|
|
{Math.round(totalStaff / count)}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-1.5 mb-4 text-xs text-slate-500">
|
|
<Clock className="w-3.5 h-3.5" />
|
|
<span>Last ordered {format(parseISO(lastOrdered), "MMM d")}</span>
|
|
</div>
|
|
|
|
<Button
|
|
size="sm"
|
|
className="w-full bg-gradient-to-r from-[#0A39DF] to-[#1C323E] hover:opacity-90 text-white rounded-xl shadow-md"
|
|
disabled={isReordering}
|
|
onClick={() => handleQuickReorder(event)}
|
|
>
|
|
{isReordering ? (
|
|
<>
|
|
<RefreshCw className="w-4 h-4 mr-2 animate-spin" />
|
|
Reordering...
|
|
</>
|
|
) : (
|
|
<>
|
|
<RefreshCw className="w-4 h-4 mr-2" />
|
|
Reorder Now
|
|
</>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
) : (
|
|
<div className="text-center py-12">
|
|
<div className="w-20 h-20 mx-auto mb-4 bg-slate-100 rounded-full flex items-center justify-center">
|
|
<RefreshCw className="w-10 h-10 text-slate-300" />
|
|
</div>
|
|
<p className="text-slate-600 font-medium mb-2">No previous orders yet</p>
|
|
<p className="text-sm text-slate-500">Complete your first order to see recommendations</p>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* Right Column - Quick Access (1 col) */}
|
|
<div className="space-y-6">
|
|
|
|
{/* Financial Card */}
|
|
<Card className="bg-gradient-to-br from-purple-500 via-pink-500 to-orange-400 border-0 shadow-xl">
|
|
<CardContent className="p-8">
|
|
<div className="flex items-center justify-between mb-6">
|
|
<p className="text-white/80 text-sm">Total Spending</p>
|
|
<div className="flex gap-1.5">
|
|
<div className="w-2 h-2 bg-white/50 rounded-full"></div>
|
|
<div className="w-2 h-2 bg-white/50 rounded-full"></div>
|
|
<div className="w-2 h-2 bg-white rounded-full"></div>
|
|
</div>
|
|
</div>
|
|
<p className="text-5xl font-bold text-white mb-2">
|
|
${Math.round(totalSpending / 1000)}k
|
|
</p>
|
|
<p className="text-white/70 text-sm">Lifetime value • {completedOrders.length} orders</p>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Quick Actions */}
|
|
<div className="grid grid-cols-2 gap-3">
|
|
<Link to={createPageUrl("ClientOrders")}>
|
|
<Card className="bg-white border-slate-200 shadow-sm hover:shadow-md transition-all cursor-pointer">
|
|
<CardContent className="p-5 text-center">
|
|
<div className="w-12 h-12 mx-auto mb-3 bg-gradient-to-br from-blue-50 to-indigo-50 rounded-xl flex items-center justify-center">
|
|
<Package className="w-6 h-6 text-blue-600" />
|
|
</div>
|
|
<p className="text-[#1C323E] font-semibold text-sm">All Orders</p>
|
|
<p className="text-slate-500 text-xs mt-1">{events.length} total</p>
|
|
</CardContent>
|
|
</Card>
|
|
</Link>
|
|
|
|
<Link to={createPageUrl("Messages")}>
|
|
<Card className="bg-white border-slate-200 shadow-sm hover:shadow-md transition-all cursor-pointer">
|
|
<CardContent className="p-5 text-center">
|
|
<div className="w-12 h-12 mx-auto mb-3 bg-gradient-to-br from-green-50 to-emerald-50 rounded-xl flex items-center justify-center">
|
|
<MessageSquare className="w-6 h-6 text-green-600" />
|
|
</div>
|
|
<p className="text-[#1C323E] font-semibold text-sm">Messages</p>
|
|
<p className="text-slate-500 text-xs mt-1">Get support</p>
|
|
</CardContent>
|
|
</Card>
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Coming Up */}
|
|
<Card className="bg-white border-slate-200 shadow-sm">
|
|
<CardContent className="p-5">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h3 className="font-bold text-[#1C323E] flex items-center gap-2">
|
|
<Clock className="w-4 h-4 text-[#0A39DF]" />
|
|
Coming Up
|
|
</h3>
|
|
<Link to={createPageUrl("ClientOrders")}>
|
|
<Button variant="ghost" size="sm" className="h-7 text-xs">
|
|
View All
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
|
|
{upcomingEvents.length > 0 ? (
|
|
<div className="space-y-3">
|
|
{upcomingEvents.map((event) => {
|
|
const daysUntil = differenceInDays(new Date(event.date), new Date());
|
|
const isUrgent = daysUntil <= 3;
|
|
const isToday = daysUntil === 0;
|
|
|
|
return (
|
|
<Link
|
|
key={event.id}
|
|
to={createPageUrl(`EventDetail?id=${event.id}`)}
|
|
className={`block p-3 rounded-xl transition-all border-2 ${
|
|
isToday
|
|
? 'bg-red-50 border-red-200 hover:bg-red-100'
|
|
: isUrgent
|
|
? 'bg-amber-50 border-amber-200 hover:bg-amber-100'
|
|
: 'bg-slate-50 border-slate-200 hover:border-[#0A39DF] hover:bg-white'
|
|
}`}
|
|
>
|
|
<div className="flex items-start justify-between mb-2">
|
|
<p className={`font-semibold text-sm ${
|
|
isToday ? 'text-red-700' : isUrgent ? 'text-amber-700' : 'text-[#1C323E]'
|
|
}`}>
|
|
{event.event_name}
|
|
</p>
|
|
{(isToday || isUrgent) && (
|
|
<Badge className={`text-[10px] ${
|
|
isToday
|
|
? 'bg-red-100 text-red-700'
|
|
: 'bg-amber-100 text-amber-700'
|
|
}`}>
|
|
{isToday ? "Today" : `${daysUntil}d`}
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
<div className="flex items-center gap-2 text-xs text-slate-600">
|
|
<Calendar className="w-3 h-3" />
|
|
<span>{format(new Date(event.date), "MMM d, h:mm a")}</span>
|
|
<span>•</span>
|
|
<Users className="w-3 h-3" />
|
|
<span>{event.requested || 0} staff</span>
|
|
</div>
|
|
</Link>
|
|
);
|
|
})}
|
|
</div>
|
|
) : (
|
|
<div className="text-center py-8">
|
|
<div className="w-12 h-12 mx-auto mb-3 bg-slate-100 rounded-full flex items-center justify-center">
|
|
<Clock className="w-6 h-6 text-slate-300" />
|
|
</div>
|
|
<p className="text-sm text-slate-500">No upcoming orders</p>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|