2901 lines
122 KiB
JavaScript
2901 lines
122 KiB
JavaScript
import * as React from 'react';
|
|
import { useEffect, useState, useRef, Fragment } from 'react';
|
|
import {
|
|
FormControl,
|
|
InputAdornment,
|
|
Grid,
|
|
Typography,
|
|
Stack,
|
|
Box,
|
|
Button,
|
|
TextField,
|
|
Autocomplete,
|
|
CardActions,
|
|
Chip,
|
|
Avatar,
|
|
Divider,
|
|
DialogTitle,
|
|
DialogContent,
|
|
Checkbox,
|
|
DialogActions,
|
|
CircularProgress,
|
|
ButtonGroup,
|
|
FormLabel,
|
|
IconButton,
|
|
Drawer,
|
|
InputLabel,
|
|
Select,
|
|
MenuItem,
|
|
Switch,
|
|
CardHeader,
|
|
Card,
|
|
OutlinedInput,
|
|
FormGroup,
|
|
FormControlLabel
|
|
} from '@mui/material';
|
|
import CloseIcon from '@mui/icons-material/Close';
|
|
import { Empty } from 'antd';
|
|
import { FaPhoneAlt } 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 { MdLocationCity } from 'react-icons/md';
|
|
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 LocationOnIcon from '@mui/icons-material/LocationOn';
|
|
import parse from 'autosuggest-highlight/parse';
|
|
import { debounce } from '@mui/material/utils';
|
|
import CardContent from 'themes/overrides/CardContent';
|
|
import { PhoneAndroid } from '@mui/icons-material';
|
|
import { SearchOutlined, CloseOutlined } from '@ant-design/icons';
|
|
import PhoneInput from 'react-phone-number-input/input';
|
|
import MyLocationIcon from '@mui/icons-material/MyLocation';
|
|
import HighlightOffIcon from '@mui/icons-material/HighlightOff';
|
|
import { Paper } from '@mui/material';
|
|
import {
|
|
MdAddShoppingCart,
|
|
MdMyLocation,
|
|
MdLocationOn,
|
|
MdSchedule,
|
|
MdLocalShipping,
|
|
MdAttachMoney,
|
|
MdNotes,
|
|
MdCheckCircle,
|
|
MdReceiptLong,
|
|
MdInventory2,
|
|
MdStraighten,
|
|
MdPersonPin,
|
|
MdPerson,
|
|
MdHistoryToggleOff
|
|
} from 'react-icons/md';
|
|
|
|
// ============================================================================
|
|
// Design tokens — shared with the rest of the redesigned operator pages.
|
|
// ============================================================================
|
|
const DT = {
|
|
radiusPill: 999,
|
|
radiusCard: 16,
|
|
shadowSoft: '0 14px 40px rgba(15, 23, 42, 0.10)',
|
|
shadowMd: '0 8px 24px rgba(15, 23, 42, 0.08)',
|
|
shadowPop: '0 18px 50px rgba(15, 23, 42, 0.18)',
|
|
textPrimary: '#0f172a',
|
|
textSecondary: '#64748b',
|
|
textMuted: '#94a3b8',
|
|
borderSubtle: '#e2e8f0',
|
|
divider: '#f1f5f9',
|
|
surface: '#ffffff',
|
|
surfaceAlt: '#f8fafc'
|
|
};
|
|
const dtA = (c, suffix) => `${c}${suffix}`;
|
|
const tint = (c) => dtA(c, '08');
|
|
const soft = (c) => dtA(c, '18');
|
|
const ring = (c) => dtA(c, '26');
|
|
const edge = (c) => dtA(c, '55');
|
|
|
|
const BRAND = '#662582';
|
|
const BRAND_LIGHT = '#9255AB';
|
|
|
|
// Soft card section header — coloured banner above each form section.
|
|
const SectionHeader = ({ color, icon, title, subtitle, action }) => (
|
|
<Stack
|
|
direction="row"
|
|
alignItems="center"
|
|
justifyContent="space-between"
|
|
spacing={1}
|
|
sx={{
|
|
px: { xs: 1.5, md: 2 },
|
|
py: 1.25,
|
|
borderBottom: `1px solid ${DT.divider}`,
|
|
background: `linear-gradient(90deg, ${tint(color)} 0%, transparent 100%)`
|
|
}}
|
|
>
|
|
<Stack direction="row" alignItems="center" spacing={1.25}>
|
|
<Avatar sx={{ width: 32, height: 32, bgcolor: color, color: '#fff', boxShadow: `0 6px 18px ${ring(color)}` }}>
|
|
{icon}
|
|
</Avatar>
|
|
<Stack>
|
|
<Typography sx={{ fontWeight: 800, color: DT.textPrimary, fontSize: 14, lineHeight: 1.1 }}>{title}</Typography>
|
|
{subtitle && (
|
|
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 600 }}>
|
|
{subtitle}
|
|
</Typography>
|
|
)}
|
|
</Stack>
|
|
</Stack>
|
|
{action}
|
|
</Stack>
|
|
);
|
|
|
|
// Section wrapper Paper used as the outer card for each form block.
|
|
const SectionCard = ({ children, sx = {} }) => (
|
|
<Paper
|
|
elevation={0}
|
|
sx={{
|
|
borderRadius: DT.radiusCard / 8,
|
|
border: '1px solid',
|
|
borderColor: DT.borderSubtle,
|
|
background: '#fff',
|
|
overflow: 'hidden',
|
|
boxShadow: DT.shadowSoft,
|
|
height: '100%',
|
|
...sx
|
|
}}
|
|
>
|
|
{children}
|
|
</Paper>
|
|
);
|
|
|
|
// Popup paper for Autocomplete dropdowns — matches the rest of the design.
|
|
const SoftPaper = (props) => (
|
|
<Paper
|
|
{...props}
|
|
sx={{
|
|
mt: 0.75,
|
|
borderRadius: 2,
|
|
boxShadow: DT.shadowPop,
|
|
border: '1px solid',
|
|
borderColor: 'divider',
|
|
overflow: 'hidden'
|
|
}}
|
|
/>
|
|
);
|
|
|
|
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 [value, setValue] = React.useState(null);
|
|
const [value1, setValue1] = React.useState(null);
|
|
const [inputValue, setInputValue] = React.useState('');
|
|
const [inputValue1, setInputValue1] = React.useState('');
|
|
const [inputValue2, setInputValue2] = React.useState('');
|
|
const [inputValue3, setInputValue3] = React.useState('');
|
|
const [options, setOptions] = React.useState([]);
|
|
const [options1, setOptions1] = React.useState([]);
|
|
const loaded = React.useRef(false);
|
|
const loaded1 = React.useRef(false);
|
|
const [mobilenumber, setMobilenumber] = useState('');
|
|
const [emailaddress, setEmailaddress] = useState('');
|
|
const [city, setCity] = useState('');
|
|
const [city1, setCity1] = useState('');
|
|
const [zipcode, setZipcode] = useState('');
|
|
const [zipcode1, setZipcode1] = useState('');
|
|
const [state, setState] = useState('');
|
|
const [state1, setState1] = useState('');
|
|
const [suburb, setSuburb] = useState('');
|
|
const [suburb1, setSuburb1] = useState('');
|
|
const [pickContactName, setPickContactName] = useState('');
|
|
const [dropContactName, setDropContactName] = useState('');
|
|
const [pickdoorno, setPickDoorno] = useState('');
|
|
const [dropDoorno, setDropDoorno] = useState('');
|
|
const [pickLandmark, setPickLandmark] = useState('');
|
|
const [dropLandmark, setDropLandmark] = useState('');
|
|
const [address, setAddress] = useState('');
|
|
const [address1, setAddress1] = useState('');
|
|
const [latlong, setLatlong] = useState({});
|
|
const [latlong1, setLatlong1] = useState({});
|
|
const autocompleteService = useRef(null);
|
|
const [tenanatLocoId, setTenanatLocoId] = useState(localStorage.getItem('locationid'));
|
|
const [isLocation, setIsLocation] = useState(false);
|
|
const textFieldRef1 = useRef(null);
|
|
const textFieldRef2 = useRef(null);
|
|
const [collectionamt, setCollectionamt] = useState(0);
|
|
const [quantity, setQuantity] = useState(1);
|
|
|
|
const handleOkClick1 = () => {
|
|
// Set focus back to the text field after clicking the "OK" chip
|
|
if (textFieldRef1.current) {
|
|
textFieldRef1.current.focus();
|
|
}
|
|
};
|
|
|
|
const handleOkClick2 = () => {
|
|
// Set focus back to the text field after clicking the "OK" chip
|
|
if (textFieldRef2.current) {
|
|
textFieldRef2.current.focus();
|
|
}
|
|
};
|
|
|
|
const top100Films = [
|
|
{ label: 'The Shawshank Redemption', year: 1994 },
|
|
{ label: 'The Godfather', year: 1972 },
|
|
{ label: 'The Godfather: Part II', year: 1974 },
|
|
{ label: 'The Dark Knight', year: 2008 },
|
|
{ label: '12 Angry Men', year: 1957 }
|
|
];
|
|
|
|
// // // ====================================================== || address (pick)|| ======================================================
|
|
// useEffect(() => {
|
|
// if (address) {
|
|
// try {
|
|
// Geocode.fromAddress(address).then(
|
|
// (response) => {
|
|
// if (response.status == 'OK') {
|
|
// const { lat, lng } = response.results[0].geometry.location;
|
|
// console.log({ lat, lng });
|
|
// setLatlong({
|
|
// lat,
|
|
// lng
|
|
// });
|
|
// console.log(response);
|
|
// if (response.results[0].address_components) {
|
|
// let place = response.results[0];
|
|
// let cityA, zipcodeA, stateA, suburbA;
|
|
// for (let i = 0; i < place.address_components.length; i++) {
|
|
// for (let j = 0; j < place.address_components[i].types.length; j++) {
|
|
// switch (place.address_components[i].types[j]) {
|
|
// case 'locality':
|
|
// cityA = place.address_components[i].long_name;
|
|
// break;
|
|
// case 'administrative_area_level_1':
|
|
// stateA = place.address_components[i].long_name;
|
|
// break;
|
|
// case 'postal_code':
|
|
// zipcodeA = place.address_components[i].long_name;
|
|
// break;
|
|
// case 'sublocality':
|
|
// suburbA = place.address_components[i].long_name;
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
// setCity(cityA || '');
|
|
// setState(stateA || '');
|
|
// setZipcode(zipcodeA || '');
|
|
// setSuburb(suburbA || '');
|
|
// console.log({ lat, lng, cityA, stateA, zipcodeA, suburbA });
|
|
// setPickCust({
|
|
// ...pickCust
|
|
// // city: cityA,
|
|
// // state: stateA,
|
|
// // postcode: zipcodeA,
|
|
// // suburb: suburbA
|
|
// // latitude: lat,
|
|
// // longitude: lng
|
|
// });
|
|
// // setStartPoint({ latitude: lat, longitude: lng });
|
|
// }
|
|
// }
|
|
// },
|
|
// (error) => {
|
|
// console.log(error);
|
|
// }
|
|
// );
|
|
// } catch (err) {
|
|
// console.log(err);
|
|
// }
|
|
// }
|
|
// }, [address]);
|
|
// // // ====================================================== || address 1 (drop)|| ======================================================
|
|
// useEffect(() => {
|
|
// if (address) {
|
|
// try {
|
|
// Geocode.fromAddress(address1).then(
|
|
// (response) => {
|
|
// if (response.status == 'OK') {
|
|
// const { lat, lng } = response.results[0].geometry.location;
|
|
|
|
// setLatlong1({
|
|
// lat,
|
|
// lng
|
|
// });
|
|
// console.log(response);
|
|
// if (response.results[0].address_components) {
|
|
// let place = response.results[0];
|
|
// let cityB, zipcodeB, stateB, suburbB;
|
|
// for (let i = 0; i < place.address_components.length; i++) {
|
|
// for (let j = 0; j < place.address_components[i].types.length; j++) {
|
|
// switch (place.address_components[i].types[j]) {
|
|
// case 'locality':
|
|
// cityB = place.address_components[i].long_name;
|
|
// break;
|
|
// case 'administrative_area_level_1':
|
|
// stateB = place.address_components[i].long_name;
|
|
// break;
|
|
// case 'postal_code':
|
|
// zipcodeB = place.address_components[i].long_name;
|
|
// break;
|
|
// case 'sublocality':
|
|
// suburbB = place.address_components[i].long_name;
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
// setCity(cityB || '');
|
|
// setState(stateB || '');
|
|
// setZipcode(zipcodeB || '');
|
|
// setSuburb(suburbB || '');
|
|
// console.log({ lat, lng, cityB, stateB, zipcodeB, suburbB });
|
|
// setDropCust({
|
|
// ...dropCust
|
|
// // city: cityB,
|
|
// // state: stateB,
|
|
// // postcode: zipcodeB,
|
|
// // suburb: suburbB
|
|
// // latitude: lat,
|
|
// // longitude: lng
|
|
// });
|
|
// // setEndPoint({ latitude: lat, longitude: lng });
|
|
// }
|
|
// }
|
|
// },
|
|
// (error) => {
|
|
// console.log(error);
|
|
// }
|
|
// );
|
|
// } catch (err) {
|
|
// console.log(err);
|
|
// }
|
|
// }
|
|
// }, [address1]);
|
|
|
|
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;
|
|
}
|
|
|
|
// const fetch = React.useMemo(
|
|
// () =>
|
|
// debounce((request, callback) => {
|
|
// autocompleteService.current.getPlacePredictions(request, callback);
|
|
// }, 400),
|
|
// []
|
|
// );
|
|
// const fetch1 = React.useMemo(
|
|
// () =>
|
|
// debounce((request, callback) => {
|
|
// autocompleteService.current.getPlacePredictions(request, callback);
|
|
// }, 400),
|
|
// []
|
|
// );
|
|
|
|
// ====================================================== || options (pick)|| ======================================================
|
|
|
|
// React.useEffect(() => {
|
|
// let active = true;
|
|
// if (!autocompleteService.current && window.google) {
|
|
// autocompleteService.current = new window.google.maps.places.AutocompleteService();
|
|
// }
|
|
// if (!autocompleteService.current) {
|
|
// return undefined;
|
|
// }
|
|
// if (inputValue === '') {
|
|
// setOptions(value ? [value] : []);
|
|
// return undefined;
|
|
// }
|
|
// fetch({ input: inputValue }, (results) => {
|
|
// if (active) {
|
|
// let newOptions = [];
|
|
|
|
// if (value) {
|
|
// newOptions = [value];
|
|
// }
|
|
|
|
// if (results) {
|
|
// newOptions = [...newOptions, ...results];
|
|
// }
|
|
|
|
// setOptions(newOptions);
|
|
// }
|
|
// });
|
|
|
|
// return () => {
|
|
// active = false;
|
|
// };
|
|
// }, [value, inputValue, fetch]);
|
|
|
|
// // ====================================================== || options1 (drop)|| ======================================================
|
|
// React.useEffect(() => {
|
|
// let active = true;
|
|
// if (!autocompleteService.current && window.google) {
|
|
// autocompleteService.current = new window.google.maps.places.AutocompleteService();
|
|
// }
|
|
// if (!autocompleteService.current) {
|
|
// return undefined;
|
|
// }
|
|
// if (inputValue1 === '') {
|
|
// setOptions1(value1 ? [value1] : []);
|
|
// return undefined;
|
|
// }
|
|
// fetch1({ input: inputValue1 }, (results) => {
|
|
// if (active) {
|
|
// let newOptions = [];
|
|
|
|
// if (value1) {
|
|
// newOptions = [value1];
|
|
// }
|
|
|
|
// if (results) {
|
|
// newOptions = [...newOptions, ...results];
|
|
// }
|
|
|
|
// setOptions1(newOptions);
|
|
// }
|
|
// });
|
|
|
|
// return () => {
|
|
// active = false;
|
|
// };
|
|
// }, [value1, inputValue1, fetch1]);
|
|
|
|
const appId = localStorage.getItem('applocationid');
|
|
const navigate = useNavigate();
|
|
const [open, setOpen] = useState({});
|
|
const [open1, setOpen1] = useState('');
|
|
const [open2, setOpen2] = useState(false);
|
|
const [open3, setOpen3] = useState(false);
|
|
const [open4, setOpen4] = useState(false);
|
|
const [shift, setShift] = useState(1);
|
|
const [clientlist, setClientlist] = useState([]);
|
|
const [clientdetail, setClientdetail] = useState([]);
|
|
const [eventname, setEventname] = useState('');
|
|
const [startdate, setStartdate] = useState(dayjs().format('MM-DD-YYYY'));
|
|
const [enddate, setEnddate] = useState(dayjs().add(1, 'day').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 [currentsno, setCurrentsno] = useState('');
|
|
const [roleoptions, setRoleoptions] = useState([]);
|
|
const theme = useTheme();
|
|
const [otherinstructions, setOtherinstructions] = useState('');
|
|
const [attireslist, setAttireslist] = useState([]);
|
|
const [serviceaddonslist, setServiceaddonslist] = useState([]);
|
|
const [orderaddonobj, setOrderaddonobj] = useState([]);
|
|
const [stafflist, setStafflist] = useState([]);
|
|
const [loading2, setLoading2] = useState(false);
|
|
const [loading, setLoading] = useState(false);
|
|
const [btnLoading, setBtnLoading] = useState(false);
|
|
const [shiftarr, setShiftarr] = useState([]);
|
|
const [shiftarr1, setShiftarr1] = useState([]);
|
|
const [orderarr, setOrderarr] = useState([]);
|
|
const [alertmessage, setAlertmessage] = useState('');
|
|
const [tabstatus, setTabstatus] = useState('');
|
|
const [tenantinfo, setTenantinfo] = useState({});
|
|
const [searchword, setSearchword] = useState('');
|
|
const [clientdetailarr, setClientdetailarr] = useState([]);
|
|
const [clientdetailbusinessarr, setClientdetailbusinessarr] = useState([]);
|
|
const [admintoken, setAdmintoken] = useState();
|
|
const [tenantlocationlist, setTenantlocationlist] = useState([]);
|
|
const [tenant, setTenant] = useState({});
|
|
const [clientinfo, setClientinfo] = useState({});
|
|
const [selectedtime, setSelectedtime] = useState('');
|
|
const [tenantlist, setTenantlist] = useState([]);
|
|
const [tenantid, setTenantid] = useState();
|
|
const [tenantlocation, setTenantlocation] = useState('');
|
|
const [pickupswitch, setPickupswitch] = useState(true);
|
|
const [deliverytype, setDeliverytype] = useState('B');
|
|
const [dropswitch, setDropswitch] = useState(false);
|
|
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();
|
|
const [weight, setWeight] = useState('');
|
|
const tid = localStorage.getItem('tenantid');
|
|
const [selectedCatChip, setSelectedCatChip] = useState(null);
|
|
const [isCustomerOpen, setIsCustomerOpen] = useState(false);
|
|
const [searchCustList, setSearchCustList] = useState('');
|
|
const [customerlist, setCustomerlist] = useState([]);
|
|
const [pickCust, setPickCust] = useState({});
|
|
const [dropCust, setDropCust] = useState({});
|
|
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 [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);
|
|
|
|
useEffect(() => {
|
|
console.log(isSms);
|
|
}, [isSms]);
|
|
|
|
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 () => {
|
|
try {
|
|
const pricingResponse = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantpricing/?tenantid=${tid}`);
|
|
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(() => {
|
|
fetchTenantPricing();
|
|
}, []);
|
|
|
|
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]);
|
|
|
|
const getDistance = () => {
|
|
const dist = geolib.getPreciseDistance(startPoint, endPoint, 1);
|
|
console.log(`Distance: ${dist} meters`);
|
|
const distanceInKm = (dist / 1000).toFixed(2);
|
|
const roundedDistance = Math.round(distanceInKm);
|
|
console.log('roundedDistance', roundedDistance);
|
|
setDistance(roundedDistance.toFixed(2));
|
|
if (roundedDistance < minKm) {
|
|
setTotalCharge(basePrice);
|
|
} else {
|
|
const total = (roundedDistance - minKm) * pricePerKm + basePrice;
|
|
setTotalCharge(total);
|
|
}
|
|
setShowDistance(true);
|
|
if (roundedDistance > appLocaRadius) {
|
|
setShowDistance(true);
|
|
setOpen4(true);
|
|
}
|
|
};
|
|
|
|
const calculateDistance = async (pickup, drop) => {
|
|
const service = new google.maps.DistanceMatrixService();
|
|
|
|
const getDistanceMatrix = (origins, destinations, travelMode, unitSystem) => {
|
|
return new Promise((resolve, reject) => {
|
|
service.getDistanceMatrix(
|
|
{
|
|
origins: [new google.maps.LatLng(origins.latitude, origins.longitude)],
|
|
destinations: [new google.maps.LatLng(destinations.latitude, destinations.longitude)],
|
|
travelMode: travelMode,
|
|
unitSystem: unitSystem
|
|
},
|
|
(response, status) => {
|
|
if (status === 'OK') {
|
|
resolve(response);
|
|
} else {
|
|
reject(new Error(`Error calculating distance: ${status}`));
|
|
}
|
|
}
|
|
);
|
|
});
|
|
};
|
|
|
|
try {
|
|
// Use await to wait for the promise to resolve
|
|
const response = await getDistanceMatrix(pickup, drop, 'DRIVING', google.maps.UnitSystem.METRIC);
|
|
|
|
// Handle the response
|
|
const results = response.rows[0].elements;
|
|
for (let i = 0; i < results.length; i++) {
|
|
const element = results[i];
|
|
const distance = element.distance.value;
|
|
console.log('distance in m ', distance);
|
|
const distanceInKm = (distance / 1000).toFixed(2);
|
|
console.log('distance in km ', distanceInKm);
|
|
const roundedDistance = Math.round(distanceInKm);
|
|
console.log('roundedDistance', roundedDistance);
|
|
setDistance(roundedDistance);
|
|
if (roundedDistance < minKm) {
|
|
setTotalCharge(basePrice);
|
|
} else {
|
|
console.log('minKm', minKm);
|
|
console.log('pricePerKm', pricePerKm);
|
|
console.log('basePrice', basePrice);
|
|
const total = (roundedDistance - minKm) * pricePerKm + basePrice;
|
|
console.log('total', total);
|
|
setTotalCharge(total);
|
|
}
|
|
setShowDistance(true);
|
|
if (roundedDistance > appLocaRadius) {
|
|
setShowDistance(true);
|
|
setOpen4(true);
|
|
}
|
|
|
|
// Extract the numerical value of the duration
|
|
const durationMatch = element.duration.text.match(/([\d.]+)/);
|
|
const duration = durationMatch ? parseInt(durationMatch[0]) : null;
|
|
|
|
// Display only the numerical values
|
|
console.log(`Distance: ${roundedDistance}, Duration: ${duration}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error calculating distance:', error);
|
|
}
|
|
};
|
|
|
|
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);
|
|
}
|
|
});
|
|
|
|
if (arr[0]) {
|
|
setOrderarr([
|
|
{
|
|
sno: 1,
|
|
address: '',
|
|
customerid: '',
|
|
deliverytime: dayjs(arr[0]) || '',
|
|
deliverylocationid: '',
|
|
clientname: '',
|
|
contactno: '',
|
|
latitude: '',
|
|
longitude: ''
|
|
}
|
|
]);
|
|
}
|
|
}
|
|
}, [timeslotarr]);
|
|
|
|
useEffect(() => {
|
|
if (searchword) {
|
|
let arr = clientdetail.filter((val) => {
|
|
return (
|
|
val.address.toLowerCase().includes(searchword.toLowerCase()) ||
|
|
val.firstname.toLowerCase().includes(searchword.toLowerCase()) ||
|
|
val.contactno.toLowerCase().includes(searchword.toLowerCase())
|
|
);
|
|
});
|
|
console.log(arr);
|
|
setClientdetailarr([...arr]);
|
|
} else {
|
|
setClientdetailarr([...clientdetail]);
|
|
}
|
|
}, [searchword]);
|
|
|
|
// const { ref: materialRef } = usePlacesWidget({
|
|
// apiKey: process.env.REACT_APP_GOOGLE_MAPS_API_KEY,
|
|
// onPlaceSelected: (place) => {
|
|
// console.log(place);
|
|
|
|
// // setAddress(place.formatted_address)
|
|
// let city1, zipcode1, state1, suburb1;
|
|
// for (let i = 0; i < place.address_components.length; i++) {
|
|
// for (let j = 0; j < place.address_components[i].types.length; j++) {
|
|
// switch (place.address_components[i].types[j]) {
|
|
// case 'locality':
|
|
// city1 = place.address_components[i].long_name;
|
|
// break;
|
|
// case 'administrative_area_level_1':
|
|
// state1 = place.address_components[i].long_name;
|
|
// break;
|
|
// case 'postal_code':
|
|
// zipcode1 = place.address_components[i].long_name;
|
|
// break;
|
|
// case 'sublocality':
|
|
// suburb1 = place.address_components[i].long_name;
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
// // setCity(city1 || '')
|
|
// // setState(state1 || '');
|
|
// // setZipcode(zipcode1 || '');
|
|
// // setSuburb(suburb1 || '')
|
|
// },
|
|
|
|
// options: {
|
|
// types: ['address' || 'geocode']
|
|
// }
|
|
// });
|
|
|
|
// ==================================================== || fetchtenantinfo || ====================================================
|
|
const fetchtenantinfo = async () => {
|
|
setLoading(true);
|
|
console.log('tid', tid);
|
|
|
|
await axios
|
|
.get(`${process.env.REACT_APP_URL}/tenants/gettenantinfo/?tenantid=${tid}`)
|
|
.then((res) => {
|
|
console.log('fetchtenantinfo', res);
|
|
if (res.data.status) {
|
|
setTenant(res.data.details);
|
|
setTenantid(res.data.details.tenantid);
|
|
fetchAppAdminTokens();
|
|
setSubCatId(res.data.details.subcategoryid);
|
|
}
|
|
setLoading(false);
|
|
})
|
|
.catch((err) => {
|
|
console.log(err);
|
|
setLoading(false);
|
|
});
|
|
};
|
|
useEffect(() => {
|
|
fetchtenantinfo();
|
|
}, []);
|
|
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 && res.data.details) {
|
|
setSubCat(res.data.details);
|
|
} else {
|
|
setSubCat([]);
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
console.log(err);
|
|
setSubCat([]);
|
|
});
|
|
};
|
|
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);
|
|
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(() => {
|
|
fetchTiming();
|
|
}, []);
|
|
|
|
// =============================================== || 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);
|
|
console.log('fetchAppAdminTokens', res);
|
|
console.log('userfcmtokemArray', userfcmtokemArray);
|
|
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 : 2000
|
|
});
|
|
console.log(alertmessage);
|
|
};
|
|
|
|
function closeAddressModal() {
|
|
setOpen2(false);
|
|
}
|
|
function closetimemodal() {
|
|
setOpen3(false);
|
|
setCurrentsno('');
|
|
}
|
|
|
|
// =============================================== || createsubmitobj1 (create orders) || ===============================================
|
|
|
|
const createsubmitobj2 = async () => {
|
|
let arr = {};
|
|
arr = {
|
|
orders: {
|
|
applocationid: tenant.applolcationid,
|
|
cancellled: '',
|
|
categoryid: +tenant.categoryid,
|
|
configid: 7,
|
|
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: pickCust.customerid !== 0 || dropCust.customerid !== 0 ? 'B' : 'C',
|
|
delivered: '',
|
|
itemcount: 1,
|
|
kms: distance.toString() || 0,
|
|
locationid: +tenanatLocoId, //main or branch
|
|
moduleid: +tenant.moduleid,
|
|
orderamount: +totalCharge.toFixed(2) || 0,
|
|
ordercharges: 0.0,
|
|
orderdate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
orderheaderid: 0,
|
|
orderid: '', //
|
|
ordernotes: otherinstructions,
|
|
orderstatus: 'created',
|
|
ordervalue: +totalCharge.toFixed(2) || 0,
|
|
partnerid: tenant.partnerid,
|
|
paymentstatus: 1,
|
|
paymenttype: 42,
|
|
pending: '',
|
|
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(),
|
|
processing: '',
|
|
ready: '',
|
|
remarks: '',
|
|
smsdelivery: isSms,
|
|
subcategoryid: +subCatId,
|
|
taxamount: 0.0,
|
|
tenantid: tenant.tenantid,
|
|
tenantuserid: parseInt(localStorage.getItem('userid')),
|
|
collectionamt: +collectionamt || 0,
|
|
quantity: +quantity || 1
|
|
},
|
|
|
|
pickup: {
|
|
address: pickCust.address || '',
|
|
applocationid: tenant.applolcationid,
|
|
city: pickCust.city || '',
|
|
configid: 7,
|
|
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() || '',
|
|
locationid: pickCust.deliverylocationid || 0,
|
|
postcode: pickCust.postcode || '',
|
|
primaryaddress: 1,
|
|
profileimage: '',
|
|
state: pickCust.state || '',
|
|
suburb: pickCust.suburb || '',
|
|
tenantid: tenant.tenantid
|
|
},
|
|
|
|
drop: {
|
|
address: dropCust.address || '',
|
|
applocationid: tenant.applolcationid,
|
|
city: dropCust.city || '',
|
|
configid: 7,
|
|
contactno: dropCust.contactno || '',
|
|
customertoken: '',
|
|
customerid: isNumChange2 == 0 ? dropCust.customerid || 0 : 0,
|
|
devicetype: '',
|
|
deviceid: '',
|
|
dialcode: '+91',
|
|
doorno: dropCust.doorno || '',
|
|
email: dropCust.email || '',
|
|
firstname: dropCust.firstname || '',
|
|
landmark: dropCust.landmark || '',
|
|
latitude: dropCust.latitude.toString(),
|
|
longitude: dropCust.longitude.toString(),
|
|
locationid: dropCust.deliverylocationid || 0,
|
|
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);
|
|
// const createRes = await axios.post(`${process.env.REACT_APP_URL}/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('Something went wrong, Cannot create order', 'warning');
|
|
}
|
|
setLoading(false);
|
|
console.log(createRes);
|
|
} catch (error) {
|
|
console.log('createResErr', error);
|
|
}
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
console.log('shiftarr');
|
|
console.log(shiftarr);
|
|
}, [shiftarr]);
|
|
|
|
const clicked1 = (e) => {
|
|
setShift(e);
|
|
};
|
|
|
|
const dialogopen = (i, result) => {
|
|
console.log(i, result);
|
|
setOpen({ shiftsno: result.sno, sno: i.sno });
|
|
};
|
|
const dialogclose = () => {
|
|
setOpen('');
|
|
};
|
|
// ========================================================= || clientdetails || =========================================================
|
|
const clientdetails = async () => {
|
|
setLoading2(true);
|
|
try {
|
|
let url =
|
|
searchCustList == ''
|
|
? // ? `${process.env.REACT_APP_URL}/customers/getbytid/?tenantid=${tid}&pageno=1&pagesize=1`
|
|
`${process.env.REACT_APP_URL}/customers/gettenantcustomers/?tenantid=${tid}&pageno=1&pagesize=20`
|
|
: `${process.env.REACT_APP_URL}/customers/search/?tenantid=${tid}&keyword=${searchCustList}`;
|
|
|
|
await axios
|
|
.get(url)
|
|
.then((res) => {
|
|
console.log('clientdetails', res.data.details);
|
|
if (res.data.status && res.data.details) {
|
|
setClientdetail(res.data.details || []);
|
|
setCustomerlist(res.data.details || []);
|
|
let arr = [];
|
|
res.data.details.map((val) => {
|
|
arr.push({
|
|
label: `${val.firstname} | ${val.contactno}`,
|
|
...val
|
|
});
|
|
});
|
|
setClientdetailarr(arr);
|
|
} else {
|
|
setClientdetail([]);
|
|
setCustomerlist([]);
|
|
setClientdetailarr([]);
|
|
}
|
|
setLoading2(false);
|
|
})
|
|
.catch((err) => {
|
|
console.log(err);
|
|
setLoading2(false);
|
|
opentoast('server error', 'warning');
|
|
});
|
|
} catch (err) {
|
|
console.log(err);
|
|
setLoading2(false);
|
|
}
|
|
};
|
|
useEffect(() => {
|
|
console.log('clientdetails, by search');
|
|
clientdetails();
|
|
// clientdetailsbusiness();
|
|
}, [searchCustList.length > 3, searchCustList == '']);
|
|
// ========================================================= || clientdetailsbusiness || =========================================================
|
|
const clientdetailsbusiness = async () => {
|
|
setLoading2(true);
|
|
try {
|
|
await axios
|
|
.get(`${process.env.REACT_APP_URL}/customers/getbytid/?tenantid=${tid}&locationid=1`)
|
|
.then((res) => {
|
|
console.log('clientdetailsbusiness', res.data.details);
|
|
if (res.data.status) {
|
|
setClientdetail(res.data.details);
|
|
// if (!searchword) {
|
|
// setClientdetailarr(res.data.details)
|
|
// }
|
|
let arr = [];
|
|
res.data.details.map((val) => {
|
|
arr.push({
|
|
label: `${val.firstname} | ${val.contactno}`,
|
|
...val
|
|
});
|
|
});
|
|
setClientdetailbusinessarr(arr);
|
|
}
|
|
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 (inputValue2) {
|
|
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()
|
|
});
|
|
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(' 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() });
|
|
setValue(place);
|
|
setAddress(`${place.name} ${place.formatted_address}`);
|
|
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);
|
|
});
|
|
}
|
|
}, [inputValue2]);
|
|
// ============================================= || Google Maps Autocomplete(Drop) || =============================================
|
|
|
|
useEffect(() => {
|
|
if (inputValue3) {
|
|
// 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();
|
|
setInputValue3(`${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() });
|
|
setValue1(place);
|
|
setAddress1(`${place.name} ${place.formatted_address}`);
|
|
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);
|
|
});
|
|
}
|
|
}, [inputValue3]);
|
|
|
|
// ============================================= || gettenantlocations (branches) || =============================================
|
|
const gettenantlocations = async () => {
|
|
try {
|
|
const res = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantlocations/?tenantid=${tid}`);
|
|
console.log('gettenantlocations', res.data.details);
|
|
if (res.data && res.data.details) {
|
|
setTenantlocations(res.data.details);
|
|
if (res.data.details.length == 1) {
|
|
setIsLocation(true);
|
|
setTenanatLocoId(res.data.details[0].locationid);
|
|
}
|
|
} else {
|
|
setTenantlocations([]);
|
|
}
|
|
} catch (err) {
|
|
console.log('gettenantlocations', err);
|
|
setTenantlocations([]);
|
|
}
|
|
};
|
|
useEffect(() => {
|
|
gettenantlocations();
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
{loading && <Loader />}
|
|
|
|
<Grid container rowSpacing={2} columnSpacing={2.75}>
|
|
<Grid item xs={12}>
|
|
<Paper
|
|
elevation={0}
|
|
sx={{
|
|
position: 'sticky',
|
|
top: '60px',
|
|
zIndex: 1000,
|
|
mb: 1.5,
|
|
p: { xs: 1.5, sm: 2, md: 2.5 },
|
|
borderRadius: DT.radiusCard / 8,
|
|
border: '1px solid',
|
|
borderColor: DT.borderSubtle,
|
|
background: `linear-gradient(135deg, ${tint(BRAND)} 0%, ${tint(BRAND_LIGHT)} 100%)`,
|
|
boxShadow: DT.shadowMd
|
|
}}
|
|
>
|
|
<Stack
|
|
direction={{ xs: 'column', sm: 'row' }}
|
|
alignItems={{ xs: 'flex-start', sm: 'center' }}
|
|
justifyContent="space-between"
|
|
spacing={{ xs: 1.5, sm: 2 }}
|
|
>
|
|
<Stack direction="row" alignItems="center" spacing={{ xs: 1.25, sm: 1.75 }}>
|
|
<Avatar
|
|
sx={{
|
|
width: { xs: 40, sm: 48 },
|
|
height: { xs: 40, sm: 48 },
|
|
bgcolor: BRAND,
|
|
color: '#fff',
|
|
boxShadow: `0 6px 18px ${ring(BRAND)}`
|
|
}}
|
|
>
|
|
<MdAddShoppingCart size={22} />
|
|
</Avatar>
|
|
<Stack>
|
|
<Typography
|
|
variant="h3"
|
|
sx={{
|
|
fontWeight: 800,
|
|
color: DT.textPrimary,
|
|
lineHeight: 1.1,
|
|
fontSize: { xs: '1.25rem', sm: '1.5rem', md: '1.75rem' }
|
|
}}
|
|
>
|
|
Create Order
|
|
</Typography>
|
|
<Stack direction="row" alignItems="center" spacing={0.75} sx={{ mt: 0.5 }}>
|
|
<Box
|
|
sx={{
|
|
width: 8,
|
|
height: 8,
|
|
borderRadius: '50%',
|
|
bgcolor: '#10b981',
|
|
boxShadow: '0 0 0 4px rgba(16,185,129,0.18)'
|
|
}}
|
|
/>
|
|
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 600 }}>
|
|
Fill pickup, drop, schedule & pricing details
|
|
</Typography>
|
|
</Stack>
|
|
</Stack>
|
|
</Stack>
|
|
|
|
{tenantLocations.length === 1 ? (
|
|
<Box
|
|
sx={{
|
|
display: 'inline-flex',
|
|
alignItems: 'center',
|
|
gap: 0.75,
|
|
px: 1.5,
|
|
py: 0.875,
|
|
borderRadius: 999,
|
|
bgcolor: tint(BRAND),
|
|
border: `1.5px solid ${edge(BRAND)}`,
|
|
color: BRAND,
|
|
fontWeight: 800,
|
|
fontSize: 13
|
|
}}
|
|
>
|
|
<MdMyLocation size={14} /> {tenantLocations[0].locationname}
|
|
</Box>
|
|
) : (
|
|
<Autocomplete
|
|
options={tenantLocations || []}
|
|
getOptionLabel={(option) =>
|
|
option && option.locationname ? `${option.locationname} (${option.suburb || ''})` : ''
|
|
}
|
|
isOptionEqualToValue={(option, value) => option?.locationid === value?.locationid}
|
|
PaperComponent={SoftPaper}
|
|
sx={{ width: { xs: '100%', sm: 300 } }}
|
|
size="small"
|
|
renderInput={(params) => (
|
|
<TextField
|
|
{...params}
|
|
placeholder="Select Business Location"
|
|
InputProps={{
|
|
...params.InputProps,
|
|
startAdornment: (
|
|
<Stack direction="row" alignItems="center" spacing={0.75} sx={{ pl: 0.5 }}>
|
|
<Avatar sx={{ width: 22, height: 22, bgcolor: BRAND, color: '#fff' }}>
|
|
<MdMyLocation size={13} />
|
|
</Avatar>
|
|
</Stack>
|
|
)
|
|
}}
|
|
sx={{
|
|
'& .MuiOutlinedInput-root': {
|
|
borderRadius: DT.radiusPill + 'px',
|
|
bgcolor: '#fff',
|
|
fontWeight: 600,
|
|
'& fieldset': { borderColor: edge(BRAND), borderWidth: 1.5 },
|
|
'&:hover fieldset': { borderColor: BRAND },
|
|
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` },
|
|
'&.Mui-focused fieldset': { borderColor: BRAND, borderWidth: 2 }
|
|
}
|
|
}}
|
|
/>
|
|
)}
|
|
onChange={(event, value, reason) => {
|
|
if (value) {
|
|
setTenanatLocoId(value.locationid);
|
|
setIsLocation(true);
|
|
}
|
|
if (reason === 'clear') {
|
|
setIsLocation(false);
|
|
}
|
|
}}
|
|
/>
|
|
)}
|
|
</Stack>
|
|
</Paper>
|
|
</Grid>
|
|
|
|
<Grid item xs={12}>
|
|
<Box sx={{ overflow: 'visible' }}>
|
|
<Grid container spacing={2}>
|
|
<Grid item xs={12}>
|
|
<Grid container spacing={2} sx={{ height: '100%' }}>
|
|
{/* ================================================= || Pickup || ================================================= */}
|
|
<Grid item xs={12} sm={6}>
|
|
<SectionCard>
|
|
<SectionHeader
|
|
color="#0ea5e9"
|
|
icon={<MdLocationOn size={16} />}
|
|
title="Pickup Details"
|
|
subtitle="Where the order is picked up"
|
|
action={
|
|
<Button
|
|
size="small"
|
|
variant="outlined"
|
|
startIcon={<MdPersonPin size={14} />}
|
|
onClick={() => {
|
|
if (!isLocation) {
|
|
opentoast('Select Business Location', 'warning');
|
|
} else {
|
|
setIsCustomerOpen(true);
|
|
setpickordrop(1);
|
|
setPickCust({});
|
|
setInputValue2('');
|
|
setSearchCustList('');
|
|
}
|
|
}}
|
|
sx={{
|
|
borderRadius: 999,
|
|
px: 1.5,
|
|
py: 0.375,
|
|
fontSize: 11.5,
|
|
fontWeight: 700,
|
|
textTransform: 'none',
|
|
borderColor: edge('#0ea5e9'),
|
|
color: '#0ea5e9',
|
|
'&:hover': {
|
|
borderColor: '#0ea5e9',
|
|
bgcolor: tint('#0ea5e9'),
|
|
boxShadow: `0 0 0 3px ${ring('#0ea5e9')}`
|
|
}
|
|
}}
|
|
>
|
|
Saved Locations
|
|
</Button>
|
|
}
|
|
/>
|
|
<Box sx={{ p: { xs: 2, md: 2.5 } }}>
|
|
<Grid container spacing={2}>
|
|
<Grid item xs={12}>
|
|
<Grid container spacing={4}>
|
|
{/* ====================================== ||Contact Name (pick) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
inputRef={textFieldRef1}
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<FaUser />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
variant="outlined"
|
|
label="Contact Name"
|
|
value={pickCust.firstname}
|
|
onChange={(e) => {
|
|
setPickCust({ ...pickCust, firstname: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== ||Contact Number(pick) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
error={numErr1}
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
type="number"
|
|
InputProps={{
|
|
inputProps: {
|
|
maxLength: 10
|
|
},
|
|
startAdornment: (
|
|
<IconButton>
|
|
<FaPhoneAlt color={numErr1 && 'red'} />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
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);
|
|
}
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== || Address (pick) || ====================================== */}
|
|
<Grid item xs={12}>
|
|
<Stack spacing={1.25} sx={{ mt: 0 }}>
|
|
{addId1 == 0 ? (
|
|
<div>
|
|
<TextField
|
|
variant="outlined"
|
|
label="Address"
|
|
disabled={!isLocation}
|
|
id="addressAuto1"
|
|
fullWidth
|
|
value={inputValue2}
|
|
onChange={(e) => setInputValue2(e.target.value)}
|
|
InputProps={{
|
|
endAdornment: (
|
|
<IconButton
|
|
onClick={() => {
|
|
setInputValue2('');
|
|
setPickCust({
|
|
...pickCust,
|
|
doorno: '',
|
|
suburb: '',
|
|
city: '',
|
|
postcode: '',
|
|
landmark: ''
|
|
});
|
|
setShowDistance(false);
|
|
setStartPoint({ latitude: 0, longitude: 0 });
|
|
}}
|
|
size="small"
|
|
>
|
|
<CloseIcon />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
/>
|
|
</div>
|
|
) : (
|
|
<TextField
|
|
InputProps={{
|
|
endAdornment: (
|
|
<IconButton
|
|
onClick={() => {
|
|
setAddId1(0);
|
|
setPickCust({
|
|
...pickCust,
|
|
// firstname: '',
|
|
// contactno: '',
|
|
doorno: '',
|
|
suburb: '',
|
|
city: '',
|
|
postcode: '',
|
|
landmark: ''
|
|
});
|
|
setShowDistance(false);
|
|
setStartPoint({ latitude: 0, longitude: 0 });
|
|
}}
|
|
>
|
|
<ClearIcon />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
variant="outlined"
|
|
placeholder="Select"
|
|
value={pickCust.address}
|
|
onChange={(e) => {
|
|
setPickCust({ ...pickCust, address: e.target.value });
|
|
if (e.target.value == '') {
|
|
setAddId1(0);
|
|
setShowDistance(false);
|
|
setStartPoint({ latitude: 0, longitude: 0 });
|
|
}
|
|
}}
|
|
/>
|
|
)}
|
|
</Stack>
|
|
</Grid>
|
|
|
|
{/* ====================================== ||Door No (pick) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<GiDoorHandle />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
variant="outlined"
|
|
label="Door No / Street"
|
|
value={pickCust.doorno}
|
|
onChange={(e) => {
|
|
setPickCust({ ...pickCust, doorno: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== || Suburb (pick) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<FaLocationDot />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
variant="outlined"
|
|
label="Location"
|
|
value={pickCust.suburb}
|
|
onChange={(e) => {
|
|
setPickCust({ ...pickCust, suburb: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== || City (pick) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<MdLocationCity />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
variant="outlined"
|
|
label="City"
|
|
value={pickCust.city}
|
|
onChange={(e) => {
|
|
setPickCust({ ...pickCust, city: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== || postcode (pick) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<TbMapPinCode />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
variant="outlined"
|
|
label="Postcode"
|
|
value={pickCust.postcode}
|
|
onChange={(e) => {
|
|
setPickCust({ ...pickCust, postcode: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== || Landmark (pick) || ====================================== */}
|
|
<Grid item xs={12}>
|
|
<TextField
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<FaLandmarkDome />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
variant="outlined"
|
|
label="Landmark"
|
|
value={pickCust.landmark}
|
|
onChange={(e) => {
|
|
setPickCust({ ...pickCust, landmark: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== ||Checkbox save for later (pick) || ====================================== */}
|
|
{showCheck1 == 1 && (
|
|
<Grid item xs={12} sx={{ display: 'flex', justifyContent: 'end' }}>
|
|
<FormGroup>
|
|
<FormControlLabel
|
|
control={
|
|
<Checkbox
|
|
checked={isNumChange1 === 1}
|
|
onChange={(e) => {
|
|
setIsNumChange1(e.target.checked ? 1 : 0);
|
|
}}
|
|
/>
|
|
}
|
|
label="Save For Later"
|
|
/>
|
|
</FormGroup>
|
|
</Grid>
|
|
)}
|
|
</Grid>
|
|
</Grid>
|
|
</Grid>
|
|
</Box>
|
|
</SectionCard>
|
|
</Grid>
|
|
{/* ================================================= || Drop || ================================================= */}
|
|
<Grid item xs={12} sm={6}>
|
|
<SectionCard>
|
|
<SectionHeader
|
|
color={BRAND}
|
|
icon={<MdLocalShipping size={16} />}
|
|
title="Drop Details"
|
|
subtitle="Where the order is delivered"
|
|
action={
|
|
<Button
|
|
size="small"
|
|
variant="outlined"
|
|
startIcon={<MdPersonPin size={14} />}
|
|
onClick={() => {
|
|
if (!isLocation) {
|
|
opentoast('Select Business Location', 'warning');
|
|
} else {
|
|
setIsCustomerOpen(true);
|
|
setpickordrop(2);
|
|
setInputValue3('');
|
|
setSearchCustList('');
|
|
}
|
|
}}
|
|
sx={{
|
|
borderRadius: 999,
|
|
px: 1.5,
|
|
py: 0.375,
|
|
fontSize: 11.5,
|
|
fontWeight: 700,
|
|
textTransform: 'none',
|
|
borderColor: edge(BRAND),
|
|
color: BRAND,
|
|
'&:hover': {
|
|
borderColor: BRAND,
|
|
bgcolor: tint(BRAND),
|
|
boxShadow: `0 0 0 3px ${ring(BRAND)}`
|
|
}
|
|
}}
|
|
>
|
|
Saved Locations
|
|
</Button>
|
|
}
|
|
/>
|
|
<Box sx={{ p: { xs: 2, md: 2.5 } }}>
|
|
<Grid container spacing={2} sx={{ height: '100%' }}>
|
|
<Grid item xs={12} sx={{ height: '100%' }}>
|
|
<Stack direction={'row'} justifyContent={'space-between'} sx={{ display: 'none' }}>
|
|
<Typography variant="h5" sx={{ mb: 2 }}>
|
|
Drop Details
|
|
</Typography>
|
|
<Stack direction={'row'} alignItems={'center'}>
|
|
{/* <Typography>Customer</Typography> */}
|
|
{/* <Switch
|
|
checked={dropswitch}
|
|
onChange={(e, val) => {
|
|
if (val) {
|
|
setDropswitch(true);
|
|
setClientinfo({});
|
|
} else {
|
|
setDropswitch(false);
|
|
setClientinfo({});
|
|
}
|
|
}}
|
|
size="small"
|
|
/>
|
|
<Typography>Business</Typography> */}
|
|
<Button
|
|
variant="outlined"
|
|
sx={{
|
|
'&:hover': {
|
|
bgcolor: theme.palette.primary.main,
|
|
color: 'white'
|
|
}
|
|
}}
|
|
onClick={() => {
|
|
if (!isLocation) {
|
|
opentoast('Select Business Location', 'warning');
|
|
} else {
|
|
setIsCustomerOpen(true);
|
|
setpickordrop(2);
|
|
|
|
setInputValue3('');
|
|
setSearchCustList('');
|
|
}
|
|
}}
|
|
>
|
|
Saved Locations
|
|
</Button>
|
|
</Stack>
|
|
</Stack>
|
|
{/* new2 */}
|
|
{/* <Autocomplete
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
disablePortal
|
|
id="combo-box-demo"
|
|
// options={customerlist}
|
|
options={clientdetailarr}
|
|
getOptionLabel={(option) => `${option.firstname} (${option.contactno})`}
|
|
sx={{ mt: 0, mb: 1 }}
|
|
renderInput={(params) => (
|
|
<TextField
|
|
{...params}
|
|
label="Search"
|
|
onChange={(e) => {
|
|
setSearchCustList(e.target.value);
|
|
}}
|
|
InputProps={{
|
|
...params.InputProps,
|
|
inputProps: {
|
|
...params.inputProps,
|
|
maxLength: 10
|
|
}
|
|
}}
|
|
/>
|
|
)}
|
|
onChange={(e, val, reason) => {
|
|
if (val) {
|
|
if (pickCust.customerid === val.customerid) {
|
|
opentoast('Select Another Customer', 'error');
|
|
setSearchCustList('');
|
|
} else {
|
|
console.log('DropClient', val);
|
|
setDropCust(val);
|
|
setEndPoint({ latitude: val.latitude, longitude: val.longitude });
|
|
setAddId2(1);
|
|
}
|
|
}
|
|
if (reason == 'clear') {
|
|
setSearchCustList('');
|
|
}
|
|
}}
|
|
noOptionsText={
|
|
/^[0-9]{10}$/.test(searchCustList) ? (
|
|
<Stack sx={{ width: '100%', display: 'flex', alignItems: 'end', justifyContent: 'end' }}>
|
|
<Chip
|
|
label={'OK'}
|
|
sx={{
|
|
width: 50,
|
|
cursor: 'pointer',
|
|
'&:hover': { background: theme.palette.primary.main, color: 'white' }
|
|
}}
|
|
onClick={() => {
|
|
setDropCust({ ...dropCust, contactno: searchCustList });
|
|
handleOkClick2();
|
|
setSearchCustList('');
|
|
}}
|
|
/>
|
|
</Stack>
|
|
) : null
|
|
}
|
|
/> */}
|
|
</Grid>
|
|
|
|
<Grid item xs={12}>
|
|
<Grid container spacing={4}>
|
|
{/* ====================================== ||Contact Name (drop) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
inputRef={textFieldRef2}
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
variant="outlined"
|
|
label="Contact Name"
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<FaUser />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
value={dropCust.firstname}
|
|
onChange={(e) => {
|
|
setDropCust({ ...dropCust, firstname: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== ||Contact Number (drop) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
disabled={!isLocation}
|
|
error={numErr2}
|
|
fullWidth
|
|
type="number"
|
|
variant="outlined"
|
|
label="Contact Number"
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<FaPhoneAlt color={numErr2 && 'red'} />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
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);
|
|
}
|
|
}}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12}>
|
|
<Stack spacing={1.25} sx={{ mt: 0 }}>
|
|
{addId2 == 0 ? (
|
|
<div>
|
|
<TextField
|
|
id="addressAuto2"
|
|
disabled={!isLocation}
|
|
label="Address"
|
|
fullWidth
|
|
value={inputValue3}
|
|
onChange={(e) => setInputValue3(e.target.value)}
|
|
InputProps={{
|
|
endAdornment: (
|
|
<IconButton
|
|
onClick={() => {
|
|
setInputValue3('');
|
|
setDropCust({
|
|
...dropCust,
|
|
doorno: '',
|
|
suburb: '',
|
|
city: '',
|
|
postcode: '',
|
|
landmark: ''
|
|
});
|
|
setShowDistance(false);
|
|
setEndPoint({ latitude: 0, longitude: 0 });
|
|
}}
|
|
size="small"
|
|
>
|
|
<CloseIcon />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
/>
|
|
</div>
|
|
) : (
|
|
<TextField
|
|
disabled={!isLocation}
|
|
InputProps={{
|
|
endAdornment: (
|
|
<IconButton
|
|
onClick={() => {
|
|
setAddId2(0);
|
|
setDropCust({
|
|
...dropCust,
|
|
firstname: '',
|
|
contactno: '',
|
|
doorno: '',
|
|
suburb: '',
|
|
city: '',
|
|
postcode: '',
|
|
landmark: ''
|
|
});
|
|
setShowDistance(false);
|
|
setEndPoint({ latitude: 0, longitude: 0 });
|
|
}}
|
|
>
|
|
<ClearIcon />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
variant="outlined"
|
|
placeholder="Select"
|
|
value={dropCust.address}
|
|
onChange={(e) => {
|
|
setPickCust({ ...dropCust, address: e.target.value });
|
|
if (e.target.value == '') {
|
|
setAddId2(0);
|
|
setShowDistance(false);
|
|
setEndPoint({ latitude: 0, longitude: 0 });
|
|
}
|
|
}}
|
|
/>
|
|
)}
|
|
</Stack>
|
|
</Grid>
|
|
|
|
{/* ====================================== ||Door No (drop) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
variant="outlined"
|
|
label="Door No / Street"
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<GiDoorHandle />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
value={dropCust.doorno}
|
|
onChange={(e) => {
|
|
setDropCust({ ...dropCust, doorno: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== ||Suburb (drop) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
variant="outlined"
|
|
label="Location"
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<FaLocationDot />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
value={dropCust.suburb}
|
|
onChange={(e) => {
|
|
setDropCust({ ...dropCust, suburb: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== ||City (drop) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
variant="outlined"
|
|
label="City"
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<MdLocationCity />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
value={dropCust.city}
|
|
onChange={(e) => {
|
|
setDropCust({ ...dropCust, city: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
|
|
{/* ====================================== ||Postcode (drop) || ====================================== */}
|
|
<Grid item xs={6}>
|
|
<TextField
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
variant="outlined"
|
|
label="Postcode"
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<TbMapPinCode />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
value={dropCust.postcode}
|
|
onChange={(e) => {
|
|
setDropCust({ ...dropCust, postcode: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== ||Landmark (drop) || ====================================== */}
|
|
<Grid item xs={12}>
|
|
<TextField
|
|
disabled={!isLocation}
|
|
fullWidth
|
|
variant="outlined"
|
|
label="Landmark"
|
|
InputProps={{
|
|
startAdornment: (
|
|
<IconButton>
|
|
<FaLandmarkDome />
|
|
</IconButton>
|
|
)
|
|
}}
|
|
value={dropCust.landmark}
|
|
onChange={(e) => {
|
|
setDropCust({ ...dropCust, landmark: e.target.value });
|
|
}}
|
|
/>
|
|
</Grid>
|
|
{/* ====================================== ||Checkbox save for later (drop) || ====================================== */}
|
|
{showCheck2 == 1 && (
|
|
<Grid item xs={12} sx={{ display: 'flex', justifyContent: 'end' }}>
|
|
<FormGroup>
|
|
<FormControlLabel
|
|
control={
|
|
<Checkbox
|
|
checked={isNumChange2 === 1}
|
|
onChange={(e) => {
|
|
setIsNumChange2(e.target.checked ? 1 : 0);
|
|
}}
|
|
/>
|
|
}
|
|
label="Save For Later"
|
|
/>
|
|
</FormGroup>
|
|
</Grid>
|
|
)}
|
|
</Grid>
|
|
</Grid>
|
|
{/* <Stack
|
|
sx={{ width: '100%', display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'end', mt: 2 }}
|
|
>
|
|
<Button
|
|
variant="outlined"
|
|
sx={{
|
|
width: 130,
|
|
'&:hover': {
|
|
bgcolor: theme.palette.primary.main,
|
|
color: 'white'
|
|
}
|
|
}}
|
|
>
|
|
Save for Later
|
|
</Button>
|
|
</Stack> */}
|
|
</Grid>
|
|
</Box>
|
|
</SectionCard>
|
|
</Grid>
|
|
{/* ================================================= || Time || ================================================= */}
|
|
<Grid item xs={12} sm={6}>
|
|
<SectionCard sx={{ mt: 2, minHeight: 390 }}>
|
|
<SectionHeader
|
|
color="#f59e0b"
|
|
icon={<MdSchedule size={16} />}
|
|
title="Schedule"
|
|
subtitle="Pickup date & time slot"
|
|
/>
|
|
<Box sx={{ p: { xs: 2, md: 2.5 } }}>
|
|
<Grid container>
|
|
<Grid item xs={12}>
|
|
<Typography variant="subtitle2" sx={{ fontWeight: 700, color: DT.textSecondary, mb: 1 }}>Date</Typography>
|
|
<LocalizationProvider dateAdapter={AdapterDayjs} sx={{}}>
|
|
<DatePicker
|
|
format="DD-MM-YYYY"
|
|
onChange={(e) => {
|
|
let dateres11 = dayjs().diff(dayjs(`${dayjs(e).format('YYYY-MM-DD')}`), 'd');
|
|
console.log('dateres11');
|
|
console.log(dateres11);
|
|
setSelectedtime('');
|
|
if (dateres11 <= 0) {
|
|
console.log('startdate', e);
|
|
setStartdate(e);
|
|
setEnddate(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);
|
|
}
|
|
});
|
|
if (arr[0]) {
|
|
setOrderarr([
|
|
{
|
|
sno: 1,
|
|
address: '',
|
|
customerid: '',
|
|
deliverytime: dayjs(arr[0]) || '',
|
|
deliverylocationid: '',
|
|
clientname: '',
|
|
contactno: '',
|
|
latitude: '',
|
|
longitude: ''
|
|
}
|
|
]);
|
|
} else {
|
|
setOrderarr([]);
|
|
}
|
|
} else {
|
|
setAlertmessage('choose Upcoming Date');
|
|
opentoast('choose Upcoming Date', 'warning');
|
|
setStartdate(NaN);
|
|
}
|
|
}}
|
|
value={dayjs(startdate)}
|
|
sx={{ width: '100%', mt: 2 }}
|
|
disablePast
|
|
/>
|
|
</LocalizationProvider>
|
|
<Typography variant="subtitle2" sx={{ fontWeight: 700, color: DT.textSecondary, mt: 2, mb: 1 }}>
|
|
Time
|
|
</Typography>
|
|
<Box
|
|
sx={{
|
|
mt: 0.5,
|
|
p: 1.25,
|
|
borderRadius: 2,
|
|
border: '1px solid',
|
|
borderColor: DT.divider,
|
|
bgcolor: DT.surfaceAlt,
|
|
maxHeight: 150,
|
|
overflowY: 'auto',
|
|
scrollbarWidth: 'thin',
|
|
'&::-webkit-scrollbar': { width: 6 },
|
|
'&::-webkit-scrollbar-thumb': { backgroundColor: edge(BRAND), borderRadius: 6 }
|
|
}}
|
|
>
|
|
<Stack direction="row" flexWrap="wrap" gap={0.75} useFlexGap>
|
|
{timeslotarr.map((val, index) => {
|
|
if (
|
|
dayjs().diff(dayjs(`${dayjs(startdate).format('MM-DD-YYYY')} ${dayjs(val).format('HH:mm:ss')}`), 'm') <= 0
|
|
) {
|
|
const active = dayjs(selectedtime).format('HH:mm') == dayjs(val).format('HH:mm');
|
|
return (
|
|
<Box
|
|
key={index}
|
|
onClick={() => {
|
|
if (distance > appLocaRadius) {
|
|
setOpen4(true);
|
|
} else if (showDistance) {
|
|
setSelectedtime(val);
|
|
} else {
|
|
opentoast('Select Pickup and Drop', 'error');
|
|
}
|
|
}}
|
|
sx={{
|
|
display: 'inline-flex',
|
|
alignItems: 'center',
|
|
gap: 0.5,
|
|
px: 1.25,
|
|
py: 0.5,
|
|
cursor: 'pointer',
|
|
borderRadius: 999,
|
|
border: `1.5px solid ${active ? '#f59e0b' : edge('#f59e0b')}`,
|
|
bgcolor: active ? '#f59e0b' : tint('#f59e0b'),
|
|
color: active ? '#fff' : '#f59e0b',
|
|
fontSize: 12,
|
|
fontWeight: 800,
|
|
transition: 'all 0.15s',
|
|
boxShadow: active ? `0 6px 18px ${ring('#f59e0b')}` : 'none',
|
|
'&:hover': {
|
|
borderColor: '#f59e0b',
|
|
boxShadow: active ? `0 6px 18px ${ring('#f59e0b')}` : `0 0 0 3px ${ring('#f59e0b')}`
|
|
}
|
|
}}
|
|
>
|
|
<MdHistoryToggleOff size={11} /> {dayjs(val).format('hh:mm A')}
|
|
</Box>
|
|
);
|
|
}
|
|
})}
|
|
</Stack>
|
|
</Box>
|
|
</Grid>
|
|
</Grid>
|
|
</Box>
|
|
</SectionCard>
|
|
</Grid>
|
|
<Grid item xs={12} sm={6} sx={{}}>
|
|
<SectionCard sx={{ mt: 2, minHeight: 390 }}>
|
|
<SectionHeader
|
|
color="#10b981"
|
|
icon={<MdAttachMoney size={16} />}
|
|
title="Distance & Pricing"
|
|
subtitle="Auto-calculated from pickup → drop"
|
|
/>
|
|
<Box sx={{ p: { xs: 2, md: 2.5 } }}>
|
|
{showDistance && (
|
|
<Stack sx={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', mb: 3 }}>
|
|
<Stack spacing={1.5}>
|
|
<Chip label={`Distance: ${distance} km`} size="medium" variant="contained" color="primary" />
|
|
</Stack>
|
|
<Stack spacing={1.5}>
|
|
<Chip label={`Charge: ₹${totalCharge.toFixed(2)}`} size="medium" variant="contained" color="primary" />
|
|
</Stack>
|
|
</Stack>
|
|
)}
|
|
<Stack direction={'column'} justifyContent={'space-between'} sx={{ mb: 2 }}>
|
|
<Typography variant="h5">Category</Typography>
|
|
<Autocomplete
|
|
disablePortal
|
|
id="combo-box-demo"
|
|
options={subCat}
|
|
getOptionLabel={(option) => `${option.subcategoryname}` || ''}
|
|
sx={{ my: 2, zIndex: '100' }}
|
|
fullWidth
|
|
renderInput={(params) => <TextField {...params} label={subCatName == '' ? tenant.subcategoryname : subCatName} />}
|
|
onChange={(event, value, reason) => {
|
|
if (value) {
|
|
console.log(value);
|
|
setSubCatName(value.subcategoryname);
|
|
setSubCatId(value.subcategoryid);
|
|
}
|
|
}}
|
|
/>
|
|
</Stack>
|
|
<Typography variant="h5">Weight</Typography>
|
|
<Stack direction={'row'} justifyContent={'space-evenly'} sx={{ border: '1px solid #eee', my: 2, py: 2 }}>
|
|
<Chip
|
|
variant="contained"
|
|
color="default"
|
|
label="1-10kgs"
|
|
sx={chipStyle('1-10kgs')}
|
|
onClick={() => {
|
|
handleChipClick('1-10kgs');
|
|
setWeight('1-10kgs');
|
|
}}
|
|
/>
|
|
<Chip
|
|
variant="contained"
|
|
color="default"
|
|
label="11-20kgs"
|
|
sx={chipStyle('11-20kgs')}
|
|
onClick={() => {
|
|
handleChipClick('11-20kgs');
|
|
setWeight('11-20kgs');
|
|
}}
|
|
/>
|
|
<Chip
|
|
variant="contained"
|
|
color="default"
|
|
label="21-30kgs"
|
|
sx={chipStyle('21-30kgs')}
|
|
onClick={() => {
|
|
handleChipClick('21-30kgs');
|
|
setWeight('21-30kgs');
|
|
}}
|
|
/>
|
|
</Stack>
|
|
<Stack direction={'row'} justifyContent={'space-between'} sx={{ mt: 4 }}>
|
|
<Typography variant="h5">SMS Delivery</Typography>
|
|
<Switch
|
|
checked={isSms === 1}
|
|
onChange={(e) => {
|
|
setIsSms(e.target.checked ? 1 : 0);
|
|
}}
|
|
/>
|
|
</Stack>
|
|
</Box>
|
|
</SectionCard>
|
|
</Grid>
|
|
</Grid>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
{/* ============================== || Cash Collect & Quantity || ============================== */}
|
|
<SectionCard sx={{ mt: 2 }}>
|
|
<SectionHeader
|
|
color="#6366f1"
|
|
icon={<MdInventory2 size={16} />}
|
|
title="Collection & Quantity"
|
|
subtitle="Cash to collect on delivery, total items"
|
|
/>
|
|
<Box sx={{ p: { xs: 2, md: 2.5 } }}>
|
|
<Grid container spacing={2}>
|
|
<Grid item xs={12} sm={6}>
|
|
<TextField
|
|
type="number"
|
|
value={collectionamt}
|
|
fullWidth
|
|
label="Cash Collect"
|
|
onChange={(e) => setCollectionamt(e.target.value)}
|
|
inputProps={{ min: 0 }}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} sm={6}>
|
|
<TextField
|
|
type="number"
|
|
value={quantity}
|
|
fullWidth
|
|
label="Quantity"
|
|
onChange={(e) => setQuantity(e.target.value)}
|
|
inputProps={{ min: 1 }}
|
|
/>
|
|
</Grid>
|
|
</Grid>
|
|
</Box>
|
|
</SectionCard>
|
|
|
|
{/* ================================================= || Notes || ================================================= */}
|
|
<SectionCard sx={{ mt: 2 }}>
|
|
<SectionHeader
|
|
color={DT.textSecondary}
|
|
icon={<MdNotes size={16} />}
|
|
title="Notes"
|
|
subtitle="Add anything the rider should know"
|
|
/>
|
|
<Box sx={{ p: { xs: 2, md: 2.5 } }}>
|
|
<TextField
|
|
focused
|
|
variant="outlined"
|
|
sx={{ width: '100%', mb: 2 }}
|
|
multiline
|
|
rows={2}
|
|
label="Notes"
|
|
placeholder="Special instructions, gate code, etc."
|
|
value={otherinstructions}
|
|
onChange={(e) => setOtherinstructions(e.target.value)}
|
|
/>
|
|
<Divider sx={{ my: 1.5 }} />
|
|
<Stack direction="row" justifyContent="flex-end" alignItems="center" spacing={1.25}>
|
|
{!showDistance && (
|
|
<Typography variant="caption" sx={{ color: DT.textMuted, fontWeight: 700 }}>
|
|
Set pickup & drop to enable
|
|
</Typography>
|
|
)}
|
|
<Button
|
|
size="medium"
|
|
disabled={!showDistance}
|
|
variant="contained"
|
|
startIcon={btnLoading ? null : <MdCheckCircle size={16} />}
|
|
onClick={() => {
|
|
setLoading(true);
|
|
setBtnLoading(true);
|
|
createsubmitobj2();
|
|
setTimeout(() => {
|
|
setLoading(false);
|
|
setBtnLoading(false);
|
|
}, 1000);
|
|
}}
|
|
sx={{
|
|
borderRadius: 999,
|
|
px: 3,
|
|
py: 1,
|
|
fontWeight: 800,
|
|
textTransform: 'none',
|
|
fontSize: 13,
|
|
background: `linear-gradient(135deg, ${BRAND} 0%, ${BRAND_LIGHT} 100%)`,
|
|
color: '#fff',
|
|
boxShadow: `0 8px 22px ${ring(BRAND)}`,
|
|
transition: 'all 0.18s',
|
|
'&:hover': {
|
|
background: `linear-gradient(135deg, #4D1C61 0%, ${BRAND} 100%)`,
|
|
transform: 'translateY(-1px)',
|
|
boxShadow: `0 10px 26px ${ring(BRAND)}`
|
|
},
|
|
'&.Mui-disabled': {
|
|
background: DT.divider,
|
|
color: DT.textMuted,
|
|
boxShadow: 'none'
|
|
}
|
|
}}
|
|
>
|
|
{btnLoading ? <CircularProgress size={18} thickness={5} sx={{ color: '#fff' }} /> : 'Create Order'}
|
|
</Button>
|
|
</Stack>
|
|
</Box>
|
|
</SectionCard>
|
|
</Box>
|
|
</Grid>
|
|
|
|
{/* <Dialog
|
|
open={open3}
|
|
onClose={closetimemodal}
|
|
sx={{ '& .MuiDialog-paper': { p: 0 }, '& .MuiBackdrop-root': { opacity: '0.5 !important' } }}
|
|
>
|
|
<DialogTitle>
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
<Typography variant="h5">Select Time</Typography>
|
|
</Stack>
|
|
</DialogTitle>
|
|
<Divider />
|
|
<DialogContent sx={{ p: 2.5 }}>
|
|
<Grid container spacing={2}>
|
|
{timeslotarr.map((val) => {
|
|
if (
|
|
dayjs().diff(dayjs(`${dayjs(startdate).format('MM-DD-YYYY')} ${dayjs(val).format('HH:mm:ss')}`), 'm') <= 0
|
|
// && currentsno
|
|
) {
|
|
return (
|
|
<>
|
|
<Grid item>
|
|
<Chip
|
|
sx={{ cursor: 'pointer' }}
|
|
label={dayjs(val).format('hh:mm A')}
|
|
onClick={() => {
|
|
setSelectedtime(dayjs(val).format('hh:mm A'));
|
|
}}
|
|
/>
|
|
</Grid>
|
|
</>
|
|
);
|
|
}
|
|
})}
|
|
</Grid>
|
|
</DialogContent>
|
|
<Divider />
|
|
<DialogActions sx={{ p: 2.5, minWidth: '300px' }}>
|
|
<Button
|
|
variant="contained"
|
|
color="error"
|
|
onClick={() => {
|
|
closetimemodal();
|
|
}}
|
|
>
|
|
Cancel
|
|
</Button>
|
|
<Button onClick={closetimemodal} color="primary" variant="contained">
|
|
OK
|
|
</Button>
|
|
</DialogActions>
|
|
</Dialog> */}
|
|
|
|
{/* ============================================= || saved address Dialog || ============================================= */}
|
|
<Dialog
|
|
open={isCustomerOpen}
|
|
onClose={() => setIsCustomerOpen(false)}
|
|
fullWidth
|
|
maxWidth="sm"
|
|
PaperProps={{ sx: { borderRadius: 3 } }}
|
|
>
|
|
<DialogTitle
|
|
sx={{
|
|
p: 2.5,
|
|
background: `linear-gradient(135deg, ${tint(BRAND)} 0%, ${tint(BRAND_LIGHT)} 100%)`,
|
|
borderBottom: `1px solid ${DT.borderSubtle}`
|
|
}}
|
|
>
|
|
<Stack direction="row" alignItems="center" spacing={1.5} sx={{ mb: 1.5 }}>
|
|
<Avatar sx={{ bgcolor: BRAND, color: '#fff', width: 40, height: 40, boxShadow: `0 6px 18px ${ring(BRAND)}` }}>
|
|
<MdPersonPin size={20} />
|
|
</Avatar>
|
|
<Stack>
|
|
<Typography variant="h5" sx={{ fontWeight: 800, color: DT.textPrimary }}>
|
|
Saved Locations
|
|
</Typography>
|
|
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 600 }}>
|
|
Pick a saved customer for {pickordrop === 1 ? 'Pickup' : 'Drop'}
|
|
</Typography>
|
|
</Stack>
|
|
</Stack>
|
|
<Box
|
|
sx={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 0.75,
|
|
px: 1.25,
|
|
py: 0.5,
|
|
borderRadius: 999,
|
|
bgcolor: '#fff',
|
|
border: `1.5px solid ${edge(BRAND)}`,
|
|
transition: 'all 0.18s',
|
|
'&:focus-within': {
|
|
borderColor: BRAND,
|
|
boxShadow: `0 0 0 3px ${ring(BRAND)}`
|
|
}
|
|
}}
|
|
>
|
|
<SearchOutlined style={{ color: BRAND, fontSize: 14 }} />
|
|
<OutlinedInput
|
|
fullWidth
|
|
placeholder="Search saved customer"
|
|
value={searchCustList}
|
|
onChange={(e) => setSearchCustList(e.target.value)}
|
|
sx={{
|
|
flex: 1,
|
|
'& .MuiOutlinedInput-input': { p: '6px 4px', fontSize: 13, fontWeight: 600 },
|
|
'& fieldset': { border: 'none' }
|
|
}}
|
|
endAdornment={
|
|
searchCustList && (
|
|
<IconButton size="small" onClick={() => setSearchCustList('')} sx={{ p: 0.25, color: BRAND }}>
|
|
<ClearIcon fontSize="small" />
|
|
</IconButton>
|
|
)
|
|
}
|
|
autoComplete="off"
|
|
/>
|
|
</Box>
|
|
</DialogTitle>
|
|
<DialogContent sx={{ p: 2, bgcolor: DT.surfaceAlt }}>
|
|
{customerlist.length === 0 ? (
|
|
<Stack alignItems="center" justifyContent="center" spacing={1.5} sx={{ minHeight: 480, maxHeight: 480 }}>
|
|
<Avatar sx={{ width: 56, height: 56, bgcolor: soft('#94a3b8'), color: DT.textMuted }}>
|
|
<MdPersonPin size={26} />
|
|
</Avatar>
|
|
<Typography variant="subtitle1" sx={{ fontWeight: 700, color: DT.textPrimary }}>
|
|
No saved locations
|
|
</Typography>
|
|
<Typography variant="caption" sx={{ color: DT.textSecondary }}>
|
|
{searchCustList ? 'Try a different keyword.' : 'Save a customer from the order form to reuse it later.'}
|
|
</Typography>
|
|
</Stack>
|
|
) : (
|
|
<Stack spacing={1} sx={{ minHeight: 480, maxHeight: 480, overflow: 'auto', pr: 0.5 }}>
|
|
{customerlist.map((address, index) => {
|
|
const isUsed = pickCust.customerid === address.customerid;
|
|
return (
|
|
<Box
|
|
key={index}
|
|
onClick={() => {
|
|
if (isUsed) return;
|
|
setIsCustomerOpen(false);
|
|
if (pickordrop === 1) {
|
|
setAddId1(1);
|
|
setStartPoint({ latitude: address.latitude, longitude: address.longitude });
|
|
setPickCust(address);
|
|
setPickNum(address.contactno);
|
|
} else {
|
|
setAddId2(1);
|
|
setEndPoint({ latitude: address.latitude, longitude: address.longitude });
|
|
setDropCust(address);
|
|
setdropNum(address.contactno);
|
|
}
|
|
}}
|
|
sx={{
|
|
display: 'flex',
|
|
alignItems: 'flex-start',
|
|
gap: 1.25,
|
|
p: 1.5,
|
|
borderRadius: 2,
|
|
border: '1px solid',
|
|
borderColor: isUsed ? edge('#94a3b8') : DT.borderSubtle,
|
|
bgcolor: isUsed ? DT.surfaceAlt : '#fff',
|
|
cursor: isUsed ? 'not-allowed' : 'pointer',
|
|
opacity: isUsed ? 0.6 : 1,
|
|
transition: 'all 0.15s',
|
|
'&:hover': isUsed
|
|
? {}
|
|
: {
|
|
borderColor: edge(BRAND),
|
|
bgcolor: tint(BRAND),
|
|
boxShadow: DT.shadowSoft
|
|
}
|
|
}}
|
|
>
|
|
<Avatar sx={{ width: 36, height: 36, bgcolor: soft(BRAND), color: BRAND, fontWeight: 800 }}>
|
|
{String(address.firstname || '?').charAt(0).toUpperCase()}
|
|
</Avatar>
|
|
<Stack sx={{ flex: 1, minWidth: 0 }}>
|
|
<Stack direction="row" alignItems="center" spacing={0.75} flexWrap="wrap" useFlexGap>
|
|
<Typography sx={{ fontWeight: 800, color: DT.textPrimary, fontSize: 13.5 }} noWrap>
|
|
{address.firstname}
|
|
</Typography>
|
|
<Box
|
|
sx={{
|
|
display: 'inline-flex',
|
|
alignItems: 'center',
|
|
gap: 0.375,
|
|
px: 0.75,
|
|
py: 0.125,
|
|
borderRadius: 999,
|
|
bgcolor: tint('#0ea5e9'),
|
|
border: `1px solid ${edge('#0ea5e9')}`,
|
|
color: '#0ea5e9',
|
|
fontSize: 10.5,
|
|
fontWeight: 800
|
|
}}
|
|
>
|
|
<FaPhoneAlt size={9} /> {address.contactno}
|
|
</Box>
|
|
{isUsed && (
|
|
<Box
|
|
sx={{
|
|
display: 'inline-flex',
|
|
alignItems: 'center',
|
|
px: 0.75,
|
|
py: 0.125,
|
|
borderRadius: 999,
|
|
bgcolor: tint('#94a3b8'),
|
|
border: `1px solid ${edge('#94a3b8')}`,
|
|
color: DT.textSecondary,
|
|
fontSize: 10.5,
|
|
fontWeight: 800
|
|
}}
|
|
>
|
|
Already used
|
|
</Box>
|
|
)}
|
|
</Stack>
|
|
<Typography variant="caption" sx={{ color: DT.textSecondary, mt: 0.25 }} noWrap>
|
|
{address.address}
|
|
</Typography>
|
|
</Stack>
|
|
</Box>
|
|
);
|
|
})}
|
|
</Stack>
|
|
)}
|
|
</DialogContent>
|
|
<Stack direction="row" justifyContent="flex-end" sx={{ p: 2, borderTop: `1px solid ${DT.divider}` }}>
|
|
<Button
|
|
variant="outlined"
|
|
onClick={() => setIsCustomerOpen(false)}
|
|
sx={{
|
|
borderRadius: 999,
|
|
px: 2.5,
|
|
borderColor: DT.borderSubtle,
|
|
color: DT.textSecondary,
|
|
fontWeight: 700,
|
|
textTransform: 'none',
|
|
'&:hover': { borderColor: DT.textSecondary, bgcolor: DT.surfaceAlt }
|
|
}}
|
|
>
|
|
Cancel
|
|
</Button>
|
|
</Stack>
|
|
</Dialog>
|
|
|
|
<Dialog open={open4} onClose={() => setOpen4(false)} PaperProps={{ sx: { borderRadius: 3 } }}>
|
|
<Box
|
|
sx={{
|
|
p: 2.5,
|
|
background: `linear-gradient(135deg, ${tint('#ef4444')} 0%, ${tint('#f59e0b')} 100%)`,
|
|
borderBottom: `1px solid ${DT.borderSubtle}`
|
|
}}
|
|
>
|
|
<Stack direction="row" alignItems="center" spacing={1.5}>
|
|
<Avatar sx={{ bgcolor: '#ef4444', color: '#fff', width: 40, height: 40, boxShadow: `0 6px 18px ${ring('#ef4444')}` }}>
|
|
<HighlightOffIcon />
|
|
</Avatar>
|
|
<Stack>
|
|
<Typography variant="h5" sx={{ fontWeight: 800, color: DT.textPrimary }}>
|
|
Out of Service Area
|
|
</Typography>
|
|
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 600 }}>
|
|
This drop point is outside the supported radius
|
|
</Typography>
|
|
</Stack>
|
|
</Stack>
|
|
</Box>
|
|
<DialogContent sx={{ pt: 2.5 }}>
|
|
<Typography sx={{ color: DT.textSecondary, fontWeight: 600 }}>
|
|
Service is not available at this location. Try a different drop point within the coverage zone.
|
|
</Typography>
|
|
</DialogContent>
|
|
<Stack direction="row" justifyContent="flex-end" sx={{ p: 2, borderTop: `1px solid ${DT.divider}` }}>
|
|
<Button
|
|
variant="contained"
|
|
onClick={() => setOpen4(false)}
|
|
sx={{
|
|
borderRadius: 999,
|
|
px: 3,
|
|
bgcolor: '#ef4444',
|
|
fontWeight: 700,
|
|
textTransform: 'none',
|
|
boxShadow: `0 6px 18px ${ring('#ef4444')}`,
|
|
'&:hover': { bgcolor: '#dc2626' }
|
|
}}
|
|
>
|
|
Close
|
|
</Button>
|
|
</Stack>
|
|
</Dialog>
|
|
</Grid>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default Createorder1;
|