import * as React from 'react'; import { useEffect, useState, useRef, Fragment } from 'react'; import { FormControl, InputAdornment, Grid, Typography, Stack, Button, TextField, Autocomplete, Chip, Divider, DialogTitle, DialogContent, Checkbox, DialogActions, CircularProgress, IconButton, Switch, OutlinedInput, FormGroup, FormControlLabel, Box, Card, useMediaQuery } from '@mui/material'; import CloseIcon from '@mui/icons-material/Close'; import { calculateDrivingDistance, calculateTotalCharge } from '../../../utils/distance'; import { Empty } from 'antd'; import { FaPhoneAlt, FaBox, FaBoxes, FaTruck, FaArrowRight, FaArrowLeft, FaCheck, FaRoute, FaMoneyBillWave, FaChartLine, FaReceipt, FaPaperPlane } from 'react-icons/fa'; import { GiDoorHandle } from 'react-icons/gi'; import { FaLandmarkDome } from 'react-icons/fa6'; import ClearIcon from '@mui/icons-material/Clear'; import { useNavigate } from 'react-router'; import { TbMapPinCode } from 'react-icons/tb'; import { FaLocationDot } from 'react-icons/fa6'; import axios from 'axios'; import { useTheme } from '@mui/material/styles'; import Geocode from 'react-geocode'; import Loader from 'components/Loader'; import * as geolib from 'geolib'; import MainCard from 'components/MainCard'; import { FaUser } from 'react-icons/fa6'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import Dialog from '@mui/material/Dialog'; import dayjs from 'dayjs'; import { enqueueSnackbar } from 'notistack'; var utc = require('dayjs/plugin/utc'); dayjs.extend(utc); import { SearchOutlined, CloseOutlined, CalendarOutlined, ClockCircleOutlined, FileTextOutlined, MessageOutlined } from '@ant-design/icons'; import MyLocationIcon from '@mui/icons-material/MyLocation'; import HighlightOffIcon from '@mui/icons-material/HighlightOff'; import { OpenToast } from 'components/third-party/OpenToast'; import { MapContainer, TileLayer, Marker, Polyline, useMap } from 'react-leaflet'; import L from 'leaflet'; import 'leaflet/dist/leaflet.css'; import './OrdersRedesign.css'; import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; import AnimateButton from 'components/@extended/AnimateButton'; const pickupIcon = typeof window !== 'undefined' ? new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-blue.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] }) : null; const dropoffIcon = typeof window !== 'undefined' ? new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] }) : null; const MapBoundsController = ({ startPoint, endPoint }) => { const map = useMap(); useEffect(() => { const points = []; const pLat = parseFloat(startPoint?.latitude); const pLng = parseFloat(startPoint?.longitude); const dLat = parseFloat(endPoint?.latitude); const dLng = parseFloat(endPoint?.longitude); if (!isNaN(pLat) && !isNaN(pLng) && pLat !== 0 && pLng !== 0) { points.push([pLat, pLng]); } if (!isNaN(dLat) && !isNaN(dLng) && dLat !== 0 && dLng !== 0) { points.push([dLat, dLng]); } if (points.length === 1) { map.setView(points[0], 14); } else if (points.length === 2) { map.fitBounds(points, { padding: [50, 50] }); } }, [startPoint?.latitude, startPoint?.longitude, endPoint?.latitude, endPoint?.longitude, map]); return null; }; const OrderMap = ({ startPoint, endPoint, appLocaLat, appLocaLng }) => { const defaultCenter = [ parseFloat(appLocaLat) || 11.0168, parseFloat(appLocaLng) || 76.9558 ]; const hasPick = startPoint?.latitude && startPoint?.longitude && parseFloat(startPoint.latitude) !== 0; const hasDrop = endPoint?.latitude && endPoint?.longitude && parseFloat(endPoint.latitude) !== 0; const pickCoords = hasPick ? [parseFloat(startPoint.latitude), parseFloat(startPoint.longitude)] : null; const dropCoords = hasDrop ? [parseFloat(endPoint.latitude), parseFloat(endPoint.longitude)] : null; const [routePoints, setRoutePoints] = React.useState([]); React.useEffect(() => { if (!hasPick || !hasDrop) { setRoutePoints([]); return; } const getOSRMRoute = async () => { const url = `https://router.project-osrm.org/route/v1/driving/${startPoint.longitude},${startPoint.latitude};${endPoint.longitude},${endPoint.latitude}?overview=full&geometries=geojson`; try { const res = await fetch(url); const data = await res.json(); if (data.routes?.length) { const points = data.routes[0].geometry.coordinates.map(([lng, lat]) => [lat, lng]); setRoutePoints(points); } else { setRoutePoints([pickCoords, dropCoords]); } } catch (err) { console.error('OSRM Error:', err); setRoutePoints([pickCoords, dropCoords]); } }; getOSRMRoute(); }, [startPoint.latitude, startPoint.longitude, endPoint.latitude, endPoint.longitude, hasPick, hasDrop]); return (
{hasPick && } {hasDrop && } {routePoints.length > 0 ? ( ) : ( hasPick && hasDrop && )}
); }; function loadScript(src, position, id) { if (!position) { return; } const script = document.createElement('script'); script.setAttribute('async', ''); script.setAttribute('id', id); script.src = src; position.appendChild(script); } const Createorder1 = () => { Geocode.setApiKey(process.env.REACT_APP_GOOGLE_MAPS_API_KEY); // ================================================= || GoogleMaps (Drawer) || ================================================= const loaded = React.useRef(false); const navigate = useNavigate(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); const locationRef = useRef(null); const tenantRef = useRef(null); const [inputValue1, setInputValue1] = React.useState(''); const [inputValue2, setInputValue2] = React.useState(''); const [tenanatLocoId, setTenanatLocoId] = useState(localStorage.getItem('locationid')); const [isLocation, setIsLocation] = useState(false); const textFieldRef1 = useRef(null); const textFieldRef1a = useRef(null); const textFieldRef2 = useRef(null); const [appId, setAppId] = useState(0); const [open, setOpen] = useState(false); const [clientdetail, setClientdetail] = useState([]); const [startdate, setStartdate] = useState(dayjs().format('MM-DD-YYYY')); // const [starttime, setStatrttime] = useState(`${dayjs().format('MM-DD-YYYY')} 08:00:00`); const [starttime, setStatrttime] = useState(); // const [endtime, setEndtime] = useState(`${dayjs().format('MM-DD-YYYY')} 20:00:00`); const [endtime, setEndtime] = useState(); const [timeslotarr, setTimeslotarr] = useState([]); const [otherinstructions, setOtherinstructions] = useState(''); const [loading2, setLoading2] = useState(false); const [loading, setLoading] = useState(false); const [btnLoading, setBtnLoading] = useState(false); const [alertmessage, setAlertmessage] = useState(''); const [admintoken, setAdmintoken] = useState(); const [tenant, setTenant] = useState({}); const [selectedtime, setSelectedtime] = useState(''); const [tenantlist, setTenantlist] = useState([]); const [startPoint, setStartPoint] = useState({ latitude: 0, longitude: 0 }); const [endPoint, setEndPoint] = useState({ latitude: 0, longitude: 0 }); const [showDistance, setShowDistance] = useState(false); const [distance, setDistance] = useState(0); const [basePrice, setBasePrice] = useState(0); const [pricePerKm, setPricePerKm] = useState(0); const [minKm, setMinKm] = useState(0); const [totalCharge, setTotalCharge] = useState(0); const [subCat, setSubCat] = useState([]); const [subCatName, setSubCatName] = useState('Select '); const [subCatId, setSubCatId] = useState(0); const [weight, setWeight] = useState(''); const [tenantid, setTenantid] = useState(0); const [locationid, setLocationid] = useState(0); const [selectedCatChip, setSelectedCatChip] = useState(null); const [isCustomerOpen, setIsCustomerOpen] = useState(false); const [searchCustList, setSearchCustList] = useState(''); const [customerlist, setCustomerlist] = useState([]); const [defaultPickup, setDefaultPickup] = useState(null); const [pickCust, setPickCust] = useState(null); const [dropCust, setDropCust] = useState(null); const [pickordrop, setpickordrop] = useState(0); // 1 ->pick 2 -> drop const [addId1, setAddId1] = useState(0); const [addId2, setAddId2] = useState(0); const [tenantLocations, setTenantlocations] = useState([]); const [appLocaLat, setAppLocaLat] = useState(); const [appLocaLng, setAppLocaLng] = useState(); const [appLocaRadius, setAppLocaRadius] = useState(); const [locations, setLocations] = useState('Select Location'); const userid = localStorage.getItem('userid'); const [isNumChange1, setIsNumChange1] = useState(0); const [isNumChange2, setIsNumChange2] = useState(0); const [showCheck1, setShowCheck1] = useState(0); const [showCheck2, setShowCheck2] = useState(0); const [pickNum, setPickNum] = useState(); const [dropNum, setdropNum] = useState(); const [numErr1, setNumErr1] = useState(false); const [numErr2, setNumErr2] = useState(false); const [isSms, setIsSms] = useState(0); const [collectionamt, setCollectionamt] = useState(0); const [quantity, setQuantity] = useState(1); const [tenantValue, setTenantValue] = useState(null); const [locationValue, setLocationValue] = useState(null); const [pickupSlotsList, setPickupSlotsList] = useState(null); const [pickupSlot, setPickupSlot] = useState(null); const [routeStep, setRouteStep] = useState(1); // 1 = Pickup, 2 = Drop const pickupStepComplete = !!( pickCust?.firstname && pickCust?.contactno && String(pickCust.contactno).length === 10 && pickCust?.doorno && pickCust?.suburb && pickCust?.postcode ); useEffect(() => { console.log('pickupSlotsList', pickupSlotsList); console.log('pickupSlot', pickupSlot); }, [pickupSlotsList, pickupSlot]); if (typeof window !== 'undefined' && !loaded.current) { if (!document.querySelector('#google-maps')) { loadScript( `https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_MAPS_API_KEY}&libraries=places&location=10.3656,77.9690&radius=50000&components=country:IN&strictbounds=true`, document.querySelector('head'), 'google-maps' ); } loaded.current = true; } // ==============================|| fetchAppLocations ||============================== // const fetchAppLocations = async () => { try { const locationRes = await axios.get(`${process.env.REACT_APP_URL}/partners/getlocations/?userid=${userid}`); console.log('fetchAppLocations', locationRes.data.details); setLocations(locationRes.data.details); } catch (err) { console.log('locationRes', err); } }; useEffect(() => { fetchAppLocations(); }, []); // ===================================================== || fetchtenantinfolist || ===================================================== const fetchtenantinfolist = async () => { setLoading(true); await axios .get(`${process.env.REACT_APP_URL}/tenants/gettenants/?applocationid=${appId}&status=active`) .then((res) => { console.log(res); if (res.data.status) { let arr = []; res.data.details.map((val) => { arr.push({ ...val, label: `${val.tenantname}` }); }); setTenantlist(arr); } setLoading(false); }) .catch((err) => { console.log(err); setLoading(false); }); }; useEffect(() => { appId && fetchtenantinfolist(); }, [appId]); const handleChipClick = (chipLabel) => { setSelectedCatChip(chipLabel); }; const chipStyle = (chipLabel) => ({ cursor: 'pointer', backgroundColor: selectedCatChip === chipLabel ? theme.palette.primary.main : 'default', color: selectedCatChip === chipLabel ? '#fff' : '', '&:hover': { backgroundColor: selectedCatChip === chipLabel ? theme.palette.primary.main : theme.palette.primary.light, color: '#fff' } }); const fetchTenantPricing = async (id) => { try { const pricingResponse = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantpricing/?tenantid=${id}`); console.log('pricingResponse', pricingResponse.data.details); setBasePrice(pricingResponse.data.details.baseprice); setPricePerKm(pricingResponse.data.details.priceperkm); setMinKm(pricingResponse.data.details.minkm); } catch (error) { console.log('fetchTenantPricing error', error); } }; useEffect(() => { console.log('startPoint', startPoint); console.log('endPoint', endPoint); if (startPoint.latitude != 0 && startPoint.longitude != 0 && endPoint.latitude != 0 && endPoint.longitude != 0) { // getDistance(); calculateDistance(startPoint, endPoint); } }, [startPoint, endPoint]); // google distance matrix logic const calculateDistance = async (pickup, drop) => { try { const roundedDistance = await calculateDrivingDistance(pickup, drop); console.log('calculated distance in km:', roundedDistance); setDistance(roundedDistance); const total = calculateTotalCharge(roundedDistance, basePrice, pricePerKm, minKm); console.log('total charge:', total); setTotalCharge(total); setShowDistance(true); if (roundedDistance > appLocaRadius) { setShowDistance(true); setOpen(true); } // ⏱️ Approximate duration const avgSpeed = 40; // km/h (adjust if needed) const duration = Math.round((roundedDistance / avgSpeed) * 60); // minutes console.log(`Distance: ${roundedDistance}, Duration: ${duration}`); } catch (error) { console.error('Error calculating distance:', error); } }; useEffect(() => { if (tenantid) { clientdetails(); } }, [searchCustList?.length > 3, searchCustList == '', tenantid]); useEffect(() => { if (timeslotarr[0]) { let arr = []; timeslotarr.map((val) => { if (dayjs().diff(dayjs(`${dayjs(startdate).format('MM-DD-YYYY')} ${dayjs(val).format('HH:mm:ss')}`), 'm') <= 0) { arr.push(val); } }); } }, [timeslotarr]); // ==================================================== || fetchtenantinfo || ==================================================== const fetchtenantinfo = async () => { setLoading(true); console.log('tenantid', tenantid); await axios .get(`${process.env.REACT_APP_URL}/tenants/gettenantinfo/?tenantid=${tenantid}`) .then((res) => { console.log('fetchtenantinfo', res); if (res.data.status) { setTenant(res.data.details); fetchAppAdminTokens(); setSubCatName(res.data.details.subcategoryname); setSubCatId(res.data.details.subcategoryid); } setLoading(false); }) .catch((err) => { console.log(err); setLoading(false); }); }; useEffect(() => { if (tenantid) { fetchtenantinfo(); } }, [tenantid]); // ==================================================== || getsubcategories || ==================================================== const getsubcategories = async () => { await axios .get(`${process.env.REACT_APP_URL}/utils/getsubcategories/?moduleid=6`) .then((res) => { console.log('subcateRes', res.data.details); if (res.data.status) { setSubCat(res.data.details); } }) .catch((err) => { console.log(err); }); }; useEffect(() => { getsubcategories(); }, []); // ==================================================== || fetchTiming || ==================================================== const fetchTiming = async () => { setLoading(true); await axios .get(`${process.env.REACT_APP_URL}/utils/getapplocations/?applocationid=${appId}`) .then((res) => { console.log('fetchTiming', res); const { opentime, closetime, latitude, longitude, radius } = res.data.details[0]; if (res.data.status) { setAppLocaLat(latitude); setAppLocaLng(longitude); setAppLocaRadius(radius); console.log('radius', radius); setStatrttime(`${dayjs().format('MM-DD-YYYY')} ${opentime}`); setEndtime(`${dayjs().format('MM-DD-YYYY')} ${closetime}`); console.log('starttime', `${dayjs().format('MM-DD-YYYY')} ${opentime}`); console.log('endtime', `${dayjs().format('MM-DD-YYYY')} ${closetime} `); let arr = []; for ( let i = `${dayjs().format('MM-DD-YYYY')} ${opentime}`, j = 0; dayjs(`${dayjs().format('MM-DD-YYYY')} ${closetime} `).diff(i, 'm') >= 0; j++, i = dayjs(i).add(30, 'm') ) { arr.push(i); } console.log('setTimeslotarr', arr); setTimeslotarr(arr); } setLoading(false); }) .catch((err) => { console.log(err); setLoading(false); }); }; useEffect(() => { if (appId) { fetchTiming(); } }, [appId]); // =============================================== || fetchAppAdminTokens (via appId) || =============================================== const fetchAppAdminTokens = async () => { setLoading(true); await axios .get(`${process.env.REACT_APP_URL}/utils/getapplocationconfig/?applocationid=${appId}`) .then((res) => { const userfcmtokemArray = res.data.details.applocationadmins.map((admin) => admin.userfcmtokem); // fcm => firebase cloud messaging if (res.data.status) { setAdmintoken(userfcmtokemArray); } setLoading(false); }) .catch((err) => { console.log(err); setLoading(false); }); }; useEffect(() => { if (starttime && endtime) { fetchAppAdminTokens(); } }, [starttime, endtime]); // =============================================== || opentoast || =============================================== const opentoast = (message, variant, time) => { enqueueSnackbar(message, { variant: variant, anchorOrigin: { vertical: 'top', horizontal: 'right' }, autoHideDuration: time ? time : 1500 }); console.log(alertmessage); }; const createsubmitobj2 = async () => { let arr = {}; arr = { orders: { applocationid: tenant.applolcationid, cancellled: '', categoryid: +tenant.categoryid, configid: 9, customerid: isNumChange1 == 0 ? +pickCust.customerid || 0 : 0, deliveryaddress: dropCust.address || '', deliverycharge: +totalCharge.toFixed(2) || 0, deliverycity: dropCust.city || '', deliverycontactno: dropCust.contactno || '', deliverycustomer: dropCust.firstname || '', deliveryid: isNumChange2 == 0 ? +dropCust.customerid || 0 : 0, deliverylandmark: dropCust.landmark || '', deliverylat: dropCust.latitude.toString(), deliverylocation: dropCust.suburb || '', deliverylocationid: dropCust.deliverylocationid || 0, deliverylong: dropCust.longitude.toString(), deliverytime: `${dayjs(startdate).format('YYYY-MM-DD')} ${dayjs(selectedtime.$d).format('HH:mm:ss')}`, deliverytype: 'B', delivered: '', itemcount: 1, kms: distance.toString() || 0, locationid: +locationid, moduleid: +tenant.moduleid, orderamount: +totalCharge.toFixed(2) || 0, ordercharges: 0.0, orderdate: dayjs().format('YYYY-MM-DD HH:mm:ss'), ordernotes: otherinstructions, orderstatus: 'created', ordervalue: +totalCharge.toFixed(2) || 0, partnerid: tenant.partnerid, partneruserid: +userid, paymentstatus: 1, paymenttype: 42, pickupaddress: pickCust.address || '', pickupcity: pickCust.city || '', pickupcontactno: pickCust.contactno || '', pickupcustomer: pickCust.firstname || '', pickuplandmark: pickCust.landmark || '', pickuplat: pickCust.latitude.toString() || '', pickuplocation: pickCust.suburb || '', pickuplocationid: pickCust.deliverylocationid || 0, pickuplong: pickCust.longitude.toString() || '', smsdelivery: isSms, subcategoryid: +subCatId, tenantid: tenant.tenantid, collectionamt: +collectionamt, quantity: +quantity, weight, pickupSlot }, pickup: { address: pickCust.address || '', applocationid: tenant.applolcationid, city: pickCust.city || '', configid: 1, contactno: pickCust.contactno || '', customertoken: '', customerid: isNumChange1 == 0 ? pickCust.customerid || 0 : 0, devicetype: '', deviceid: '', dialcode: '+91', doorno: pickCust.doorno || '', email: pickCust.email || '', firstname: pickCust.firstname || '', landmark: pickCust.landmark || '', latitude: pickCust.latitude.toString() || '', longitude: pickCust.longitude.toString() || '', postcode: pickCust.postcode || '', primaryaddress: 1, locationid: pickCust.deliverylocationid || 0, profileimage: '', state: pickCust.state || '', suburb: pickCust.suburb || '', tenantid: tenant.tenantid }, drop: { address: dropCust.address || '', applocationid: tenant.applolcationid, city: dropCust.city || '', configid: 1, contactno: dropCust.contactno || '', customertoken: '', customerid: isNumChange2 == 0 ? dropCust.customerid || 0 : 0, devicetype: '', deviceid: '', locationid: dropCust.deliverylocationid || 0, dialcode: '+91', doorno: dropCust.doorno || '', email: dropCust.email || '', firstname: dropCust.firstname || '', landmark: dropCust.landmark || '', latitude: dropCust.latitude.toString(), longitude: dropCust.longitude.toString(), postcode: dropCust.postcode || '', primaryaddress: 1, profileimage: '', state: dropCust.state || '', suburb: dropCust.suburb || '', tenantid: tenant.tenantid } }; console.log('createsubmitobj2', arr); if (!pickCust.firstname) { opentoast('Enter Pickup Contact Name ', 'warning', 2000); } else if (!pickCust.contactno) { opentoast('Enter Pickup Contact Number ', 'warning', 2000); } else if (pickCust.contactno.length != 10) { opentoast('Check Pickup Contact Number ', 'error', 2000); } else if (!pickCust.suburb) { opentoast('Enter Pickup Location ', 'warning', 2000); } else if (!pickCust.city) { opentoast('Enter Pickup City ', 'warning', 2000); } else if (!pickCust.postcode) { opentoast('Enter Pickup Postcode ', 'warning', 2000); } else if (!pickCust.landmark) { opentoast('Enter Pickup Landmark ', 'warning', 2000); } else if (!dropCust.firstname) { opentoast('Enter Drop Contact Name ', 'warning', 2000); } else if (!dropCust.contactno) { opentoast('Enter Drop Contact Number', 'warning', 2000); } else if (dropCust.contactno.length !== 10) { opentoast('Check Drop Contact Number ', 'error', 2000); } else if (!dropCust.suburb) { opentoast('Enter Drop Suburb ', 'warning', 2000); } else if (!dropCust.city) { opentoast('Enter Drop City ', 'warning', 2000); } else if (!dropCust.postcode) { opentoast('Enter Drop postcode ', 'warning', 2000); } else if (!dropCust.landmark) { opentoast('Enter Drop Landmark ', 'warning', 2000); } else if (!selectedtime) { opentoast('Choose deliverytime ', 'warning', 2000); } else if (!setSubCatId) { opentoast('Choose SubCategory ', 'warning', 2000); } else { try { const createRes = await axios.post(`${process.env.REACT_APP_URL2}/orders/createorder`, arr); if (createRes.data.status) { console.log('createRes', createRes); enqueueSnackbar('Order Created Successfully', { variant: 'success', anchorOrigin: { vertical: 'top', horizontal: 'right' }, autoHideDuration: 1000 }); if (admintoken) { // notifyadmin(admintoken); sendnotifications(); } navigate('/nearle/orders'); } else { opentoast('Error in creating orders', 'warning'); } setLoading(false); } catch (error) { opentoast(error.message, 'warning'); console.log('createResErr', error); } } }; // ========================================================= || clientdetails || ========================================================= const clientdetails = async () => { setLoading2(true); try { let url = searchCustList == '' ? `${process.env.REACT_APP_URL}/customers/gettenantcustomers/?tenantid=${tenantid}&pageno=1&pagesize=30` : `${process.env.REACT_APP_URL}/customers/search/?tenantid=${tenantid}&keyword=${searchCustList}`; await axios .get(url) .then((res) => { if (res.data.status) { console.log('clientdetails', res.data.details); setClientdetail(res.data.details); setCustomerlist(res.data.details); } setLoading2(false); }) .catch((err) => { console.log(err); setLoading2(false); opentoast('server error', 'warning'); }); } catch (err) { console.log(err); setLoading2(false); } }; // ================================================== || sendnotifications || ================================================== const sendnotifications = async () => { setLoading(true); await axios .post(`${process.env.REACT_APP_URL}/utils/sendnotifications`, { priority: 'high', registration_ids: admintoken, data: { accessid: process.env.REACT_APP_RIDER_ACCESS_ID }, notification: { title: 'Nearle Merchant', body: 'An Order has been placed successfully,kindly process the same', sound: 'ring' } }) .then((res) => { console.log(res); if (res.data.message == 'Success') { enqueueSnackbar('Notification sent Successfully', { variant: 'success', anchorOrigin: { vertical: 'top', horizontal: 'right' }, autoHideDuration: 1000 }); } setLoading(false); }) .catch((err) => { console.log(err); enqueueSnackbar(err.message, { variant: 'error', anchorOrigin: { vertical: 'top', horizontal: 'right' }, autoHideDuration: 1000 }); setLoading(false); }); }; // ============================================= || Google Maps Autocomplete(pick) || ============================================= useEffect(() => { // Initialize Google Maps Autocomplete if (inputValue1) { const autocompleteInput = document.getElementById('addressAuto1'); const autocomplete = new window.google.maps.places.Autocomplete(autocompleteInput, { // types: ['(cities)'], // You can adjust the types parameter based on your requirements strictBounds: true, bounds: new window.google.maps.Circle({ // center: new window.google.maps.LatLng(11.0050707, 76.9509083), // radius: 100000 center: new window.google.maps.LatLng(appLocaLat, appLocaLng), radius: appLocaRadius * 1000 }).getBounds() }); // Event listener for autocomplete place changed autocomplete.addListener('place_changed', () => { const place = autocomplete.getPlace(); setInputValue1(`${place.name}, ${place.formatted_address}`); console.log('new place', place); // Do something with the selected place console.log(' pick (new place) lat lng', { lat: place.geometry.location.lat(), lng: place.geometry.location.lng() }); // Do something with the selected place // to trigger getDistance setStartPoint({ latitude: place.geometry.location.lat(), longitude: place.geometry.location.lng() }); setPickCust({ ...pickCust, address: `${place.name} ${place.formatted_address}` }); const address = { address: `${place.name} ${place.formatted_address}`, street_number: '', route: '', locality: '', sublocality_level_1: '', administrative_area_level_3: '', administrative_area_level_1: '', country: '', postal_code: '' }; place.address_components.forEach((component) => { component.types.forEach((type) => { switch (type) { case 'street_number': address.street_number = component.long_name; break; case 'route': address.route = component.long_name; break; case 'locality': address.locality = component.long_name; break; case 'sublocality_level_1': address.sublocality_level_1 = component.long_name; break; case 'administrative_area_level_3': address.administrative_area_level_3 = component.long_name; break; case 'administrative_area_level_1': address.administrative_area_level_1 = component.long_name; break; case 'country': address.country = component.long_name; break; case 'postal_code': address.postal_code = component.long_name; break; // Add more cases as needed for other types } }); }); // Use address object as per your requirements setPickCust({ ...pickCust, address: address.address, doorno: `${address.street_number} ${address.route}`, suburb: address.sublocality_level_1, city: address.locality, postcode: address.postal_code, latitude: place.geometry.location.lat(), longitude: place.geometry.location.lng() }); console.log('Pick Address:', address); }); } }, [inputValue1]); // ============================================= || Google Maps Autocomplete(Drop) || ============================================= useEffect(() => { if (inputValue2) { // Initialize Google Maps Autocomplete const autocompleteInput = document.getElementById('addressAuto2'); const autocomplete = new window.google.maps.places.Autocomplete(autocompleteInput, { // types: ['(cities)'], // You can adjust the types parameter based on your requirements strictBounds: true, bounds: new window.google.maps.Circle({ // center: new window.google.maps.LatLng(11.0050707, 76.9509083), center: new window.google.maps.LatLng(appLocaLat, appLocaLng), radius: appLocaRadius * 1000 //km to m // radius: 100000 //km to m }).getBounds() }); let arr = []; // Event listener for autocomplete place changed autocomplete.addListener('place_changed', () => { const place = autocomplete.getPlace(); setInputValue2(`${place.name}, ${place.formatted_address}`); console.log('new place', place); // Do something with the selected place console.log('drop (new place) lat lng', { lat: place.geometry.location.lat(), lng: place.geometry.location.lng() }); // Do something with the selected place setEndPoint({ latitude: place.geometry.location.lat(), longitude: place.geometry.location.lng() }); setDropCust({ ...dropCust, address: `${place.name} ${place.formatted_address}` }); const address = { address: `${place.name} ${place.formatted_address}`, street_number: '', route: '', locality: '', sublocality_level_1: '', administrative_area_level_3: '', administrative_area_level_1: '', country: '', postal_code: '' }; place.address_components.forEach((component) => { component.types.forEach((type) => { switch (type) { case 'street_number': address.street_number = component.long_name; break; case 'route': address.route = component.long_name; break; case 'locality': address.locality = component.long_name; break; case 'sublocality_level_1': address.sublocality_level_1 = component.long_name; break; case 'administrative_area_level_3': address.administrative_area_level_3 = component.long_name; break; case 'administrative_area_level_1': address.administrative_area_level_1 = component.long_name; break; case 'country': address.country = component.long_name; break; case 'postal_code': address.postal_code = component.long_name; break; // Add more cases as needed for other types } }); }); // Use address object as per your requirements setDropCust({ ...dropCust, address: address.address, doorno: `${address.street_number} ${address.route}`, suburb: address.sublocality_level_1, city: address.locality, postcode: address.postal_code, latitude: place.geometry.location.lat(), longitude: place.geometry.location.lng() }); console.log('Drop Address:', address); }); } }, [inputValue2]); // ============================================= || gettenantlocations (branches) || ============================================= const gettenantlocations = async (id) => { try { const res = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantlocations/?tenantid=${id}`); console.log('gettenantlocations', res.data.details); if (res.data.details.length == 1) { setTenantlocations(res.data.details); setDefaultPickup(res.data.details[0]); setLocationid(res.data.details[0].locationid); setLocationValue(res.data.details[0].locationid); setPickupSlotsList(res.data.details[0].slots); } else { setTenantlocations(res.data.details); } } catch (err) { console.log('gettenantlocations', err); } }; return ( <> {loading && } {loading2 && } {/* Header Section — single white card spanning the full row: title on the left, service configurators inline on the right. */} Create New Order {/* Choose App location */} `${option.locationname}`} className="header-compact-input" onChange={(event, value, reason) => { if (reason === 'clear') { setAppId(0); setTenantid(0); setTenantValue(null); setTenantlist([]); setLocationid(0); setLocationValue(null); setTenantlocations([]); setPickCust(null); setDropCust(null); } else { setAppId(value.applocationid); setPickCust(null); setDropCust(null); setTenantid(0); setTenantValue(null); setLocationid(0); setLocationValue(null); setTenantlocations([]); } }} renderInput={(params) => ( {params.InputProps.startAdornment} ) }} /> )} /> {/* Choose Client */} { if (!appId) { event.preventDefault(); OpenToast('Please select a your location first!', 'warning', 3000); setTimeout(() => { locationRef.current?.focus(); }, 0); } }} onChange={(e, val, reason) => { if (reason == 'clear') { setTenantid(0); setTenantValue(null); setLocationid(0); setLocationValue(null); setTenantlocations([]); setPickCust(null); setDropCust(null); } else { setTenantid(val?.tenantid || 0); setTenantValue(val); setLocationid(0); setLocationValue(null); fetchTenantPricing(val.tenantid); gettenantlocations(val.tenantid); setDropCust(null); } }} renderInput={(params) => ( {params.InputProps.startAdornment} ) }} /> )} /> {/* Business Location */} {tenantLocations.length == 1 ? ( ) }} /> ) : ( `${option.locationname} (${option.suburb})` || ''} onOpen={(event) => { if (!appId && !tenantid) { event.preventDefault(); OpenToast('Please select Location and Tenant first!', 'warning', 3000); setTimeout(() => { locationRef.current?.focus(); }, 0); } else if (!tenantid) { event.preventDefault(); OpenToast('Please select a your Tenant first!', 'warning', 3000); setTimeout(() => { tenantRef.current?.focus(); }, 0); } }} onChange={(event, value, reason) => { if (reason === 'clear') { setLocationid(0); setLocationValue(null); setPickCust(null); } else { setLocationid(value.locationid || 0); setLocationValue(value); setDefaultPickup(value); setPickupSlotsList(value?.slots); } }} renderInput={(params) => ( {params.InputProps.startAdornment} ) }} /> )} /> )} {/* Workspace 2-Column responsive layout */} {/* Left Column: Form & Configurator (7.5 columns on lg+) */} {/* Card 2: Route Planner (Pickup & Drop) — tighter padding on md+ since the two panels now sit side-by-side and need the horizontal room. */} {/* Two-step stepper: Pickup → Drop */} setRouteStep(1)} role="button" tabIndex={0} > {pickupStepComplete && routeStep !== 1 ? : '1'} Pickup Where to collect { if (pickupStepComplete) { setRouteStep(2); } else { opentoast('Please complete Pickup details first', 'warning', 2000); } }} role="button" tabIndex={0} > 2 Drop Where to deliver {/* Pickup Details Block */} Pickup Where to collect the parcel {/* Contact group */} Contact ), style: { borderRadius: '10px' } }} variant="outlined" label="Contact Name" value={pickCust?.firstname || ''} onChange={(e) => { setPickCust({ ...pickCust, firstname: e.target.value }); }} /> ), style: { borderRadius: '10px' } }} variant="outlined" label="Contact Number" value={pickCust?.contactno || ''} onChange={(e) => { if (e.target.value.length <= 10) { setPickCust({ ...pickCust, contactno: e.target.value }); } if (pickNum == e.target.value) { setShowCheck1(0); } else { setShowCheck1(1); } if (e.target.value.length < 10) { setNumErr1(true); } else { setNumErr1(false); } }} /> {/* Address Autocomplete */} Address Lookup {addId1 == 0 ? ( setInputValue1(e.target.value)} helperText="Start typing to auto-fill the address details below" FormHelperTextProps={{ className: 'address-search-helper pickup-helper' }} InputProps={{ startAdornment: ( ), endAdornment: ( { setInputValue1(''); setPickCust({ ...pickCust, doorno: '', suburb: '', city: '', postcode: '', landmark: '' }); setShowDistance(false); setStartPoint({ latitude: 0, longitude: 0 }); }} size="small" > ), style: { borderRadius: '10px', background: '#fff' } }} /> ) : ( ), endAdornment: ( { setAddId1(0); setPickCust({ ...pickCust, doorno: '', suburb: '', city: '', postcode: '', landmark: '' }); setShowDistance(false); setStartPoint({ latitude: 0, longitude: 0 }); }} size="small" > ), style: { borderRadius: '10px', background: '#fff' } }} value={pickCust?.address || ''} onChange={(e) => { setPickCust({ ...pickCust, address: e.target.value }); if (e.target.value == '') { setAddId1(0); setShowDistance(false); setStartPoint({ latitude: 0, longitude: 0 }); } }} /> )} {/* Address details */} Address Details ), style: { borderRadius: '10px' } }} variant="outlined" label="Door No / Street" value={pickCust?.doorno || ''} onChange={(e) => { setPickCust({ ...pickCust, doorno: e.target.value }); }} /> ), style: { borderRadius: '10px' } }} variant="outlined" label="Location" value={pickCust?.suburb || ''} onChange={(e) => { setPickCust({ ...pickCust, suburb: e.target.value }); }} /> ), style: { borderRadius: '10px' } }} variant="outlined" label="Postcode" value={pickCust?.postcode || ''} onChange={(e) => { setPickCust({ ...pickCust, postcode: e.target.value }); }} /> ), style: { borderRadius: '10px' } }} variant="outlined" label="Landmark" value={pickCust?.landmark || ''} onChange={(e) => { setPickCust({ ...pickCust, landmark: e.target.value }); }} /> {/* Save for later */} {showCheck1 == 1 && ( { setIsNumChange1(e.target.checked ? 1 : 0); }} /> } label="Save contact for later" /> )} {/* Step navigation */} {pickupStepComplete ? 'Pickup looks good. Proceed to Drop details.' : 'Fill the required Pickup fields to continue.'} {/* Drop Details Block */} Drop Where to deliver the parcel {/* Contact group */} Contact ), style: { borderRadius: '10px' } }} value={dropCust?.firstname || ''} onChange={(e) => { setDropCust({ ...dropCust, firstname: e.target.value }); }} /> ), style: { borderRadius: '10px' } }} value={dropCust?.contactno || ''} onChange={(e) => { if (e.target.value.length <= 10) { setDropCust({ ...dropCust, contactno: e.target.value }); } if (dropNum == e.target.value) { setShowCheck2(0); } else { setShowCheck2(1); } if (e.target.value.length < 10) { setNumErr2(true); } else { setNumErr2(false); } }} /> {/* Address Autocomplete */} Address Lookup {addId2 == 0 ? ( setInputValue2(e.target.value)} helperText="Start typing to auto-fill the address details below" FormHelperTextProps={{ className: 'address-search-helper drop-helper' }} InputProps={{ startAdornment: ( ), endAdornment: ( { setInputValue2(''); setDropCust({ ...dropCust, doorno: '', suburb: '', city: '', postcode: '', landmark: '' }); setShowDistance(false); setEndPoint({ latitude: 0, longitude: 0 }); }} size="small" > ), style: { borderRadius: '10px', background: '#fff' } }} /> ) : ( ), endAdornment: ( { setAddId2(0); setDropCust({ ...dropCust, doorno: '', suburb: '', city: '', postcode: '', landmark: '' }); setShowDistance(false); setEndPoint({ latitude: 0, longitude: 0 }); }} size="small" > ), style: { borderRadius: '10px', background: '#fff' } }} value={dropCust?.address || ''} onChange={(e) => { setDropCust({ ...dropCust, address: e.target.value }); if (e.target.value == '') { setAddId2(0); setShowDistance(false); setEndPoint({ latitude: 0, longitude: 0 }); } }} /> )} {/* Address details */} Address Details ), style: { borderRadius: '10px' } }} value={dropCust?.doorno || ''} onChange={(e) => { setDropCust({ ...dropCust, doorno: e.target.value }); }} /> ), style: { borderRadius: '10px' } }} value={dropCust?.suburb || ''} onChange={(e) => { setDropCust({ ...dropCust, suburb: e.target.value }); }} /> ), style: { borderRadius: '10px' } }} value={dropCust?.postcode || ''} onChange={(e) => { setDropCust({ ...dropCust, postcode: e.target.value }); }} /> ), style: { borderRadius: '10px' } }} value={dropCust?.landmark || ''} onChange={(e) => { setDropCust({ ...dropCust, landmark: e.target.value }); }} /> {/* Save for later */} {showCheck2 == 1 && ( { setIsNumChange2(e.target.checked ? 1 : 0); }} /> } label="Save contact for later" /> )} {/* Step navigation */} Review the route below once Drop is filled. {/* Card 3: Cargo & Dispatch Logistics */} Cargo & Dispatch Logistics {/* Section Header: Cargo Details */} Cargo Details {/* Row 1: Category, Cash Collect, Quantity */} option?.subcategoryname || ''} fullWidth sx={{ '& .MuiOutlinedInput-root': { borderRadius: '12px', height: '38px', paddingTop: '0px !important', paddingBottom: '0px !important' } }} renderInput={(params) => ( {params.InputProps.startAdornment} ) }} /> )} onChange={(event, value, reason) => { if (value) { console.log(value); setSubCatName(value.subcategoryname || ''); setSubCatId(value.subcategoryid || 0); } else if (reason) { setSubCatName(null); setSubCatId(null); } }} /> { setCollectionamt(e.target.value); }} inputProps={{ min: 0 }} sx={{ '& .MuiOutlinedInput-root': { borderRadius: '12px', height: '38px' } }} InputProps={{ startAdornment: ( ) }} /> { setQuantity(e.target.value); }} inputProps={{ min: 1 }} sx={{ '& .MuiOutlinedInput-root': { borderRadius: '12px', height: '38px' } }} InputProps={{ startAdornment: ( ) }} /> {/* Section Header: Handover & Schedule */} Schedule Details {/* Nested Grid Container with tight spacing to eliminate excessive gaps */} {/* Row 3: Pickup Date & Time Slot (Side-by-Side) */} { let dateres11 = dayjs().diff(dayjs(`${dayjs(e).format('YYYY-MM-DD')}`), 'd'); setSelectedtime(''); if (dateres11 <= 0) { setStartdate(e); let arr = []; timeslotarr.map((val) => { if ( dayjs().diff(dayjs(`${dayjs(e).format('MM-DD-YYYY')} ${dayjs(val).format('HH:mm:ss')}`), 'm') <= 0 ) { arr.push(val); } }); } else { setAlertmessage('choose Upcoming Date'); opentoast('choose Upcoming Date', 'warning'); setStartdate(NaN); } }} value={dayjs(startdate)} sx={{ width: '100%', '& .MuiOutlinedInput-root': { borderRadius: '12px', height: '38px' } }} slotProps={{ textField: { size: 'small', fullWidth: true, InputLabelProps: { shrink: true }, InputProps: { startAdornment: ( ) }, sx: { '& .MuiOutlinedInput-root': { borderRadius: '12px', height: '38px', paddingLeft: '10px' } } } }} disablePast /> { if (reason === 'clear' || !newValue) { setSelectedtime(null); setPickupSlot(null); } else { const formattedTime = dayjs(newValue.time, 'HH:mm').format('hh:mm A'); setSelectedtime(formattedTime); const finalDateTime = dayjs(`${startdate} ${formattedTime}`, 'MM-DD-YYYY hh:mm A').format( 'YYYY-MM-DD hh:mm A' ); setPickupSlot(finalDateTime); } }} getOptionLabel={(option) => option ? `${option.name} (${dayjs(option.time, 'HH:mm').format('hh:mm A')})` : ''} renderInput={(params) => ( {params.InputProps.startAdornment} ) }} /> )} /> {/* Right Column: Live Map & Cost Summary Panel (4.5 columns on lg+, sticky) */} {/* Map Card */} Live Route Preview
{/* Delivery Preferences — Dispatch Notes & SMS Updates */} Delivery Preferences Customer notifications & dispatch instructions setOtherinstructions(e.target.value)} sx={{ '& .MuiOutlinedInput-root': { borderRadius: '10px', padding: '0 10px', alignItems: 'center', fontSize: '12px', background: '#ffffff', height: '32px' }, '& .MuiOutlinedInput-input': { padding: '0 !important', fontSize: '12px !important', lineHeight: '32px' } }} /> setIsSms(isSms === 1 ? 0 : 1)} role="button" tabIndex={0} > SMS Updates Auto-notify customer on dispatch & delivery { e.stopPropagation(); setIsSms(e.target.checked ? 1 : 0); }} /> {/* Pricing breakdown card */} Pricing & Dispatch Live cost estimate
Delivery Distance
{showDistance ? `${distance} km` : '—'}
Base Fare · {minKm} km
{basePrice ? `₹${basePrice.toFixed(2)}` : '₹0.00'}
Rate per km
{pricePerKm ? `₹${pricePerKm.toFixed(2)}` : '₹0.00'} /km
{/* Total Cost Display */} {showDistance && (
Total Delivery Charge
₹{totalCharge.toFixed(2)}
)} {/* Submit button */}
{/* Saved address Dialog (Modal) */} { setIsCustomerOpen(false); setSearchCustList(''); }} fullWidth fullScreen={isMobile} sx={{ '& .MuiDialog-paper': { borderRadius: { xs: 0, sm: '16px' }, overflow: 'hidden' } }} > {`Select Saved Address (${pickordrop === 1 ? 'Pickup' : 'Drop'})`} setSearchCustList(e.target.value)} sx={{ bgcolor: 'white', borderRadius: '10px', '& .MuiOutlinedInput-input': { p: '10px 14px' } }} startAdornment={ } endAdornment={ { setSearchCustList(''); }} > } autoComplete="off" /> {customerlist?.length == 0 ? ( ) : ( {customerlist && customerlist.map((address, index) => ( ))} )} {/* Location error Dialog */} { setOpen(false); }} fullWidth sx={{ '& .MuiDialog-paper': { borderRadius: { xs: 3, sm: '16px' }, p: 1.5, m: { xs: 1.5, sm: 4 }, width: { xs: 'calc(100% - 24px)', sm: 'auto' }, maxWidth: '400px' } }} > Dispatch Blocked Our delivery partners cannot service this coordinate combination. The route distance exceeds the active operating radius for this app location. { setOpen(false); }} > Acknowledge & Close ); }; export default Createorder1;