diff --git a/src/pages/nearle/orders/orders.js b/src/pages/nearle/orders/orders.js index 942c5e2..59c74cc 100644 --- a/src/pages/nearle/orders/orders.js +++ b/src/pages/nearle/orders/orders.js @@ -1,19 +1,13 @@ import * as React from 'react'; -import { useState, useEffect, Fragment, useRef } from 'react'; -import { DeleteFilled, DeleteOutlined, ShoppingCartOutlined } from '@ant-design/icons'; -import { Empty } from 'antd'; +import { useState, useEffect, useRef } from 'react'; +import { DeleteFilled, CloseOutlined } from '@ant-design/icons'; import dayjs from 'dayjs'; import { useQuery, useMutation, useInfiniteQuery } from '@tanstack/react-query'; import { useTheme } from '@mui/material/styles'; -import { CloseOutlined } from '@ant-design/icons'; -import { PopupTransition } from 'components/@extended/Transitions'; -import CircularLoader from 'components/CircularLoader'; import Loader from 'components/Loader'; -import { KeyboardArrowDownOutlined, KeyboardArrowUpOutlined } from '@mui/icons-material'; +import CircularLoader from 'components/CircularLoader'; import { - MdPersonOff, - MdEventBusy, MdLocalShipping, MdHourglassEmpty, MdCheckCircle, @@ -23,24 +17,16 @@ import { MdOutlineCheckCircle, MdOutlineCancel, MdMyLocation, - MdGroups, - MdPlace, MdHistoryToggleOff, - MdCalendarMonth + MdPlace, + MdOutlineAssignmentInd } from 'react-icons/md'; -import DateFilterDialog from 'components/DateFilterDialog'; import DebounceSearchBar from 'components/nearle_components/DebounceSearchBar'; -import MainCard from 'components/MainCard'; import { OpenToast } from 'components/third-party/OpenToast'; import { OrdersTableSkeleton } from './OrdersTableSkeleton'; import LocationAutocomplete from 'components/nearle_components/LocationAutocomplete'; import PageHeader from 'components/nearle_components/PageHeader'; import StatCard from 'components/nearle_components/StatCard'; -import AiImage from '../../../assets/images/aiImage.png'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import { HiOutlineArrowLeft } from 'react-icons/hi'; - -import { IoReload } from 'react-icons/io5'; var utc = require('dayjs/plugin/utc'); dayjs.extend(utc); @@ -51,8 +37,6 @@ import { Grid, IconButton, Stack, - TextField, - Chip, Typography, Table, TableCell, @@ -61,45 +45,18 @@ import { Dialog, TableRow, DialogContent, - DialogTitle, Tooltip, - DialogActions, - Autocomplete, TableContainer, - Checkbox, useMediaQuery, Backdrop, - SpeedDial, - SpeedDialIcon, - SpeedDialAction, - Badge, - Divider, Paper, - Box + Box, + Skeleton } from '@mui/material'; -import { - fetchOrders, - fetchorderscount, - fetchPercentageData, - createOptimisationDeliveries, - // notifyRider, - cancelOrder, - getTenants, - gettenantlocations, - cancelMultipleOrder, - createAutomationDeliveries, - fetchPaymentType, - fetchRidersList, - finalCreatedeliveries, - notifyRider, - getallriders -} from '../../api/api'; +import { fetchOrders, fetchorderscount, fetchPercentageData, cancelOrder, autoAssignBooking } from '../../api/api'; import LoaderWithImage from 'components/nearle_components/LoaderWithImage'; import { MobileCard, MobileCardList, MobileField, MobileFieldGrid } from 'components/nearle_components/MobileCard'; -import { useNavigate } from 'react-router'; -import CSVExport from 'components/third-party/ReactTable'; -import Dispatch from '../dispatch/Dispatch'; // ============================================================================ // Design tokens — shared with deliveries / tenants / customers / pricing / @@ -141,277 +98,57 @@ const SoftPaper = (props) => ( /> ); -const DTAccentAvatar = ({ color, selected, size = 24, children }) => ( - - {children} - -); - -const pillFieldSx = () => ({ - '& .MuiOutlinedInput-root': { - borderRadius: '10px', - bgcolor: '#ffffff', - fontWeight: 600, - '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, - '&:hover fieldset': { borderColor: '#cbd5e1' }, - '&.Mui-focused': { boxShadow: `0 0 0 3px ${dtRing('#C01227')}` }, - '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 } - } -}); - -// Order row status meta — semantic palette for the per-row status badge. +// Doormile booking status palette — keyed by lowercased status string. const ROW_STATUS_META = { - created: { label: 'Created', color: '#0ea5e9', icon: MdLocalShipping }, - pending: { label: 'Pending', color: '#f59e0b', icon: MdHourglassEmpty }, - processing:{ label: 'Processing',color: '#0ea5e9', icon: MdHistoryToggleOff }, - modified: { label: 'Modified', color: '#06b6d4', icon: MdHistoryToggleOff }, - confirmed: { label: 'Confirmed', color: '#10b981', icon: MdCheckCircle }, - accepted: { label: 'Accepted', color: '#6366f1', icon: MdCheckCircle }, + pending_pickup: { label: 'Pending Pickup', color: '#f59e0b', icon: MdHourglassEmpty }, + miler_assigned: { label: 'Miler Assigned', color: '#6366f1', icon: MdLocalShipping }, + pickup_scheduled: { label: 'Pickup Scheduled', color: '#06b6d4', icon: MdHistoryToggleOff }, + at_customer: { label: 'At Customer', color: '#8b5cf6', icon: MdPlace }, + picked_up: { label: 'Picked Up', color: '#14b8a6', icon: MdCheckCircle }, + at_hub: { label: 'At Hub', color: '#0ea5e9', icon: MdPlace }, delivered: { label: 'Delivered', color: '#10b981', icon: MdCheckCircle }, - cancelled: { label: 'Cancelled', color: '#ef4444', icon: MdCancel } + cancelled: { label: 'Cancelled', color: '#ef4444', icon: MdCancel }, + assignment_failed: { label: 'Assignment Failed', color: '#ef4444', icon: MdCancel } }; -// Tab pill meta — controls the 4 top-level status tabs. +// Tab pill meta — "All" has no status filter; the other three map to real +// Doormile statuses. countKey matches what fetchorderscount/fetchPercentageData +// return (created = total, pending/delivered/cancelled = per-status counts). const ORDERS_STATUS_TABS = [ - { idx: 0, status: 'created', label: 'Created', color: BRAND, icon: MdLocalShipping, countKey: 'created' }, - { idx: 1, status: 'pending', label: 'Pending', color: '#f59e0b', icon: MdHourglassEmpty, countKey: 'pending' }, - { idx: 2, status: 'delivered', label: 'Delivered', color: '#10b981', icon: MdCheckCircle, countKey: 'delivered' }, - { idx: 3, status: 'cancelled', label: 'Cancelled', color: '#ef4444', icon: MdCancel, countKey: 'cancelled' } + { idx: 0, status: 'All', label: 'All', color: BRAND, icon: MdLocalShipping, countKey: 'created' }, + { idx: 1, status: 'Pending_Pickup', label: 'Pending', color: '#f59e0b', icon: MdHourglassEmpty, countKey: 'pending' }, + { idx: 2, status: 'Delivered', label: 'Delivered', color: '#10b981', icon: MdCheckCircle, countKey: 'delivered' }, + { idx: 3, status: 'Cancelled', label: 'Cancelled', color: '#ef4444', icon: MdCancel, countKey: 'cancelled' } ]; -const formatOrderDate = (row) => { - const dateCandidates = [row.pickupslot, row.deliverydate, row.orderdate]; - for (const candidate of dateCandidates) { - if (candidate && dayjs(candidate).isValid()) { - return `${dayjs(candidate).utc().format('DD/MM/YYYY')} ${dayjs(candidate).format('hh:mm A')}`; - } - } - return '—'; -}; - const Orders = () => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); - const navigate = useNavigate(); const loadMoreRef = useRef(); const containerRef = useRef(); - const locationRef = useRef(null); - const tenantRef = useRef(null); const [appId, setAppId] = useState(0); const [locaName, setLocoName] = useState('All'); - const [assignLoading, setAssignLoading] = useState(false); - const [startdate, setStartdate] = useState(dayjs().format('YYYY-MM-DD')); - const [enddate, setEnddate] = useState(dayjs().format('YYYY-MM-DD')); - const [datestatus, setDatestatus] = useState('Today'); - const [open, setOpen] = useState(false); const [tabvalue, setTabvalue] = useState(0); - const [currentStatus, setCurrentStatus] = useState('created'); + const [currentStatus, setCurrentStatus] = useState('All'); const [cancelDialog, setCancelDialog] = useState(false); - const [assignDialog, setAssignDialog] = useState(false); - const [multiDeleteDialog, setMultiDeleteDialog] = useState(false); - const [rider, setRider] = useState(null); - const [payment, setPayment] = useState(null); - const [orderheaderid, setOrderheaderid] = useState(''); + const [bookingIdToCancel, setBookingIdToCancel] = useState(null); const [page, setPage] = useState(0); - const [productCollapse, setProductCollapse] = useState(null); - const [tenantid, setTenantid] = useState(0); - const [locationid, setLocationid] = useState(0); const [searchword, setSearchword] = useState(''); const [debouncedSearch, setDebouncedSearch] = useState(''); - const [createloader, setCreateloader] = useState(false); - const [isLoading, setIsLoading] = useState(false); - const [tenantValue, setTenantValue] = useState(null); - const [locationValue, setLocationValue] = useState(null); - const [speedDialOpen, setSpeedDialOpen] = useState(false); - const [aiDialog, setAiDialog] = useState(false); - const [normalAssignDialog, setNormalAssignDialog] = useState(false); - const [dispatchPreviewData, setDispatchPreviewData] = useState(null); - const [deliverylist, setDeliverylist] = useState([]); - const [deliveryDetails, setDeliveryDetails] = useState([]); - const [, setZoneData] = useState(null); - const [, setMetaData] = useState(null); - const [aiMode] = useState(0); - const [csvExportData, setCsvExportData] = useState([]); - const [finaldeliveryList, setFinalDeliveryList] = useState([]); - - const aiModeRef = useRef(0); - // Caches the inputs of the most recent AI Assign call so we can forward them - // to the /nearle/dispatch/preview page via navigate state (the page re-uses - // them for its Re-Assign button). - const aiMutationContextRef = useRef(null); const rowsPerPage = 100; - const transportOptions = [ - { label: 'Bike', value: 1 }, - { label: 'Auto', value: 2 } - ]; - const [selectedMode, setSelectedMode] = useState(null); - // Riders the operator has marked as absent for today — passed to the AI - // assign API so its allocation skips them. Optional: the AI run still - // works with an empty list. - const [absentRiders, setAbsentRiders] = useState([]); - - // when orders are selected to show popup to stop unwanted reload - - // usePreventReload(shouldBlock); - - const tuningTypes = [ - { - tuneid: 1, - type: 'Balanced', - value: 'balanced' - }, - { - tuneid: 2, - type: 'Aggressive Speed', - value: 'aggressive_speed' - }, - { - tuneid: 3, - type: 'Fuel Saver', - value: 'fuel_saver' - }, - { - tuneid: 4, - type: 'Zone Strict', - value: 'zone_strict' - } - ]; - - // to clear the tenant and location autocomplete - useEffect(() => { - setTenantid(0); - setTenantValue(null); - setLocationid(0); - setLocationValue(null); - }, [appId]); - // to clear the location autocomplete - useEffect(() => { - setLocationid(0); - setLocationValue(null); - }, [tenantid]); - - // for csv file - useEffect(() => { - const filtered = finaldeliveryList.map((item) => ({ - zone_name: item.zone_name, - ordernotes: item.ordernotes, - rider: item.rider, - step: item.step, - ordertype: item.ordertype, - orderamount: item.orderamount, - riderkms: item.riderkms, - cumulativekms: item.cumulativekms, - baseprice: item.baseprice, - minkm: item.minkm, - priceperkm: item.priceperkm, - kms: item.kms, - actualkms: item.actualkms, - rider_charge: item.rider_charge, - deliveryamt: item.deliveryamt, - deliverycharges: item.deliverycharges, - profit: item.profit - })); - - setCsvExportData(filtered); - - console.log('csvExportData', filtered); - }, [finaldeliveryList]); - - // whenever thr delivery details get updated, delivery amt calculated and added - useEffect(() => { - if (!deliveryDetails?.length) return; - const updateDeliveryAmtList = deliveryDetails.map((list) => { - const cumulativeKms = Number(list.cumulativekms || 0); - const minKm = Number(list.minkm || 0); - const basePrice = Number(list.baseprice || 0); - const pricePerKm = Number(list.priceperkm || 0); - - if (cumulativeKms <= minKm) { - return { - ...list, - deliveryamt: basePrice - }; - } - return { - ...list, - deliveryamt: (cumulativeKms - minKm) * pricePerKm + basePrice - }; - }); - - setFinalDeliveryList(updateDeliveryAmtList); - console.log('finaldeliveryList', updateDeliveryAmtList); - }, [deliveryDetails]); - // ==============================|| fetchPercentageData ||============================== // - const { data: percentageData, isLoading: fetchpercentageIsLoading, isError: fetchpercentageIsError, - error: fetchpercentageError, - refetch: percentagedataRefetch + error: fetchpercentageError } = useQuery({ - queryKey: ['percentageData', appId, startdate, enddate, tenantid, locationid], - queryFn: fetchPercentageData, - enabled: true + queryKey: ['percentageData', appId, null, null, 0, 0], + queryFn: fetchPercentageData }); - - // ==============================|| getTenants ||============================== // - - const { - data: tenantlist, - isLoading: fetchtenantsIsLoading, - isError: fetchtenantsIsError, - error: fetchtenantsError - } = useQuery({ - queryKey: ['tenantlist', appId], - queryFn: () => getTenants(appId), // Ensure appId is passed - enabled: appId !== 0 // Ensures query runs only when appId is valid - }); - - // ==============================|| gettenantlocations ||============================== // - - const { - data: locationlist, - isLoading: fetchlocationsIsLoading, - isError: fetchlocationsIsError, - error: fetchlocationsError - } = useQuery({ - queryKey: ['gettenantlocations', tenantid], - queryFn: () => gettenantlocations(tenantid), // Ensure appId is passed - enabled: tenantid !== 0 // Ensures query runs only when appId is valid - }); - // ==============================|| fetchPaymentType ||============================== // - - const { - data: paymentModes = [], - isLoading: paymentModesLoading - } = useQuery({ - queryKey: ['paymentmodes'], - queryFn: fetchPaymentType - }); - // ==============================|| fetchRidersList ||============================== // - - const { - data: ridersList = [], - isLoading: ridersListLoading - } = useQuery({ - queryKey: ['ridersList', appId], // Unique key for caching & re-fetching - queryFn: fetchRidersList, - enabled: appId !== 0 // Ensures query runs only when appId is valid - }); // ==============================|| fetchorderscount ||============================== // - const { data: ordersCountData, isLoading: fetchorderscountIsLoading, @@ -419,23 +156,11 @@ const Orders = () => { error: fetchorderscountError, refetch: orderscountRefetch } = useQuery({ - queryKey: ['ordersCount', appId, startdate, enddate, currentStatus, tenantid, locationid], - queryFn: fetchorderscount, - refetchOnMount: true, - refetchOnWindowFocus: true - }); - // ==============================|| getallriders ||============================== // - - const { - data: autoRiders - } = useQuery({ - queryKey: ['getallriders'], - queryFn: getallriders, - refetchOnMount: true, - refetchOnWindowFocus: true + queryKey: ['ordersCount', appId, null, null, currentStatus, 0, 0], + queryFn: fetchorderscount }); - // ==============================|| getorders ||============================== // + // ==============================|| fetchOrders (bookings) ||============================== // const { data: orderData, isLoading: fetchOrdersIsLoading, @@ -446,13 +171,9 @@ const Orders = () => { isFetchingNextPage, refetch: ordersRefetch } = useInfiniteQuery({ - queryKey: ['fetchOrders', appId, currentStatus, debouncedSearch, startdate, enddate, rowsPerPage, tenantid, locationid], + queryKey: ['fetchOrders', appId, currentStatus, debouncedSearch, null, null, rowsPerPage, 0, 0], queryFn: fetchOrders, - getNextPageParam: (lastPage) => lastPage.nextPage ?? undefined, - refetchOnWindowFocus: true, - refetchOnMount: true, // 👈 ensures API triggers on page navigation - refetchOnReconnect: true, - staleTime: 0 + getNextPageParam: (lastPage) => lastPage.nextPage ?? undefined }); const rows = orderData?.pages.flatMap((page) => page.rows) || []; @@ -466,7 +187,7 @@ const Orders = () => { } }, { - root: document.querySelector('.MuiTableContainer-root'), // 👈 or explicitly TableContainer + root: document.querySelector('.MuiTableContainer-root'), rootMargin: '0px', threshold: 1.0 } @@ -486,451 +207,76 @@ const Orders = () => { } }; - // ======================================================= || createDeliveryMutation || ======================================================= - - const createDeliveryMutation = useMutation({ - // mutationFn: createDeliveries, // Using the separate function - // 0 -> manual rider assign 1 -> ai rider assign - mutationFn: aiModeRef.current == 0 ? createOptimisationDeliveries : createAutomationDeliveries, - onSuccess: (data, variables = []) => { - console.log('data', data); - console.log('varialbles', variables); - OpenToast('Orders Optimised Successfully', 'success', 2000); - orderscountRefetch(); + // ==============================|| autoAssignBooking ||============================== // + const assignMutation = useMutation({ + mutationFn: autoAssignBooking, + onSuccess: () => { + OpenToast('Booking assigned', 'success', 2000); ordersRefetch(); - // notifyRiderMutation.mutate(variables?.riderToken); // Call notifyRider after success - setAssignLoading(false); - setCreateloader(false); - if (aiModeRef.current == 0) { - setDeliveryDetails(data?.details); - setZoneData(data?.zones); - setMetaData(data?.meta); - setNormalAssignDialog(true); - // navigate('/nearle/orders/preview', { - // state: { - // zoneSummary: data?.zone_analysis, - // deliverylist: data?.details, - // zoneData: data?.zones, - // metaData: data?.meta, - // riderToken: rider.userfcmtoken, - // appId, - // aiMode: aiModeRef.current, - // reassignOrders - // } - // }); - } else { - setDeliveryDetails(data?.details); - setZoneData(data?.zones); - setMetaData(data?.meta); - setDispatchPreviewData(data); - // Route the AI Assign result to the dedicated Preview page (Dispatch - // view + Reconcile tab + Change Rider). The previous in-page dialog - // (aiDialog) is left intact but no longer opened — the page replaces - // it. All inputs needed for Re-Assign / Assign Orders are forwarded. - const ctx = aiMutationContextRef.current || {}; - navigate('/nearle/dispatch/preview', { - state: { - dispatchPreviewData: data, - aiMode: ctx.aiMode ?? aiModeRef.current, - selectedMode: ctx.selectedMode || selectedMode, - deliveryData: ctx.deliveryData || [], - autoRiders: ctx.autoRiders || autoRiders || [], - absentRidersPayload: ctx.absentRidersPayload || [], - rider: ctx.rider || rider, - appId: ctx.appId ?? appId, - tenantId: ctx.tenantid ?? tenantid, - startdate - } - }); - } + orderscountRefetch(); }, onError: (error) => { - OpenToast(error.message, 'error', 4000); - setCreateloader(false); - setAssignLoading(false); - }, - onSettled: () => { - assignDialogclose(); - setAssignLoading(false); - setCreateloader(false); - setIsLoading(false); - } - }); - // ======================================================= || handleManualCreateDelivery || ======================================================= - - const handleManualCreateDelivery = () => { - if (!finaldeliveryList?.length) { - OpenToast('No deliveries selected', 'error', 3000); - return; - } - createManualDeliveryMutation.mutate({ - deliveries: finaldeliveryList - }); - }; - - // ======================================================= || createManualDeliveryMutation || ======================================================= - const createManualDeliveryMutation = useMutation({ - mutationFn: finalCreatedeliveries, - onMutate: () => { - setIsLoading(true); - }, - onSuccess: (data) => { - console.log('create data', data); - OpenToast('Delivery Created Successfully', 'success', 2000); - navigate('/nearle/deliveries'); // ✅ no delay - // if (rider?.userfcmtoken) { - notifyRiderMutation.mutate(rider?.userfcmtoken); - // } - }, - - onError: (error) => { - OpenToast(error.message, 'error', 4000); - }, - - onSettled: () => { - setIsLoading(false); + OpenToast(error.response?.data?.message || error.message, 'error', 3000); } }); - // ==============================|| cancelOrder ||============================== // - + // ==============================|| cancelOrder ||============================== // + // NOTE: no Doormile "cancel booking" endpoint has been specified anywhere in + // the conversion work so far — this still calls the old /orders/updateorder + // path and will fail against api.doormile.com until a real endpoint exists. const cancelOrderMutation = useMutation({ mutationFn: cancelOrder, - onSuccess: (data) => { - if (data.status) { - setCancelDialog(false); - OpenToast('Order Cancelled Successfully', 'success', 2000); - orderscountRefetch(); - percentagedataRefetch(); - } - }, - onError: (error) => { - OpenToast(error.message, 'error', 2000); - } - }); - - // ==============================|| cancelMultipleOrder ||============================== // - - const cancelMultipleOrderMutation = useMutation({ - mutationFn: cancelMultipleOrder, - onSuccess: (data) => { - if (data.status) { - setMultiDeleteDialog(false); - OpenToast('Order Cancelled Successfully', 'success', 2000); - ordersRefetch(); - orderscountRefetch(); - percentagedataRefetch(); - setDeliverylist([]); - } - }, - onError: (error) => { - OpenToast(error.message, 'error', 2000); - } - }); - - // ======================================================= || notifyRiderMutation || ======================================================= - - const notifyRiderMutation = useMutation({ - mutationFn: notifyRider, // Using the separate function onSuccess: () => { - OpenToast('Notification sent Successfully', 'success', 2000); + setCancelDialog(false); + OpenToast('Order Cancelled Successfully', 'success', 2000); + ordersRefetch(); + orderscountRefetch(); }, onError: (error) => { - OpenToast(error.message, 'error', 2000); + OpenToast(error.response?.data?.message || error.message, 'error', 2000); } }); - // ======================================================= || handleCreateDelivery || ======================================================= - - const handleCreateDelivery = async (tune) => { - setIsLoading(true); - setAssignLoading(true); - const deliveryData = deliverylist.map((val) => ({ - ...val, - deliveryid: 0, - deliverydate: dayjs(val.deliverydate).utc().format('YYYY-MM-DD HH:mm:ss'), - assigntime: dayjs().format('YYYY-MM-DD HH:mm:ss'), - orderstatus: 'pending', - orderamount: val.deliverycharge, - droplat: val.deliverylat, - droplon: val.deliverylong, - pickuplat: val.pickuplat, - pickuplon: val.pickuplong, - ordernotes: val.ordernotes, - deliverycharges: val.deliverycharge, - pickuplocation: val.pickupsuburb, - deliverylocation: val.deliverysuburb - })); - console.log('deliveryData', deliveryData); - // Normalize the operator's "Absent Riders" picks into the {userid, username} - // shape the AI assign API expects. The API returns firstname/lastname, so - // we join them into a single `username` string (with a fallback to the - // raw `username` field when names are missing). - const absentRidersPayload = (absentRiders || []).map((r) => ({ - userid: r.userid, - username: - `${r.firstname || ''} ${r.lastname || ''}`.trim() || - r.username || - `Rider ${r.userid}` - })); - - // Remember the inputs so the Preview page can re-run Re-Assign with the - // same payload without us having to re-derive it from current Orders state. - aiMutationContextRef.current = { - deliveryData, - absentRidersPayload, - autoRiders, - selectedMode, - aiMode: aiModeRef.current, - rider, - appId, - tenantid - }; - - if (aiModeRef.current == 0) { - // manual assign - createDeliveryMutation.mutate({ - deliveries: deliveryData - }); - } else { - if (selectedMode && selectedMode?.value == 1) { - // bike auto assign - createDeliveryMutation.mutate({ - // mode 1 -> bike , 2 -> auto - deliveries: selectedMode.value == 1 ? deliveryData : { body: deliveryData }, - hypertuning_params: tune || null, - selectedMode, - absent_riders: absentRidersPayload - // reshuffle: 'joshi' - }); - } else { - createDeliveryMutation.mutate({ - // Auto auti assign - data: { - orders: deliveryData, - riders: autoRiders, - config: { - pay_type: 'hourly', // options: "hourly", "daily", or "orders" - base_pay: 300.0, - strategy: 'multi_trip' - }, - absent_riders: absentRidersPayload - }, - selectedMode - }); - } - } - }; - // ======================================================= || createFinalDeliveryMutation || ======================================================= - - const createFinalDeliveryMutation = useMutation({ - mutationFn: finalCreatedeliveries, // for optimised delivery create - onSuccess: (data, variables) => { - console.log('data', data); - console.log('varialbles', variables); - // notifyRiderMutation.mutate(rider.userfcmtoken); // Call notifyRider after success - OpenToast('Delivery Created Successfully', 'success', 2000); - setIsLoading(false); - navigate('/nearle/deliveries'); - }, - onError: (error) => { - OpenToast(error.message, 'error', 4000); - }, - onSettled: () => { - setIsLoading(false); - } - }); - - // ======================================================= || handleFinalCreateDelivery || ======================================================= - - const handleFinalCreateDelivery = async () => { - // console.log('Final delivery list:', finaldeliveryList); - - setIsLoading(true); - createFinalDeliveryMutation.mutate({ - deliveries: finaldeliveryList - }); - }; - - const handleChangetab = (e, i) => { + const handleChangetab = (i) => { setPage(0); setTabvalue(i); - if (i === 0) { - setCurrentStatus('created'); - } - if (i === 1) { - setCurrentStatus('pending'); - } - if (i === 2) { - setCurrentStatus('delivered'); - } - if (i === 3) { - setCurrentStatus('cancelled'); - } + setCurrentStatus(ORDERS_STATUS_TABS[i].status); setSearchword(''); }; - const assignDialogclose = () => { - setAssignDialog(false); - setRider(null); - setPayment(null); - setSelectedMode(null); - setAbsentRiders([]); - }; - const errorMessage = fetchpercentageIsError ? `Error fetching percentages: ${fetchpercentageError?.message}` : fetchorderscountIsError ? `Error fetching orders Count: ${fetchorderscountError?.message}` : fetchOrdersIsError ? `Error fetching orders : ${fetchOrdersError?.message}` - : fetchtenantsIsError - ? `Error Fetching on Tenants:${fetchtenantsError?.message} ` - : fetchlocationsIsError - ? `Error Fetching on Tenants Locations:${fetchlocationsError?.message} ` - : null; + : null; useEffect(() => { if (errorMessage) { - console.log(errorMessage); OpenToast(errorMessage, 'error', 3000); } }, [errorMessage]); return ( - - {(fetchpercentageIsLoading || - fetchorderscountIsLoading || - fetchOrdersIsLoading || - fetchtenantsIsLoading || - fetchlocationsIsLoading || - createloader) && ( - <> - - - > - )} - { - theme.zIndex.drawer + 1 - }} - open={createloader || fetchOrdersIsLoading} // when loader = true, backdrop covers the page - > - - - } - {} - {/* // ==============================|| SpeedDial ||============================== // */} - {deliverylist.length > 0 && ( - - - - } - open={speedDialOpen} - onOpen={() => setSpeedDialOpen(true)} - onClose={() => setSpeedDialOpen(false)} - sx={{ - position: 'fixed', - bottom: 52, - right: 16, - '& .MuiFab-primary': { - bgcolor: '#7b1fa2', - color: '#fff', - '&:hover': { - bgcolor: '#6a1b9a' - }, - width: 64, - height: 64 - } - }} - > - - } - tooltipTitle=" Optimisation" - FabProps={{ - sx: { - bgcolor: 'primary.main', - color: '#fff', - '&:hover': { - bgcolor: 'primary.dark' - }, - width: 64, - height: 64 - } - }} - onClick={() => { - aiModeRef.current = 1; - // setAiMode(1); - setSpeedDialOpen(false); - setAssignDialog(true); - }} - /> - } - tooltipTitle="Manual Assign" - FabProps={{ - sx: { - bgcolor: 'success.600', - color: '#fff', - '&:hover': { - bgcolor: 'success.dark' - }, - width: 64, - height: 64 - } - }} - onClick={() => { - aiModeRef.current = 0; - setSpeedDialOpen(false); - setAssignDialog(true); - }} - /> - - } - tooltipTitle="Delete" - FabProps={{ - sx: { - bgcolor: '#d32f2f', - color: '#fff', - '&:hover': { - bgcolor: '#9a0007' - }, - width: 64, - height: 64 - } - }} - onClick={() => { - setSpeedDialOpen(false); - setMultiDeleteDialog(true); - }} - /> - + <> + {(fetchpercentageIsLoading || fetchorderscountIsLoading || fetchOrdersIsLoading) && ( + <> + + + > )} + theme.zIndex.drawer + 1 }} open={fetchOrdersIsLoading}> + + + {/* ============================================= || Header || ============================================= */} { {/* ============================================= || KPI Cards || ============================================= */} {[ - { key: 'created', label: 'Created Orders', color: '#C01227', icon: MdOutlineReceiptLong, value: percentageData?.created, percentage: percentageData?.percentage1 }, - { key: 'pending', label: 'Pending Orders', color: '#f59e0b', icon: MdOutlinePendingActions, value: percentageData?.uncoveredOrders, percentage: percentageData?.percentage2 }, - { key: 'delivered', label: 'Delivered Orders', color: '#10b981', icon: MdOutlineCheckCircle, value: percentageData?.coveredOrders, percentage: percentageData?.percentage3 }, - { key: 'cancelled', label: 'Cancelled Orders', color: '#ef4444', icon: MdOutlineCancel, value: percentageData?.cancelled, percentage: percentageData?.percentage4 } + { key: 'created', label: 'Total Bookings', color: '#C01227', icon: MdOutlineReceiptLong, value: percentageData?.created, percentage: percentageData?.percentage1 }, + { key: 'pending', label: 'Pending Bookings', color: '#f59e0b', icon: MdOutlinePendingActions, value: percentageData?.uncoveredOrders, percentage: percentageData?.percentage2 }, + { key: 'delivered', label: 'Delivered Bookings', color: '#10b981', icon: MdOutlineCheckCircle, value: percentageData?.coveredOrders, percentage: percentageData?.percentage3 }, + { key: 'cancelled', label: 'Cancelled Bookings', color: '#ef4444', icon: MdOutlineCancel, value: percentageData?.cancelled, percentage: percentageData?.percentage4 } ].map((item) => { const Icon = item.icon; return ( @@ -969,180 +315,6 @@ const Orders = () => { })} - {/* ============================================= || Filter Bar (tenant, location, date) || ============================================= */} - - - - option?.tenantname || ''} - PaperComponent={SoftPaper} - onOpen={(event) => { - if (!appId) { - event.preventDefault(); - OpenToast('Please select location first!', 'warning', 3000); - setTimeout(() => { - locationRef.current?.focus(); - }, 0); - } - }} - onChange={(e, val, reason) => { - if (reason === 'clear') { - setTenantid(0); - setTenantValue(null); - setLocationid(0); - setLocationValue(null); - } else { - setTenantid(val?.tenantid || 0); - setTenantValue(val); - setLocationid(0); - setLocationValue(null); - } - }} - renderInput={(params) => ( - - - - - - ) - }} - /> - )} - /> - - - - (option ? `${option.locationname} (${option.suburb})` : '')} - value={locationValue} - PaperComponent={SoftPaper} - onOpen={(event) => { - if (!appId && !tenantid) { - event.preventDefault(); - OpenToast('Please select a your Location and Tenant first!', 'warning', 3000); - setTimeout(() => { - locationRef.current?.focus(); - }, 0); - } else if (!tenantid) { - event.preventDefault(); - OpenToast('Please select Tenant first!', 'warning', 3000); - setTimeout(() => { - tenantRef.current?.focus(); - }, 0); - } - }} - onChange={(e, val, reason) => { - if (reason === 'clear') { - setLocationid(0); - setLocationValue(null); - } else { - setLocationid(val.locationid || 0); - setLocationValue(val); - } - }} - renderInput={(params) => ( - - - - - - ) - }} - /> - )} - /> - - - - - - setOpen(true)} - sx={{ - display: 'inline-flex', - alignItems: 'center', - gap: 0.75, - px: 1.5, - py: 0.875, - borderRadius: '10px', - cursor: 'pointer', - bgcolor: '#ffffff', - border: '1px solid #e2e8f0', - color: '#475569', - fontWeight: 600, - fontSize: 12, - transition: 'border-color 0.15s, box-shadow 0.15s', - '&:hover': { borderColor: '#cbd5e1' }, - '& svg': { color: '#94a3b8' } - }} - > - - {dayjs(startdate).format('DD/MM/YY')} – {dayjs(enddate).format('DD/MM/YY')} - - - - {datestatus} - - - - - {/* ============================================= || filter Dialog | ============================================= */} - setOpen(false)} - onSelect={(range) => { - setStartdate(range.startDate); - setEnddate(range.endDate); - setDatestatus(range.label); - console.log('Selected Date Range:', range); - }} - /> - - {/* ============================================= || Status Tabs + Search || ============================================= */} { background: '#fff' }} > - + { return ( handleChangetab(e, t.idx)} + onClick={() => handleChangetab(t.idx)} sx={{ display: 'inline-flex', alignItems: 'center', @@ -1195,7 +361,7 @@ const Orders = () => { py: 0.5, flexShrink: 0, cursor: 'pointer', - borderRadius: DT.radiusField + 'px', + borderRadius: '10px', border: `1px solid ${active ? t.color : DT.borderSubtle}`, bgcolor: active ? t.color : DT.surface, color: active ? '#fff' : DT.textSecondary, @@ -1203,7 +369,7 @@ const Orders = () => { boxShadow: 'none', transition: 'background-color 0.15s, border-color 0.15s, color 0.15s', '&:hover': { - borderColor: active ? t.color : DT.borderHover, + borderColor: active ? t.color : '#cbd5e1', bgcolor: active ? t.color : DT.surfaceAlt } }} @@ -1218,10 +384,7 @@ const Orders = () => { > - + {t.label} { border: 'none' }} > - {count} + {fetchorderscountIsLoading ? : count} ); @@ -1252,7 +415,7 @@ const Orders = () => { value={searchword} onChange={setSearchword} onDebouncedChange={setDebouncedSearch} - placeholder="Search orders (ctrl+k)" + placeholder="Search bookings (ctrl+k)" sx={{ m: 0, width: '100%', @@ -1267,6 +430,7 @@ const Orders = () => { + {/* ============================================= || Table || ============================================= */} { - No {currentStatus} orders + No bookings to show - {searchword ? 'Try a different keyword.' : 'Adjust the filters above to load orders.'} + {searchword ? 'Try a different keyword.' : 'Adjust the filters above to load bookings.'} )} @@ -1316,63 +480,25 @@ const Orders = () => { - Loading orders… + Loading bookings… )} {rows?.map((row, index) => { - const isItemSelected = !!deliverylist.find((res) => res.orderheaderid === row.orderheaderid); - const handleCheckbox = (e) => { - if (!appId) { - OpenToast('Please select a location first!', 'warning', 2000); - locationRef.current?.focus(); - return; - } - if (e.target.checked) { - setDeliverylist((prev) => [...prev, { ...row, sno: prev.length + 1 }]); - } else { - setDeliverylist((prev) => - prev.filter((item) => item.orderheaderid !== row.orderheaderid).map((item, i) => ({ ...item, sno: i + 1 })) - ); - } - }; - const meta = ROW_STATUS_META[String(row.orderstatus || '').toLowerCase()] || { - label: row.orderstatus || '—', + const meta = ROW_STATUS_META[String(row.status || '').toLowerCase()] || { + label: row.status || '—', color: BRAND, icon: MdHistoryToggleOff }; const StatusIcon = meta.icon; - const chipSx = (c) => ({ - display: 'inline-flex', - alignItems: 'center', - justifyContent: 'center', - px: 1, - py: 0.25, - borderRadius: 999, - bgcolor: dtTint(c), - color: c, - fontWeight: 700, - fontSize: 11, - border: `1px solid ${dtEdge(c)}`, - whiteSpace: 'nowrap' - }); return ( - {currentStatus === 'created' && ( - - )} {String(page * rowsPerPage + index + 1).padStart(2, '0')} @@ -1395,1517 +521,298 @@ const Orders = () => { {meta.label} - {row.orderstatus === 'created' && ( - - {row.deliverytype === 'C' && ( + + {String(row.status || '').toLowerCase() === 'pending_pickup' && ( + { - if (productCollapse?.orderid === row.orderid) { - setProductCollapse(null); - } else { - setProductCollapse(row); - } - }} + disabled={assignMutation.isLoading} + onClick={() => assignMutation.mutate(row.bookingid)} sx={{ borderRadius: 999, - bgcolor: dtTint('#06b6d4'), - color: '#06b6d4', - border: `1px solid ${dtEdge('#06b6d4')}`, - '&:hover': { bgcolor: dtSoft('#06b6d4') } + bgcolor: dtSoft('#6366f1'), + color: '#6366f1', + border: `1px solid ${dtEdge('#6366f1')}`, + '&:hover': { bgcolor: '#6366f1', color: '#fff' } }} > - {productCollapse?.orderid === row.orderid ? ( - - ) : ( - - )} + - )} + + )} + { setCancelDialog(true); - setOrderheaderid(row.orderheaderid); + setBookingIdToCancel(row.bookingid); }} sx={{ borderRadius: 999, bgcolor: dtTint('#ef4444'), color: '#ef4444', border: `1px solid ${dtEdge('#ef4444')}`, - '&:hover': { bgcolor: dtSoft('#ef4444') }, - '&.Mui-disabled': { color: theme.palette.secondary.main } + '&:hover': { bgcolor: dtSoft('#ef4444') } }} > - - )} + + - {row.tenantname} + {row.bookingreference || `Booking #${row.bookingid}`} - {[row.tenantsuburb, row.applocation].filter(Boolean).join(' · ') || '—'} + {row.createdat ? dayjs(row.createdat).format('DD/MM/YYYY hh:mm A') : '—'} } > - - - {`${row.locationname}-(${row.locationsuburb})`} - - - {row.orderid} · {formatOrderDate(row)} + + + {row.pickupaddress || '—'} - - - {row.pickupcustomer || '—'} - - - {row.pickupcontactno} - - - {row.pickupsuburb || row.pickupaddress} + + + {row.deliveryaddress || '—'} - - - {row.deliverycustomer || '—'} - - - {row.deliverycontactno} - - - {row.deliverysuburb || row.deliveryaddress} - - - - - {row.kms || 0} km - - - - {row.collectionamt ? `₹ ${row.collectionamt.toFixed(2)}` : '—'} - - - - - {row.deliverycharge ? `₹ ${row.deliverycharge.toFixed(2)}` : '—'} - - - {row.ordernotes && ( - - - {row.ordernotes} - - - )} + ); })} - {rows?.length != 0 && ( + {rows?.length !== 0 && ( {isFetchingNextPage || hasNextPage ? ( ) : ( - No more orders + No more bookings )} )} ) : ( - - - - {currentStatus == 'created' && ( - - 0 && deliverylist.length !== rows?.length} - checked={deliverylist.length === rows?.length} - onChange={(e) => { - if (!appId) { - OpenToast('Please select a location first!', 'warning', 2000); - locationRef.current?.focus(); // Auto-focus on the Autocomplete input - return; - } - if (e.target.checked) { - const newList = rows?.map((row, index) => ({ - ...row, - sno: index + 1 - })); - setDeliverylist(newList); - } else { - setDeliverylist([]); - } - }} - /> - - )} - # - Tenant - Location - Pickup - Drop - QTY - COD - KMS - Charges - Notes - Status - {currentStatus == 'created' && Actions} - - - - {rows?.length === 0 && !fetchOrdersIsLoading && ( - - - - - - - - No {currentStatus} orders - - - {searchword ? 'Try a different keyword.' : 'Adjust the filters above to load orders.'} - - - + + + + # + Booking + Pickup + Delivery + Miler + Created + Status + Actions - )} - {fetchOrdersIsLoading && } - {rows?.map((row, index) => { - const isItemSelected = !!deliverylist.find((res) => res.orderheaderid === row.orderheaderid); - const handleCheckbox = (e) => { - if (!appId) { - OpenToast('Please select a location first!', 'warning', 2000); - locationRef.current?.focus(); - return; - } - if (e.target.checked) { - setDeliverylist((prev) => [...prev, { ...row, sno: prev.length + 1 }]); - } else { - setDeliverylist((prev) => - prev.filter((item) => item.orderheaderid !== row.orderheaderid).map((item, i) => ({ ...item, sno: i + 1 })) - ); - } - }; - - return ( - - {currentStatus === 'created' && ( - - - - )} - - {/* Serial Number */} - - {page * rowsPerPage + index + 1} - - - {/* Tenant Info */} - - - - {row.tenantname} + + + {rows?.length === 0 && !fetchOrdersIsLoading && ( + + + + + + + + No bookings to show - - {row.tenantsuburb} - + + {searchword ? 'Try a different keyword.' : 'Adjust the filters above to load bookings.'} - - {row.applocation} - - - - - {/* Order Info */} - - {/* */} - - {`${row.locationname}-(${row.locationsuburb})`} - - {/* */} - - - {row.orderid} - - - - - {formatOrderDate(row)} - - - - - {/* Pickup Info */} - - - - {row.pickupcustomer} - - {row.pickupcontactno} - - {`${row.pickupsuburb || row.pickupaddress.slice(0, 12) + '.....'}`} - - - {/* Delivery Info */} - - - + )} + {fetchOrdersIsLoading && } + {rows?.map((row, index) => { + const meta = ROW_STATUS_META[String(row.status || '').toLowerCase()] || { + label: row.status || '—', + color: BRAND, + icon: MdHistoryToggleOff + }; + const StatusIcon = meta.icon; + return ( + + + + {page * rowsPerPage + index + 1} + + + + + {row.bookingreference || `#${row.bookingid}`} + + + + + + {row.pickupaddress || '—'} + + + + + + + {row.deliveryaddress || '—'} + + + + + + {row.assignedmileruserid ? `#${row.assignedmileruserid}` : 'Unassigned'} + + + + + {row.createdat ? dayjs(row.createdat).format('DD/MM/YYYY hh:mm A') : '—'} + + + + - {row.deliverycustomer} - - {row.deliverycontactno} - - {`${row.deliverysuburb || row.deliveryaddress.slice(0, 12) + '.....'}`} - - - - {/* Quantity */} - - - {row.quantity ? ( - - {row.quantity} - - ) : ( - - {row.quantity} - - )} - - {/* cod */} - - {row.collectionamt ? ( - - ₹{row.collectionamt.toFixed(2)} - - ) : ( - - ₹{row.collectionamt.toFixed(2)} - - )} - - {/* kms */} - - - {row.kms} - - - {/* Charges */} - - {row.deliverycharge ? ( - - ₹{row.deliverycharge.toFixed(2)} - - ) : ( - - ₹{row.deliverycharge.toFixed(2)} - - )} - - - {/* Notes */} - - - {row.ordernotes} - - - - {/* Order Status */} - - {(() => { - const meta = ROW_STATUS_META[String(row.orderstatus || '').toLowerCase()] || { - label: row.orderstatus || '—', - color: BRAND, - icon: MdHistoryToggleOff - }; - const StatusIcon = meta.icon; - return ( - - {meta.label} - - ); - })()} - - - {/* Actions */} - {row.orderstatus === 'created' && ( - - - {row.deliverytype === 'C' && ( - + {meta.label} + + + + + {String(row.status || '').toLowerCase() === 'pending_pickup' && ( + { - if (productCollapse?.orderid === row.orderid) { - setProductCollapse(null); - } else { - setProductCollapse(row); - } + size="small" + disabled={assignMutation.isLoading} + onClick={() => assignMutation.mutate(row.bookingid)} + sx={{ + borderRadius: 999, + bgcolor: dtSoft('#6366f1'), + color: '#6366f1', + border: `1px solid ${dtEdge('#6366f1')}`, + '&:hover': { bgcolor: '#6366f1', color: '#fff' } }} > - {productCollapse?.orderid === row.orderid ? : } + )} - - + { setCancelDialog(true); - setOrderheaderid(row.orderheaderid); + setBookingIdToCancel(row.bookingid); + }} + sx={{ + borderRadius: 999, + bgcolor: dtTint('#ef4444'), + color: '#ef4444', + border: `1px solid ${dtEdge('#ef4444')}`, + '&:hover': { bgcolor: dtSoft('#ef4444') } }} > - + - )} + + ); + })} + {rows?.length !== 0 && ( + + + + {isFetchingNextPage || hasNextPage ? ( + + ) : ( + + No more bookings + + )} + + - ); - })} - {rows?.length != 0 && ( - - - - {isFetchingNextPage ? ( - - ) : hasNextPage ? ( - - ) : ( - - No more orders - - )} - - - - )} - - + )} + + )} - {/* ============================================= || Orders Preview Dialog | ============================================= */} - - { - theme.zIndex.modal + 1 - }} - open={createloader} - > - - - } - - - Preview Orders } variant="contained" /> - - - - - - - - - - # - - - Tenant{' '} - - - order Location - - - Pickup{' '} - - - Delivery - - - Notes - - - Charges - - - KMS - - - - - {deliverylist.map((val, i) => { - return ( - - - - {val.sno} - - - - - {val.tenantname} - - - {val.tenantsuburb} - - - - {val.applocation} - - - - - - - {`${val.locationname}-(${val.locationsuburb})`} - - - - - {val.orderid} - - - - - - {dayjs(val.orderdate).utc().format('DD/MM/YYYY')} - - - {dayjs(val.orderdate).utc().format('hh:mm A')} - - - - - - - {dayjs(val.deliverydate).utc().format('DD/MM/YYYY')} - - - - {dayjs(val.deliverydate).utc().format('hh:mm A')} - - - - - - - - {val.pickupcustomer} - {val.pickupcontactno} - - {val.pickupsuburb || val.pickupaddress.slice(0, 20)} - - - - - - - - {val.deliverycustomer} - {val.deliverycontactno} - - {val.deliverysuburb || val.deliveryaddress.slice(0, 20)} - - - - - {val.ordernotes} - ₹ {val.deliverycharge.toFixed(2)} - {val.kms} - - - ); - })} - - - - - - - - - - { - assignDialogclose(); - }} - startIcon={} - > - Close - - {aiModeRef.current == 1 && ( - option.label} - value={selectedMode} - onChange={(event, newValue) => { - setSelectedMode(newValue); - console.log('Selected value:', newValue?.value); // 1 or 2 - }} - renderInput={(params) => ( - - )} - isOptionEqualToValue={(option, value) => option.value === value.value} - /> - )} - - {/* Absent Riders multi-select — optional. Operator picks the - riders who are off today; the AI assign API receives their - {userid, username} under `absent_riders` and skips them - during allocation. Leaving it empty is valid: the AI run - proceeds against every rider in the location. */} - {aiModeRef.current == 1 && ( - setAbsentRiders(newValue)} - getOptionLabel={(option) => { - const name = `${option.firstname || ''} ${option.lastname || ''}`.trim(); - return name || `Rider #${option.userid}`; - }} - isOptionEqualToValue={(option, value) => option.userid === value.userid} - PaperComponent={(paperProps) => ( - - )} - ListboxProps={{ sx: { py: 0, maxHeight: 340 } }} - noOptionsText={ - - - - No riders to show for this location - - - } - renderTags={(value, getTagProps) => - value.map((option, index) => { - const name = - `${option.firstname || ''} ${option.lastname || ''}`.trim() || - `Rider #${option.userid}`; - const initials = - (name.match(/\b\w/g) || []).slice(0, 2).join('').toUpperCase() || '?'; - const tagProps = getTagProps({ index }); - return ( - - {initials} - - } - label={name} - sx={{ - height: 26, - bgcolor: '#fff7ed', - color: '#9a3412', - border: '1px solid', - borderColor: '#fdba74', - fontWeight: 600, - fontSize: 12, - '& .MuiChip-label': { px: 0.75 }, - '& .MuiChip-deleteIcon': { - color: '#c2410c', - fontSize: 16, - '&:hover': { color: '#7c2d12' } - } - }} - /> - ); - }) - } - renderOption={(props, option, { selected }) => { - const name = `${option.firstname || ''} ${option.lastname || ''}`.trim(); - const initials = - (name.match(/\b\w/g) || []).slice(0, 2).join('').toUpperCase() || '?'; - return ( - - - - {initials} - - - - {name || `Rider #${option.userid}`} - - - ID #{option.userid} - {option.contactno ? ` · ${option.contactno}` : ''} - - - {selected && ( - - )} - - ); - }} - renderInput={(params) => ( - - - {absentRiders.length > 0 && ( - - )} - {params.InputProps.startAdornment} - - ) - }} - sx={{ - minWidth: 300, - maxWidth: 440, - '& .MuiOutlinedInput-root': { - borderRadius: 2, - bgcolor: '#fffbf5', - transition: 'border-color 0.15s, box-shadow 0.15s', - '& fieldset': { - borderColor: '#fdba74', - borderWidth: 1.5 - }, - '&:hover fieldset': { borderColor: '#fb923c' }, - '&.Mui-focused': { - boxShadow: '0 0 0 3px rgba(251, 146, 60, 0.18)' - }, - '&.Mui-focused fieldset': { - borderColor: '#ea580c', - borderWidth: 2 - } - }, - '& .MuiInputLabel-root': { - fontWeight: 700, - fontSize: 13, - color: '#9a3412', - '&.Mui-focused': { color: '#9a3412' } - } - }} - /> - )} - sx={{ - '& .MuiAutocomplete-tag': { my: 0.25 }, - '& .MuiAutocomplete-endAdornment': { right: 8 } - }} - /> - )} - - - ) - } - onClick={() => { - setCreateloader(true); - handleCreateDelivery(); - }} - > - {assignLoading ? 'Optimising...' : aiModeRef.current == 0 ? 'Optimise Orders' : 'AI Optimise Orders'} - - - - - - - {/* ============================================= || Normal Assign Orders | ============================================= */} - - - - - - setNormalAssignDialog(false)} - sx={{ - backgroundColor: 'action.hover', - color: 'text.primary', - '&:hover': { - backgroundColor: 'action.selected' - } - }} - > - - - - - Assign Orders - - - - - - - - {(paymentModesLoading || ridersListLoading || isLoading) && ( - <> - - - > - )} - { - theme.zIndex.drawer + 1 - }} - open={paymentModesLoading || ridersListLoading || isLoading} // when loader = true, backdrop covers the page - > - - - } - - - - - - - # - - {aiMode == 1 && ( - - Zone{' '} - - )} - - Tenant{' '} - - - order Location - - - Pickup{' '} - - - Delivery - - - Notes - - {aiMode == 1 && ( - - Rider - - )} - - Type - - - Charges - - - KMS - - - - - {finaldeliveryList?.length == 0 && ( - - - - - - )} - {finaldeliveryList?.map((val, index) => { - return ( - - - {index + 1} - - - - - {val.tenantname} - - - {val.tenantsuburb} - - - - - {val.applocation} - - - - - - - {`${val.locationname}-(${val.locationsuburb})`} - - - - - {val.orderid} - - - - - - {dayjs(val.orderdate).utc().format('DD/MM/YYYY')} - - - {dayjs(val.orderdate).utc().format('hh:mm A')} - - - - - - - {dayjs(val.deliverydate).utc().format('DD/MM/YYYY')} - - - - {dayjs(val.deliverydate).utc().format('hh:mm A')} - - - - - - - - {val.pickupcustomer} - {val.pickupcontactno} - - {val.pickupsuburb || val.pickupaddress.slice(0, 20)} - - - - - - - - {val.deliverycustomer} - {val.deliverycontactno} - - {val.deliverysuburb || val.deliveryaddress.slice(0, 20)} - - - - - {val.ordernotes} - {/* {aiMode == 1 && ( - - {val.username} - ID : {val.userid} - - )} */} - - - - - - - - - - - - - - - - - - - - - - - - - ); - })} - - - - - - - - - {/* Top Inputs Section */} - - - } - onChange={(event, newValue, reason) => { - if (reason === 'clear') { - setPayment(null); - return; - } - - if (newValue) { - setPayment(newValue); - - const newList = finaldeliveryList?.map((list) => ({ - ...list, - paymenttype: newValue.apptypeid || 42 - })); - - setFinalDeliveryList(newList); - } - }} - /> - - - - } - onChange={(event, newValue, reason) => { - if (reason === 'clear') { - setRider(null); - return; - } - - if (newValue) { - setRider(newValue); - - const newList = finaldeliveryList?.map((list) => ({ - ...list, - userid: newValue.userid, - fuelcharge: newValue.fuelcharge || 0, - userfcmtoken: newValue.userfcmtoken - })); - - setFinalDeliveryList(newList); - } - }} - /> - - - - {/* Buttons Section */} - - } onClick={() => setNormalAssignDialog(false)}> - Back - - - - Assign Orders - - - - - {/* ============================================= || AI optimisation Assign Orders | ============================================= */} - - { - theme.zIndex.modal + 1 - }} - open={isLoading} - > - - - } - - - - - navigate('/nearle/orders')} - sx={{ - bgcolor: 'action.hover', - '&:hover': { bgcolor: 'action.selected' } - }} - > - - - - - Assign Orders - - - - option.type} - sx={{ minWidth: 250, maxWidth: 600, flex: 1 }} - renderInput={(params) => } - onChange={(e, val, reason) => { - if (reason === 'clear') { - handleCreateDelivery(null); - } else { - console.log('val', val); - handleCreateDelivery(val.value); - } - }} - /> - {/* option.type} - renderOption={(props, option, { selected }) => { - const { id, ...optionProps } = props; - const SelectionIcon = selected ? CheckBoxIcon : CheckBoxOutlineBlankIcon; - - return ( - - - {option.type} - - ); - }} - style={{ width: 400 }} - renderInput={(params) => ( - - )} - /> */} - } - onClick={() => { - setIsLoading(true); - handleCreateDelivery('reshuffle'); - }} - > - Re-Assign - - - - - - - {dispatchPreviewData && } - - - - } - onClick={() => { - // navigate('/nearle/orders'); - setAiDialog(false); - }} - > - Back - - - Assign Orders - - - - - {/* ========================================= || cancel order Dialog || ========================================= */} - handleClose()} maxWidth="xs"> + {/* ========================================= || cancel booking Dialog || ========================================= */} + setCancelDialog(false)} maxWidth="xs"> - - - - Are you sure you want to cancel this order? - - - + + Are you sure you want to cancel this booking? + { - cancelOrderMutation.mutate(orderheaderid); - // cancelridernotification(); - }} + onClick={() => cancelOrderMutation.mutate(bookingIdToCancel)} autoFocus > Yes, Cancel - { - setCancelDialog(false); - }} - color="secondary" - variant="outlined" - > + setCancelDialog(false)} color="secondary" variant="outlined"> No - {/* ========================================= || Multiple cancel order Dialog || ========================================= */} - setMultiDeleteDialog(false)} maxWidth="xs"> - - - - - - - - - Are you sure, you want to cancel multiple orders? - - - - - { - setMultiDeleteDialog(false); - }} - color="secondary" - variant="outlined" - > - No - - { - cancelMultipleOrderMutation.mutate(deliverylist); - // cancelMultipleOrderMutation.mutate(orderheaderid); - // cancelridernotification(); - }} - autoFocus - > - Yes, Cancel - - - - - - + > ); };