import { useState, useEffect, useMemo } from "react"; import { useQueryClient } from "@tanstack/react-query"; import { useNavigate, useParams } from "react-router-dom"; import { useSelector } from "react-redux"; import { createPageUrl } from "@/lib/index"; import { Button } from "@/common/components/ui/button"; import { Loader2, AlertTriangle } from "lucide-react"; import DashboardLayout from "@/features/layouts/DashboardLayout"; import OrderReductionAlert from "./components/OrderReductionAlert"; import EventFormWizard from "./components/EventFormWizard"; import { useToast } from "@/common/components/ui/use-toast"; import { useGetOrderById, useUpdateOrder, useListStaff } from "@/dataconnect-generated/react"; import { dataConnect } from "@/features/auth/firebase"; import type { RootState } from "@/store/store"; export default function EditOrder() { const navigate = useNavigate(); const queryClient = useQueryClient(); const { toast } = useToast(); const { id: eventId } = useParams<{ id: string }>(); const { user } = useSelector((state: RootState) => state.auth); const [showReductionAlert, setShowReductionAlert] = useState(false); const [pendingUpdate, setPendingUpdate] = useState(null); const [originalRequested, setOriginalRequested] = useState(0); const { data: orderData, isLoading: isOrderLoading } = useGetOrderById( dataConnect, { id: eventId || "" }, { enabled: !!eventId } ); const event = orderData?.order; const { data: staffData } = useListStaff(dataConnect); const allStaff = staffData?.staffs || []; useEffect(() => { if (event) { setOriginalRequested(event.requested || 0); } }, [event]); const updateOrderMutation = useUpdateOrder(dataConnect, { onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["listOrders"] }); queryClient.invalidateQueries({ queryKey: ["getOrderById", { id: eventId }] }); toast({ title: "✅ Order Updated", description: "Your changes have been saved successfully.", }); navigate(createPageUrl("Events")); }, onError: (error) => { toast({ title: "❌ Update Failed", description: error.message || "Could not update the order. Please try again.", variant: "destructive", }); }, }); const canModify = useMemo(() => { if (!event) return false; if (!event.startDate) return true; const startTime = new Date(event.startDate); return startTime > new Date(); }, [event]); const handleSubmit = (eventData: any) => { if (!canModify) { toast({ title: "Cannot Edit Order", description: "This order has already started and cannot be modified.", variant: "destructive", }); return; } // CRITICAL: Recalculate requested count from current roles const totalRequested = eventData.shifts.reduce((sum: number, shift: any) => { const roles = Array.isArray(shift.roles) ? shift.roles : []; return sum + roles.reduce((roleSum: number, role: any) => roleSum + (parseInt(role.count) || 0), 0); }, 0); const assignedStaff = Array.isArray(event?.assignedStaff) ? event!.assignedStaff : []; const assignedCount = assignedStaff.length; const isVendor = user?.userRole === 'vendor' || (user as any)?.role === 'vendor'; // If client is reducing headcount and vendor has already assigned staff if (!isVendor && totalRequested < originalRequested && assignedCount > totalRequested) { setPendingUpdate({ ...eventData, requested: totalRequested }); setShowReductionAlert(true); toast({ title: "⚠️ Headcount Reduced", description: "Assigned staff exceeds new headcount. Please resolve assignments.", }); return; } if (eventId) { // Normal update updateOrderMutation.mutate({ id: eventId, eventName: eventData.event_name, date: eventData.date, startDate: eventData.startDate || eventData.date, endDate: eventData.endDate, notes: eventData.notes, shifts: eventData.shifts, requested: totalRequested, total: eventData.total, poReference: eventData.po_reference, } as any); } }; const handleAutoUnassign = async () => { if (!pendingUpdate || !event || !eventId) return; const assignedStaff = Array.isArray(event.assignedStaff) ? (event.assignedStaff as any[]) : []; const excessCount = assignedStaff.length - pendingUpdate.requested; // Calculate reliability scores for assigned staff const staffWithScores = assignedStaff.map(assigned => { const staffInfo = allStaff.find(s => s.id === assigned.staff_id || s.id === assigned.staffId); return { ...assigned, reliability: staffInfo?.averageRating ? staffInfo.averageRating * 20 : 50, // Convert 0-5 to 0-100 }; }); // Sort by reliability (lowest first) staffWithScores.sort((a: any, b: any) => a.reliability - b.reliability); // Remove lowest reliability staff const staffToKeep = staffWithScores.slice(excessCount); await updateOrderMutation.mutateAsync({ id: eventId, ...pendingUpdate, assignedStaff: staffToKeep.map((s: any) => ({ staffId: s.staffId || s.staff_id, staffName: s.staffName || s.staff_name, role: s.role })) } as any); setShowReductionAlert(false); setPendingUpdate(null); toast({ title: "✅ Staff Auto-Unassigned", description: `Removed ${excessCount} lowest reliability staff members`, }); }; const handleManualUnassign = () => { setShowReductionAlert(false); toast({ title: "Manual Adjustment Required", description: "Please manually remove excess staff from the order", }); }; if (isOrderLoading) { return (
); } if (!event) { return (

Event Not Found

); } return (
{!canModify && (

This order has already started. Some details may no longer be editable for security and tracking purposes.

)} {showReductionAlert && pendingUpdate && (
{ const staffInfo = allStaff.find(s => s.id === assigned.staffId || s.id === assigned.staff_id); return { name: assigned.staffName || assigned.staff_name, reliability: staffInfo?.averageRating ? staffInfo.averageRating * 20 : 50 }; }).sort((a, b) => a.reliability - b.reliability)} />
)} navigate(createPageUrl("Events"))} />
); }