import { useParams, useNavigate } from 'react-router-dom';
import { Avatar, Box, Button, Chip, Grid, Paper, Stack, Step, StepLabel, Stepper, Typography, useMediaQuery } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import {
MdArrowBack,
MdLocalShipping,
MdPerson,
MdPhone,
MdLocationOn,
MdTwoWheeler,
MdStar,
MdOutlineSmartToy,
MdOutlineAssignmentInd,
MdOutlineCancel
} from 'react-icons/md';
import Loader from 'components/Loader';
import { OpenToast } from 'components/third-party/OpenToast';
import { getorderdetails, autoAssignBooking, cancelOrder } from 'pages/api/api';
const DT = {
radiusCard: 16,
textPrimary: '#0f172a',
textSecondary: '#64748b',
textMuted: '#94a3b8',
borderSubtle: '#e2e8f0',
divider: '#f1f5f9',
surface: '#ffffff',
surfaceAlt: '#f8fafc'
};
const a = (c, suffix) => `${c}${suffix}`;
const tint = (c) => a(c, '08');
const soft = (c) => a(c, '18');
const edge = (c) => a(c, '55');
const BRAND = '#C01227';
// Ordered status progression used for the stepper. Doormile's real status
// vocabulary — Assignment_Failed and Cancelled are terminal/off-path states
// shown separately rather than as stepper nodes.
const STATUS_STEPS = ['Pending_Pickup', 'Miler_Assigned', 'Pickup_Scheduled', 'At_Customer', 'Picked_Up', 'At_Hub', 'Delivered'];
const STEP_LABELS = {
Pending_Pickup: 'Pending Pickup',
Miler_Assigned: 'Miler Assigned',
Pickup_Scheduled: 'Pickup Scheduled',
At_Customer: 'At Customer',
Picked_Up: 'Picked Up',
At_Hub: 'At Hub',
Delivered: 'Delivered'
};
const InfoRow = ({ icon: Icon, label, value, color = BRAND }) => (
{label}
{value || '—'}
);
const BookingDetail = () => {
const { id } = useParams();
const navigate = useNavigate();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
const queryClient = useQueryClient();
const { data, isLoading, isError } = useQuery({
queryKey: ['bookingDetail', id],
queryFn: () => getorderdetails(id),
enabled: Boolean(id)
});
// Confirmed shape (booking id 5): bookingid, bookingreference, status,
// pickupaddress, deliveryaddress, assignedmileruserid, createdat,
// bookingparcels (nested parcels), serviceoptions, payments.
const booking = data?.data || data || {};
const reassignMutation = useMutation({
mutationFn: () => autoAssignBooking(id),
onSuccess: () => {
OpenToast('Reassignment triggered', 'success', 2000);
queryClient.invalidateQueries({ queryKey: ['bookingDetail', id] });
},
onError: (err) => OpenToast(err.response?.data?.message || err.message, 'error', 3000)
});
const cancelMutation = useMutation({
mutationFn: () => cancelOrder(id),
onSuccess: () => {
OpenToast('Booking cancelled', 'success', 2000);
queryClient.invalidateQueries({ queryKey: ['bookingDetail', id] });
},
onError: (err) => OpenToast(err.response?.data?.message || err.message, 'error', 3000)
});
if (isLoading) return ;
const status = booking.status || 'Pending_Pickup';
const isTerminal = ['cancelled', 'assignment_failed'].includes(String(status).toLowerCase());
const activeStepIdx = STATUS_STEPS.indexOf(status);
const parcels = booking.bookingparcels || booking.parcels || [];
const miler = booking.miler || booking.assignedmiler || null;
const agentDecision = booking.agent_decision_id ? booking.agentdecision || booking.agent_decision : null;
return (
<>
} onClick={() => navigate('/nearle/orders')} sx={{ color: DT.textSecondary, textTransform: 'none', fontWeight: 700 }}>
Back to Bookings
{booking.bookingreference || `Booking #${id}`}
{booking.createdat ? new Date(booking.createdat).toLocaleString() : '—'}
{isError && (
Could not load full booking details — showing whatever came back.
)}
{/* Status timeline */}
{!isTerminal && (
{STATUS_STEPS.map((s) => (
{STEP_LABELS[s]}
))}
)}
Customer & Pickup
Delivery
Assigned Miler
{booking.assignedmileruserid || miler ? (
{miler?.displayname || `Miler #${booking.assignedmileruserid}`}
{miler?.phone && (
{miler.phone}
)}
{miler?.rating != null && (
{miler.rating}
)}
) : (
No miler assigned yet.
)}
Parcel Details
{parcels.length === 0 ? (
No parcel details available.
) : (
{parcels.map((p, i) => (
{p.description || p.name || `Parcel ${i + 1}`}
{p.weight ? `${p.weight}kg` : ''}
))}
)}
{agentDecision && (
AI Assignment Reasoning
{agentDecision.reasoning || agentDecision.reason || JSON.stringify(agentDecision)}
)}
{!isTerminal && (
}
disabled={reassignMutation.isLoading}
onClick={() => reassignMutation.mutate()}
sx={{ bgcolor: '#6366f1', '&:hover': { bgcolor: '#4f46e5' } }}
>
Reassign Miler
)}
{!isTerminal && (
}
disabled={cancelMutation.isLoading}
onClick={() => cancelMutation.mutate()}
>
Cancel Booking
)}
>
);
};
export default BookingDetail;