updates on the build regarding the google map api key removal
This commit is contained in:
193
src/components/nearle_components/AddressAutocomplete.js
Normal file
193
src/components/nearle_components/AddressAutocomplete.js
Normal file
@@ -0,0 +1,193 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { Autocomplete, TextField, CircularProgress } from '@mui/material';
|
||||
import { debounce } from '@mui/material/utils';
|
||||
|
||||
// Free OSM Nominatim geocoder — replaces Google Places Autocomplete /
|
||||
// react-geocode across the console. No API key required. Nominatim's usage
|
||||
// policy caps the public endpoint at ~1 req/sec, so every caller here is
|
||||
// debounced (500ms) and cancels stale in-flight predictions.
|
||||
const NOMINATIM_SEARCH_URL = 'https://nominatim.openstreetmap.org/search';
|
||||
|
||||
// Builds a Google-Places-shaped `address_components` array (each entry
|
||||
// `{ long_name, short_name, types: [] }`) from Nominatim's flat `address`
|
||||
// object, so existing call sites' `place.address_components.forEach(...)`
|
||||
// type-switch parsing keeps working unchanged.
|
||||
const buildAddressComponents = (addr = {}) => {
|
||||
const components = [];
|
||||
const push = (longName, types) => {
|
||||
if (longName) components.push({ long_name: longName, short_name: longName, types });
|
||||
};
|
||||
push(addr.house_number, ['street_number']);
|
||||
push(addr.road || addr.pedestrian, ['route']);
|
||||
push(addr.suburb || addr.neighbourhood || addr.quarter, ['sublocality_level_1', 'sublocality']);
|
||||
push(addr.city_district || addr.county, ['administrative_area_level_3']);
|
||||
push(addr.city || addr.town || addr.village, ['locality']);
|
||||
push(addr.state, ['administrative_area_level_1']);
|
||||
push(addr.country, ['country']);
|
||||
push(addr.postcode, ['postal_code']);
|
||||
return components;
|
||||
};
|
||||
|
||||
// Shapes a Nominatim result close enough to a Google Places `place` object
|
||||
// (formatted_address, geometry.location.lat()/lng(), address_components)
|
||||
// that call sites need only mechanical edits, not rewrites.
|
||||
export const toPlace = (result) => ({
|
||||
formatted_address: result.display_name,
|
||||
name: result.display_name?.split(',')[0] || '',
|
||||
geometry: {
|
||||
location: {
|
||||
lat: () => parseFloat(result.lat),
|
||||
lng: () => parseFloat(result.lon)
|
||||
}
|
||||
},
|
||||
address_components: buildAddressComponents(result.address)
|
||||
});
|
||||
|
||||
const buildParams = (query, bias) => {
|
||||
const params = new URLSearchParams({ q: query, format: 'json', addressdetails: '1', limit: '5' });
|
||||
if (bias?.lat && bias?.lng) {
|
||||
const d = 0.5; // ~55km box around the operator's zone — soft bias, not a hard filter
|
||||
params.set('viewbox', `${bias.lng - d},${bias.lat + d},${bias.lng + d},${bias.lat - d}`);
|
||||
}
|
||||
return params;
|
||||
};
|
||||
|
||||
// Standalone forward-geocode helper — replaces `Geocode.fromAddress(address)`
|
||||
// for call sites that resolve a plain text address without a predictions
|
||||
// dropdown (e.g. re-geocoding on submit). Returns a `toPlace`-shaped object,
|
||||
// or null if nothing matched.
|
||||
export async function geocodeAddress(address, { bias } = {}) {
|
||||
if (!address) return null;
|
||||
try {
|
||||
const params = buildParams(address, bias);
|
||||
params.set('limit', '1');
|
||||
const res = await fetch(`${NOMINATIM_SEARCH_URL}?${params.toString()}`, { headers: { Accept: 'application/json' } });
|
||||
if (!res.ok) return null;
|
||||
const results = await res.json();
|
||||
if (!results?.length) return null;
|
||||
return toPlace(results[0]);
|
||||
} catch (err) {
|
||||
console.error('geocodeAddress error:', err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Address search-as-you-type — replaces Google Places Autocomplete
|
||||
// (usePlacesWidget / window.google.maps.places.Autocomplete /
|
||||
// AutocompleteService) across the console. Renders as an MUI Autocomplete
|
||||
// with freeSolo so the operator can still submit free text.
|
||||
//
|
||||
// Props:
|
||||
// value / onChange(text) — controlled free-text input value
|
||||
// onPlaceSelected(place) — fired when a suggestion is chosen; `place`
|
||||
// is shaped like a Google Places `place`
|
||||
// bias { lat, lng } — optional soft bias toward the operator's zone
|
||||
const AddressAutocomplete = ({
|
||||
id,
|
||||
label,
|
||||
placeholder = 'Search address',
|
||||
value,
|
||||
onChange,
|
||||
onPlaceSelected,
|
||||
bias,
|
||||
sx,
|
||||
textFieldSx,
|
||||
fullWidth = true,
|
||||
disabled,
|
||||
inputRef,
|
||||
TextFieldProps = {}
|
||||
}) => {
|
||||
const [inputValue, setInputValue] = useState(value || '');
|
||||
const [options, setOptions] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (value !== undefined && value !== inputValue) setInputValue(value || '');
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [value]);
|
||||
|
||||
const fetchPredictions = useMemo(
|
||||
() =>
|
||||
debounce((query, bias1, callback) => {
|
||||
if (!query) {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
const params = buildParams(query, bias1);
|
||||
fetch(`${NOMINATIM_SEARCH_URL}?${params.toString()}`, { headers: { Accept: 'application/json' } })
|
||||
.then((res) => (res.ok ? res.json() : []))
|
||||
.then((results) => callback(results || []))
|
||||
.catch(() => callback([]));
|
||||
}, 500),
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
if (!inputValue) {
|
||||
setOptions([]);
|
||||
setLoading(false);
|
||||
return undefined;
|
||||
}
|
||||
setLoading(true);
|
||||
fetchPredictions(inputValue, bias, (results) => {
|
||||
if (!active) return;
|
||||
setLoading(false);
|
||||
setOptions(results);
|
||||
});
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [inputValue, bias?.lat, bias?.lng, fetchPredictions]);
|
||||
|
||||
return (
|
||||
<Autocomplete
|
||||
id={id}
|
||||
freeSolo
|
||||
fullWidth={fullWidth}
|
||||
disabled={disabled}
|
||||
sx={sx}
|
||||
options={options}
|
||||
filterOptions={(x) => x}
|
||||
getOptionLabel={(option) => (typeof option === 'string' ? option : option.display_name || '')}
|
||||
isOptionEqualToValue={(option, val) => option.place_id === val?.place_id}
|
||||
inputValue={inputValue}
|
||||
onInputChange={(event, newInputValue) => {
|
||||
setInputValue(newInputValue);
|
||||
onChange?.(newInputValue);
|
||||
}}
|
||||
onChange={(event, selected) => {
|
||||
if (selected && typeof selected !== 'string') {
|
||||
setInputValue(selected.display_name || '');
|
||||
onPlaceSelected?.(toPlace(selected));
|
||||
}
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
{...TextFieldProps}
|
||||
inputRef={inputRef}
|
||||
label={label}
|
||||
placeholder={placeholder}
|
||||
sx={textFieldSx}
|
||||
autoComplete="off"
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
...TextFieldProps.InputProps,
|
||||
startAdornment: TextFieldProps.InputProps?.startAdornment ?? params.InputProps.startAdornment,
|
||||
endAdornment: (
|
||||
<>
|
||||
{loading ? <CircularProgress color="inherit" size={16} /> : null}
|
||||
{TextFieldProps.InputProps?.endAdornment ?? params.InputProps.endAdornment}
|
||||
</>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddressAutocomplete;
|
||||
@@ -25,9 +25,8 @@ import MainCard from 'components/MainCard';
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
import { usePlacesWidget } from 'react-google-autocomplete';
|
||||
import AddressAutocomplete from 'components/nearle_components/AddressAutocomplete';
|
||||
import Loader from 'components/Loader';
|
||||
import Geocode from 'react-geocode';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { useNavigate } from 'react-router';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
@@ -54,7 +53,6 @@ const CreateCustomer = () => {
|
||||
const [inputValue2, setInputValue2] = useState('');
|
||||
const [appLocaLat, setAppLocaLat] = useState();
|
||||
const [appLocaLng, setAppLocaLng] = useState();
|
||||
const [appLocaRadius, setAppLocaRadius] = useState();
|
||||
const [locaName, setLocoName] = useState('Select Location');
|
||||
const [locations, setLocations] = useState('Select Location');
|
||||
const [tenantlist, setTenantlist] = useState([]);
|
||||
@@ -72,9 +70,6 @@ const CreateCustomer = () => {
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
Geocode.setApiKey(process.env.REACT_APP_GOOGLE_MAPS_API_KEY);
|
||||
// Geocode.setApiKey('AIzaSyCF4KatYCI3vqz1_H3kiHeyS3yCMfYToh8');
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -83,91 +78,68 @@ const CreateCustomer = () => {
|
||||
}
|
||||
}, []);
|
||||
|
||||
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()
|
||||
// ============================================= || Address Autocomplete (pick) || =============================================
|
||||
const handlePickPlaceSelected = (place) => {
|
||||
setInputValue2(`${place.name}, ${place.formatted_address}`);
|
||||
setStartPoint({ latitude: place.geometry.location.lat(), longitude: place.geometry.location.lng() });
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
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() });
|
||||
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.administrative_area_level_3,
|
||||
city: address.locality,
|
||||
state: address.administrative_area_level_1,
|
||||
postcode: address.postal_code,
|
||||
latitude: place.geometry.location.lat(),
|
||||
longitude: place.geometry.location.lng()
|
||||
});
|
||||
console.log('Pick Address:', address);
|
||||
});
|
||||
}
|
||||
}, [inputValue2]);
|
||||
setPickCust({
|
||||
...pickCust,
|
||||
address: address.address,
|
||||
doorno: `${address.street_number} ${address.route}`,
|
||||
suburb: address.administrative_area_level_3,
|
||||
city: address.locality,
|
||||
state: address.administrative_area_level_1,
|
||||
postcode: address.postal_code,
|
||||
latitude: place.geometry.location.lat(),
|
||||
longitude: place.geometry.location.lng()
|
||||
});
|
||||
};
|
||||
// ==================================================== || getapplocations || ====================================================
|
||||
const getapplocations = async () => {
|
||||
setLoading(true);
|
||||
@@ -175,12 +147,10 @@ const CreateCustomer = () => {
|
||||
.get(`${process.env.REACT_APP_URL}/utils/getapplocations/?applocationid=${appId}`)
|
||||
.then((res) => {
|
||||
console.log('getapplocations', res);
|
||||
const { opentime, closetime, latitude, longitude, radius } = res.data.details[0];
|
||||
const { latitude, longitude } = res.data.details[0];
|
||||
if (res.data.status) {
|
||||
setAppLocaLat(latitude);
|
||||
setAppLocaLng(longitude);
|
||||
setAppLocaRadius(radius);
|
||||
console.log('radius', radius);
|
||||
}
|
||||
setLoading(false);
|
||||
})
|
||||
@@ -449,32 +419,36 @@ const CreateCustomer = () => {
|
||||
<Grid item xs={12}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel htmlFor="personal-email"> Address</InputLabel>
|
||||
<TextField
|
||||
variant="outlined"
|
||||
<AddressAutocomplete
|
||||
id="addressAuto1"
|
||||
fullWidth
|
||||
value={inputValue2}
|
||||
onChange={(e) => setInputValue2(e.target.value)}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setInputValue2('');
|
||||
setPickCust({
|
||||
...pickCust,
|
||||
doorno: '',
|
||||
suburb: '',
|
||||
city: '',
|
||||
postcode: '',
|
||||
landmark: ''
|
||||
});
|
||||
setStartPoint({ latitude: 0, longitude: 0 });
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
)
|
||||
onChange={setInputValue2}
|
||||
onPlaceSelected={handlePickPlaceSelected}
|
||||
bias={{ lat: appLocaLat, lng: appLocaLng }}
|
||||
TextFieldProps={{
|
||||
variant: 'outlined',
|
||||
InputProps: {
|
||||
endAdornment: (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setInputValue2('');
|
||||
setPickCust({
|
||||
...pickCust,
|
||||
doorno: '',
|
||||
suburb: '',
|
||||
city: '',
|
||||
postcode: '',
|
||||
landmark: ''
|
||||
});
|
||||
setStartPoint({ latitude: 0, longitude: 0 });
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
@@ -46,7 +46,7 @@ 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 AddressAutocomplete from 'components/nearle_components/AddressAutocomplete';
|
||||
import Loader from 'components/Loader';
|
||||
import * as geolib from 'geolib';
|
||||
import MainCard from 'components/MainCard';
|
||||
@@ -60,7 +60,6 @@ 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';
|
||||
@@ -177,31 +176,9 @@ const SoftPaper = (props) => (
|
||||
/>
|
||||
);
|
||||
|
||||
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('');
|
||||
@@ -218,11 +195,6 @@ const Createorder1 = () => {
|
||||
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);
|
||||
@@ -244,234 +216,6 @@ const Createorder1 = () => {
|
||||
}
|
||||
};
|
||||
|
||||
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({});
|
||||
@@ -687,41 +431,6 @@ const Createorder1 = () => {
|
||||
}
|
||||
}, [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 () => {
|
||||
@@ -1161,176 +870,126 @@ const Createorder1 = () => {
|
||||
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()
|
||||
// ============================================= || Address Autocomplete (pick) || =============================================
|
||||
const handlePickPlaceSelected = (place) => {
|
||||
setInputValue2(`${place.name}, ${place.formatted_address}`);
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
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);
|
||||
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()
|
||||
});
|
||||
};
|
||||
// ============================================= || Address Autocomplete (Drop) || =============================================
|
||||
const handleDropPlaceSelected = (place) => {
|
||||
setInputValue3(`${place.name}, ${place.formatted_address}`);
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [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]);
|
||||
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()
|
||||
});
|
||||
};
|
||||
|
||||
// ============================================= || gettenantlocations (branches) || =============================================
|
||||
const gettenantlocations = async () => {
|
||||
@@ -1609,35 +1268,39 @@ const Createorder1 = () => {
|
||||
<Stack spacing={1.25} sx={{ mt: 0 }}>
|
||||
{addId1 == 0 ? (
|
||||
<div>
|
||||
<TextField
|
||||
variant="outlined"
|
||||
<AddressAutocomplete
|
||||
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>
|
||||
)
|
||||
onChange={setInputValue2}
|
||||
onPlaceSelected={handlePickPlaceSelected}
|
||||
bias={{ lat: appLocaLat, lng: appLocaLng }}
|
||||
TextFieldProps={{
|
||||
variant: 'outlined',
|
||||
InputProps: {
|
||||
endAdornment: (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setInputValue2('');
|
||||
setPickCust({
|
||||
...pickCust,
|
||||
doorno: '',
|
||||
suburb: '',
|
||||
city: '',
|
||||
postcode: '',
|
||||
landmark: ''
|
||||
});
|
||||
setShowDistance(false);
|
||||
setStartPoint({ latitude: 0, longitude: 0 });
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -2021,34 +1684,38 @@ const Createorder1 = () => {
|
||||
<Stack spacing={1.25} sx={{ mt: 0 }}>
|
||||
{addId2 == 0 ? (
|
||||
<div>
|
||||
<TextField
|
||||
<AddressAutocomplete
|
||||
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>
|
||||
)
|
||||
onChange={setInputValue3}
|
||||
onPlaceSelected={handleDropPlaceSelected}
|
||||
bias={{ lat: appLocaLat, lng: appLocaLng }}
|
||||
TextFieldProps={{
|
||||
InputProps: {
|
||||
endAdornment: (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setInputValue3('');
|
||||
setDropCust({
|
||||
...dropCust,
|
||||
doorno: '',
|
||||
suburb: '',
|
||||
city: '',
|
||||
postcode: '',
|
||||
landmark: ''
|
||||
});
|
||||
setShowDistance(false);
|
||||
setEndPoint({ latitude: 0, longitude: 0 });
|
||||
}}
|
||||
size="small"
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import TextField from '@mui/material/TextField';
|
||||
import Autocomplete from '@mui/material/Autocomplete';
|
||||
import LocationOnIcon from '@mui/icons-material/LocationOn';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import parse from 'autosuggest-highlight/parse';
|
||||
import { debounce } from '@mui/material/utils';
|
||||
|
||||
// This key was created specifically for the demo in mui.com.
|
||||
// You need to create a new one for your application.
|
||||
const GOOGLE_MAPS_API_KEY ='AIzaSyCF4KatYCI3vqz1_H3kiHeyS3yCMfYToh8';
|
||||
|
||||
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 autocompleteService = { current: null };
|
||||
|
||||
export default function GoogleMaps() {
|
||||
const [value, setValue] = React.useState(null);
|
||||
const [inputValue, setInputValue] = React.useState('');
|
||||
const [options, setOptions] = React.useState([]);
|
||||
const loaded = React.useRef(false);
|
||||
|
||||
if (typeof window !== 'undefined' && !loaded.current) {
|
||||
if (!document.querySelector('#google-maps')) {
|
||||
loadScript(
|
||||
`https://maps.googleapis.com/maps/api/js?key=${GOOGLE_MAPS_API_KEY}&libraries=places`,
|
||||
document.querySelector('head'),
|
||||
'google-maps',
|
||||
);
|
||||
}
|
||||
|
||||
loaded.current = true;
|
||||
}
|
||||
|
||||
const fetch = React.useMemo(
|
||||
() =>
|
||||
debounce((request, callback) => {
|
||||
autocompleteService.current.getPlacePredictions(request, callback);
|
||||
}, 400),
|
||||
[],
|
||||
);
|
||||
|
||||
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]);
|
||||
|
||||
return (
|
||||
<Autocomplete
|
||||
id="google-map-demo"
|
||||
// sx={{ width: 300 }}
|
||||
fullWidth
|
||||
getOptionLabel={(option) =>
|
||||
typeof option === 'string' ? option : option.description
|
||||
}
|
||||
filterOptions={(x) => x}
|
||||
options={options}
|
||||
autoComplete
|
||||
includeInputInList
|
||||
filterSelectedOptions
|
||||
value={value}
|
||||
noOptionsText="No locations"
|
||||
onChange={(event, newValue) => {
|
||||
setOptions(newValue ? [newValue, ...options] : options);
|
||||
setValue(newValue);
|
||||
}}
|
||||
onInputChange={(event, newInputValue) => {
|
||||
setInputValue(newInputValue);
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params}
|
||||
// label="Add a location"
|
||||
placeholder='Address'
|
||||
|
||||
fullWidth />
|
||||
)}
|
||||
renderOption={(props, option) => {
|
||||
const matches =
|
||||
option.structured_formatting.main_text_matched_substrings || [];
|
||||
|
||||
const parts = parse(
|
||||
option.structured_formatting.main_text,
|
||||
matches.map((match) => [match.offset, match.offset + match.length]),
|
||||
);
|
||||
|
||||
return (
|
||||
<li {...props}>
|
||||
<Grid container alignItems="center">
|
||||
<Grid item sx={{ display: 'flex', width: 44 }}>
|
||||
<LocationOnIcon sx={{ color: 'text.secondary' }} />
|
||||
</Grid>
|
||||
<Grid item sx={{ width: 'calc(100% - 44px)', wordWrap: 'break-word' }}>
|
||||
{parts.map((part, index) => (
|
||||
<Box
|
||||
key={index}
|
||||
component="span"
|
||||
sx={{ fontWeight: part.highlight ? 'bold' : 'regular' }}
|
||||
>
|
||||
{part.text}
|
||||
</Box>
|
||||
))}
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{option.structured_formatting.secondary_text}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</li>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,845 +0,0 @@
|
||||
import React from 'react';
|
||||
import Loader from 'components/Loader';
|
||||
import { useEffect, useState, Fragment } from 'react';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import MainCard from 'components/MainCard';
|
||||
import axios from 'axios';
|
||||
import ClearIcon from '@mui/icons-material/Clear';
|
||||
import { SearchOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import { Empty } from 'antd';
|
||||
import MyLocationIcon from '@mui/icons-material/MyLocation';
|
||||
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 dayjs from 'dayjs';
|
||||
var utc = require('dayjs/plugin/utc');
|
||||
dayjs.extend(utc);
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { calculateDrivingDistance, calculateTotalCharge } from '../../../utils/distance';
|
||||
import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api';
|
||||
|
||||
import {
|
||||
FormControl,
|
||||
InputAdornment,
|
||||
Grid,
|
||||
Typography,
|
||||
Stack,
|
||||
Button,
|
||||
TextField,
|
||||
Autocomplete,
|
||||
Divider,
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
Checkbox,
|
||||
DialogActions,
|
||||
CircularProgress,
|
||||
IconButton,
|
||||
OutlinedInput,
|
||||
FormGroup,
|
||||
FormControlLabel,
|
||||
Table,
|
||||
TableContainer,
|
||||
TableCell,
|
||||
TableBody,
|
||||
TableRow,
|
||||
Paper,
|
||||
TableHead,
|
||||
Box
|
||||
} from '@mui/material';
|
||||
import CircularLoader from 'components/nearle_components/CircularLoader';
|
||||
// import RidersPinPointOSM from './RidersPinPointOSM';
|
||||
import RidersPinPoint from './ridersPinPoint';
|
||||
|
||||
const MultipleOrders = () => {
|
||||
const navigate = useNavigate();
|
||||
const theme = useTheme();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [btnLoading, setBtnLoading] = useState(false);
|
||||
const [appId, setAppId] = useState(0);
|
||||
|
||||
const [tenantLocations, setTenantlocations] = useState([]);
|
||||
const userid = localStorage.getItem('userid');
|
||||
const tenId = localStorage.getItem('tenantid');
|
||||
const [tid, setTid] = useState(0);
|
||||
const [isLocation, setIsLocation] = useState(false);
|
||||
const [basePrice, setBasePrice] = useState(0);
|
||||
const [pricePerKm, setPricePerKm] = useState(0);
|
||||
const [minKm, setMinKm] = useState(0);
|
||||
const [pickCust, setPickCust] = useState(null);
|
||||
const [dropCust, setDropCust] = useState([]);
|
||||
const [isCustomerOpen, setIsCustomerOpen] = useState(false);
|
||||
const [searchCustList, setSearchCustList] = useState('');
|
||||
const [customerlist, setCustomerlist] = useState([]);
|
||||
const [startdate, setStartdate] = useState(dayjs().format('MM-DD-YYYY'));
|
||||
const [timeslotarr, setTimeslotarr] = useState([]);
|
||||
const [starttime, setStatrttime] = useState();
|
||||
const [endtime, setEndtime] = useState();
|
||||
const [alertmessage, setAlertmessage] = useState('');
|
||||
const [otherinstructions, setOtherinstructions] = useState('');
|
||||
const [admintoken, setAdmintoken] = useState();
|
||||
const [totaldist, settotaldist] = useState(0);
|
||||
const [totalAmt, settotalAmt] = useState(0);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [showMap, setShowMap] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
dropCust && console.log('dropCust', dropCust);
|
||||
}, [dropCust]);
|
||||
|
||||
// =============================================== || opentoast || ===============================================
|
||||
const opentoast = (message, variant, time) => {
|
||||
enqueueSnackbar(message, {
|
||||
variant: variant,
|
||||
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
||||
autoHideDuration: time ? time : 1500
|
||||
});
|
||||
console.log(alertmessage);
|
||||
};
|
||||
// ==============================|| 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);
|
||||
} catch (err) {
|
||||
console.log('locationRes', err);
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
fetchAppLocations();
|
||||
}, []);
|
||||
|
||||
// ============================================= || fetchTenantPricing || =============================================
|
||||
|
||||
const fetchTenantPricing = async (id) => {
|
||||
try {
|
||||
const pricingResponse = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantpricing/?tenantid=${tenId}`);
|
||||
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();
|
||||
}, []);
|
||||
// ============================================= || 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) {
|
||||
setIsLocation(true);
|
||||
setTenantlocations(res.data.details);
|
||||
setPickCust(res.data.details[0]);
|
||||
} else {
|
||||
setTenantlocations(res.data.details);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('gettenantlocations', err);
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
gettenantlocations(tenId);
|
||||
}, []);
|
||||
// ========================================================= || clientdetails || =========================================================
|
||||
const clientdetails = async () => {
|
||||
try {
|
||||
let url =
|
||||
searchCustList == ''
|
||||
? `${process.env.REACT_APP_URL}/customers/gettenantcustomers/?tenantid=${tenId}&pageno=1&pagesize=10`
|
||||
: `${process.env.REACT_APP_URL}/customers/search/?tenantid=${tenId}&keyword=${searchCustList}`;
|
||||
await axios
|
||||
.get(url)
|
||||
.then((res) => {
|
||||
if (res.data.status) {
|
||||
console.log('clientdetails', res.data.details);
|
||||
|
||||
setCustomerlist(res.data.details);
|
||||
let arr = [];
|
||||
res.data.details.map((val) => {
|
||||
arr.push({
|
||||
label: `${val.firstname} | ${val.contactno}`,
|
||||
...val
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
opentoast('server error', 'warning');
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
if (tenId) {
|
||||
clientdetails();
|
||||
}
|
||||
}, [searchCustList.length > 3, searchCustList == '', tenId]);
|
||||
|
||||
// ========================================================= || calculateTotal(dist , charge) || =========================================================
|
||||
const calculateTotal = () => {
|
||||
let a1 = 0;
|
||||
let a2 = 0;
|
||||
dropCust?.map((customer) => {
|
||||
a1 += customer.distance;
|
||||
a2 += customer.totalcharge;
|
||||
});
|
||||
settotaldist(a1);
|
||||
settotalAmt(a2);
|
||||
};
|
||||
useEffect(() => {
|
||||
dropCust && calculateTotal();
|
||||
}, [dropCust]);
|
||||
|
||||
// ========================================================= || handleCheckboxChange || =========================================================
|
||||
const handleCheckboxChange = async (event, customer) => {
|
||||
setIsLoading(true);
|
||||
console.log('event', event.target.checked);
|
||||
console.log('customer', customer);
|
||||
if (event.target.checked) {
|
||||
// If the checkbox is checked, calculate the distance and add the customer
|
||||
try {
|
||||
const obj = await calculateDistance(customer);
|
||||
console.log('return of calculateDistance', obj);
|
||||
|
||||
const { roundedDistance, totalcharge } = obj;
|
||||
// Create a new customer object with the distance property
|
||||
const updatedCustomer = {
|
||||
...customer,
|
||||
distance: roundedDistance,
|
||||
totalcharge: totalcharge
|
||||
};
|
||||
|
||||
// Add the updated customer object to dropCust
|
||||
setDropCust((prevDropCust) => [...prevDropCust, updatedCustomer]);
|
||||
|
||||
// Log the rounded distance
|
||||
console.log(`Rounded Distance: ${roundedDistance} km`);
|
||||
} catch (error) {
|
||||
console.error('Failed to calculate distance:', error);
|
||||
}
|
||||
setIsLoading(false);
|
||||
} else {
|
||||
// If the checkbox is unchecked, remove the customer from dropCust
|
||||
setDropCust((prevDropCust) => {
|
||||
return prevDropCust.filter((cust) => cust.customerid !== customer.customerid);
|
||||
});
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// ========================================================= || calculateDistance || =========================================================
|
||||
const calculateDistance = async (customer) => {
|
||||
console.log('Distance calculation starts');
|
||||
try {
|
||||
const roundedDistance = await calculateDrivingDistance(pickCust, customer);
|
||||
const totalcharge = calculateTotalCharge(roundedDistance, basePrice, pricePerKm, minKm);
|
||||
return { roundedDistance, totalcharge };
|
||||
} catch (error) {
|
||||
console.error('Error calculating distance:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// ==================================================== || 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) {
|
||||
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();
|
||||
}
|
||||
}, [starttime, endtime, 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
|
||||
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]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('pickCust', pickCust);
|
||||
}, [pickCust]);
|
||||
|
||||
// ==================================================== || 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) {
|
||||
fetchAppAdminTokens();
|
||||
}
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
if (tid) {
|
||||
fetchtenantinfo();
|
||||
}
|
||||
}, [tid]);
|
||||
// ================================================== || 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);
|
||||
});
|
||||
};
|
||||
// =============================================== || creategrouporders || ===============================================
|
||||
const creategrouporders = async () => {
|
||||
const arr = dropCust?.map((customer) => ({
|
||||
applocationid: pickCust.applocationid,
|
||||
cancellled: '',
|
||||
// categoryid: +tenant.categoryid,
|
||||
configid: 9,
|
||||
customerid: customer.customerid,
|
||||
deliveryaddress: customer.address || '',
|
||||
deliverycharge: +customer.totalcharge || 0,
|
||||
deliverycity: customer.city || '',
|
||||
deliverycontactno: customer.contactno || '',
|
||||
deliverycustomer: customer.firstname || '',
|
||||
deliveryid: +customer.customerid,
|
||||
deliverylandmark: customer.landmark || '',
|
||||
deliverylat: customer.latitude,
|
||||
deliverylocation: customer.suburb || '',
|
||||
deliverylocationid: customer.deliverylocationid || 0,
|
||||
deliverylong: customer.longitude,
|
||||
// deliverytime: `${dayjs(startdate).format('YYYY-MM-DD HH:mm:ss')} `,
|
||||
deliverytime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
deliverytype: 'B',
|
||||
delivered: '',
|
||||
itemcount: 1,
|
||||
kms: customer.distance.toString() || 0,
|
||||
locationid: +pickCust.locationid,
|
||||
moduleid: +pickCust.moduleid,
|
||||
orderamount: +customer.totalcharge || 0,
|
||||
ordercharges: 0.0,
|
||||
orderdate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
orderheaderid: 0,
|
||||
orderid: '', //
|
||||
ordernotes: otherinstructions,
|
||||
orderstatus: 'created',
|
||||
ordervalue: +customer.totalcharge || 0,
|
||||
partnerid: pickCust.partnerid,
|
||||
partneruserid: +userid,
|
||||
paymentstatus: 1,
|
||||
paymenttype: 42,
|
||||
pending: '',
|
||||
pickupaddress: pickCust.address || '',
|
||||
pickupcity: pickCust.locationcity || '',
|
||||
pickupcontactno: pickCust.contactno || '',
|
||||
pickupcustomer: pickCust.locationname || '',
|
||||
pickuplandmark: pickCust.landmark || '',
|
||||
pickuplat: pickCust.latitude,
|
||||
pickuplocation: pickCust.suburb || '',
|
||||
pickuplocationid: pickCust.locationid || 0,
|
||||
pickuplong: pickCust.longitude,
|
||||
processing: '',
|
||||
ready: '',
|
||||
remarks: '',
|
||||
taxamount: 0.0,
|
||||
tenantid: pickCust.tenantid,
|
||||
tenantuserid: 0
|
||||
}));
|
||||
console.log('arr', arr);
|
||||
|
||||
if (!tenId) {
|
||||
opentoast('Choose Client ', 'warning');
|
||||
} else {
|
||||
setLoading(true);
|
||||
|
||||
await axios
|
||||
.post(`${process.env.REACT_APP_URL}/orders/createorders`, arr)
|
||||
.then((res) => {
|
||||
if (res.data.status) {
|
||||
enqueueSnackbar('Order Created Successfully', {
|
||||
variant: 'success',
|
||||
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
||||
autoHideDuration: 1000
|
||||
});
|
||||
if (admintoken) {
|
||||
// notifyadmin(admintoken);
|
||||
sendnotifications();
|
||||
}
|
||||
navigate('/nearle/orders');
|
||||
} else {
|
||||
opentoast(res.data.message, 'warning');
|
||||
}
|
||||
setLoading(false);
|
||||
console.log(res);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
// opentoast(err.data.message, 'warning');
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
console.log(arr);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{loading && <Loader />}
|
||||
{/* <RidersPinPointOSM /> */}
|
||||
<Grid container sx={{ mb: 2 }}>
|
||||
<Grid item xs={12} sm={3} md={6}>
|
||||
<Stack>
|
||||
<Typography variant="h3" whiteSpace="nowrap">
|
||||
Multiple Orders
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={9} md={6}>
|
||||
<Stack
|
||||
sx={{}}
|
||||
width={'100%'}
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
spacing={2}
|
||||
justifyContent={'flex-end'}
|
||||
flexWrap={{ xs: 'wrap', custom550: 'nowrap' }}
|
||||
gap={2}
|
||||
>
|
||||
{/* Business Location */}
|
||||
<Stack sx={{ width: '100%' }}>
|
||||
{tenantLocations?.length === 1 ? (
|
||||
<TextField
|
||||
label="Business Location"
|
||||
fullWidth
|
||||
focused
|
||||
value={tenantLocations[0]?.locationname}
|
||||
InputProps={{
|
||||
style: { color: theme.palette.primary.main },
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<MyLocationIcon color="primary" />
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Autocomplete
|
||||
fullWidth
|
||||
options={tenantLocations || []}
|
||||
getOptionLabel={(option) => `${option.locationname} (${option.suburb})`}
|
||||
onChange={(event, value, reason) => {
|
||||
if (value) {
|
||||
setTid(value.tenantid);
|
||||
setIsLocation(true);
|
||||
setPickCust(value);
|
||||
}
|
||||
if (reason === 'clear') setIsLocation(false);
|
||||
}}
|
||||
renderInput={(params) => <TextField {...params} label="Select Business Location" color="primary" fullWidth />}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
{/* Date Picker */}
|
||||
<Stack sx={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
||||
<DatePicker
|
||||
format="DD-MM-YYYY"
|
||||
disablePast
|
||||
value={dayjs(startdate)}
|
||||
sx={{ width: 150 }}
|
||||
onChange={(e) => {
|
||||
let diff = dayjs().diff(dayjs(dayjs(e).format('YYYY-MM-DD')), 'd');
|
||||
|
||||
if (diff <= 0) {
|
||||
setStartdate(e);
|
||||
|
||||
let arr = [];
|
||||
timeslotarr.forEach((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 {
|
||||
opentoast('choose Upcoming Date', 'warning');
|
||||
setStartdate(NaN);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* ===================================================== || Pickup || ===================================================== */}
|
||||
{pickCust && (
|
||||
<TableContainer component={Paper} sx={{ mb: 2 }}>
|
||||
<Table sx={{ minWidth: 650 }} aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Pickup Location</TableCell>
|
||||
<TableCell>Address</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell>{pickCust?.locationname}</TableCell>
|
||||
<TableCell>{pickCust?.address}</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)}
|
||||
|
||||
{/* ===================================================== || Drop || ===================================================== */}
|
||||
|
||||
<MainCard
|
||||
sx={{ height: '100%' }}
|
||||
title={`Drop (${dropCust?.length || 0})`}
|
||||
secondary={
|
||||
<Button
|
||||
variant="outlined"
|
||||
size="small"
|
||||
sx={{
|
||||
'&:hover': {
|
||||
bgcolor: theme.palette.primary.main,
|
||||
color: 'white'
|
||||
}
|
||||
}}
|
||||
onClick={() => {
|
||||
if (!isLocation) {
|
||||
opentoast('Select Business Location', 'warning');
|
||||
} else {
|
||||
setIsCustomerOpen(true);
|
||||
setSearchCustList('');
|
||||
}
|
||||
}}
|
||||
>
|
||||
Select Customers
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<TableContainer component={Paper}>
|
||||
<Table sx={{ minWidth: 650 }} aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>S.No</TableCell>
|
||||
<TableCell>Customer</TableCell>
|
||||
<TableCell>Address</TableCell>
|
||||
<TableCell>Kms</TableCell>
|
||||
<TableCell align="right">Charge</TableCell>
|
||||
<TableCell>Action</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{!dropCust && (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6}>
|
||||
<Empty description={' Drop Customers Not Selected'} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
{dropCust?.map((customer, index) => (
|
||||
<TableRow key={index}>
|
||||
<TableCell>{index + 1}</TableCell>
|
||||
<TableCell>{customer.firstname}</TableCell>
|
||||
<TableCell>{customer.address}</TableCell>
|
||||
<TableCell>{customer.distance}</TableCell>
|
||||
<TableCell align="right">{`₹${customer.totalcharge}.00`}</TableCell>
|
||||
<TableCell align="center">
|
||||
{
|
||||
<CloseOutlined
|
||||
style={{ cursor: 'pointer', color: 'red' }}
|
||||
onClick={(event) => handleCheckboxChange(event, customer)}
|
||||
/>
|
||||
}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
{dropCust?.length != 0 && (
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Typography variant="h5">Total</Typography>
|
||||
</TableCell>
|
||||
<TableCell></TableCell>
|
||||
<TableCell></TableCell>
|
||||
<TableCell>
|
||||
<Typography variant="h5">{`${totaldist} `}</Typography>
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<Typography variant="h5"> {`₹${totalAmt}.00`}</Typography>
|
||||
</TableCell>
|
||||
<TableCell></TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</MainCard>
|
||||
|
||||
{/* ================================================= || Riders Map || ================================================= */}
|
||||
|
||||
{/* {showMap && dropCust.length >= 1 && <RidersPinPoint pickCust={pickCust} dropCust={dropCust} />} */}
|
||||
|
||||
{/* ================================================= || Notes || ================================================= */}
|
||||
{dropCust && (
|
||||
<MainCard sx={{ mt: 2 }} title={'Notes'}>
|
||||
<Grid container>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
focused
|
||||
id="outlined-multiline-static"
|
||||
sx={{ width: '100%', height: '100%', mb: 2 }}
|
||||
multiline
|
||||
rows={1}
|
||||
placeholder="Notes"
|
||||
value={otherinstructions}
|
||||
onChange={(e) => setOtherinstructions(e.target.value)}
|
||||
/>
|
||||
</Grid>
|
||||
<Stack direction="row" justifyContent={'end'} sx={{ mt: 2, width: '100%' }}>
|
||||
<Button
|
||||
disabled={dropCust?.length == 0}
|
||||
size="medium"
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
setLoading(true);
|
||||
setBtnLoading(true);
|
||||
creategrouporders();
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
setBtnLoading(false);
|
||||
}, 2000);
|
||||
}}
|
||||
sx={{
|
||||
'&:hover': {
|
||||
transform: 'scale(1.05)',
|
||||
transition: 'transform 0.3s ease'
|
||||
}
|
||||
}}
|
||||
>
|
||||
{btnLoading ? <CircularProgress color="primary" size={20} thickness={10} /> : 'Create'}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Grid>
|
||||
</MainCard>
|
||||
)}
|
||||
|
||||
{/* ============================================= || saved address Dialog || ============================================= */}
|
||||
<Dialog
|
||||
open={isCustomerOpen}
|
||||
onClose={() => {
|
||||
setIsCustomerOpen(false);
|
||||
}}
|
||||
fullWidth
|
||||
sx={{ minWidth: 'lg' }}
|
||||
>
|
||||
{isLoading && <CircularLoader />}
|
||||
<DialogTitle sx={{ bgcolor: theme.palette.primary.main, color: 'white' }}>
|
||||
<Stack>
|
||||
<Typography variant="h4"> {`Select Drop Customers (${dropCust?.length || 0})`}</Typography>
|
||||
<FormControl
|
||||
sx={{
|
||||
width: '100%',
|
||||
mt: 1
|
||||
}}
|
||||
>
|
||||
<Stack spacing={2} sx={{ py: 0.2 }}>
|
||||
<OutlinedInput
|
||||
fullWidth
|
||||
id="input-search-header"
|
||||
placeholder="Search"
|
||||
value={searchCustList}
|
||||
onChange={(e) => setSearchCustList(e.target.value)}
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-input': {
|
||||
p: '10.5px 0px 12px'
|
||||
},
|
||||
bgcolor: 'white'
|
||||
}}
|
||||
startAdornment={
|
||||
<InputAdornment position="start">
|
||||
<SearchOutlined style={{ fontSize: 'small' }} />
|
||||
</InputAdornment>
|
||||
}
|
||||
endAdornment={
|
||||
<IconButton
|
||||
sx={{ visibility: searchCustList ? 'visible' : 'hidden' }}
|
||||
onClick={() => {
|
||||
setSearchCustList('');
|
||||
}}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</FormControl>
|
||||
</Stack>
|
||||
</DialogTitle>
|
||||
<Divider />
|
||||
<DialogContent sx={{ p: 2.5 }}>
|
||||
{customerlist.length == 0 ? (
|
||||
<Stack spacing={2} direction={'row'} alignItems={'center'} justifyContent={'center'} sx={{ minHeight: 600, maxHeight: 600 }}>
|
||||
<Empty />
|
||||
</Stack>
|
||||
) : (
|
||||
<Stack spacing={2} sx={{ minHeight: 600, maxHeight: 600 }}>
|
||||
{customerlist &&
|
||||
customerlist.map((customer, index) => (
|
||||
<FormGroup key={index}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={dropCust?.some((cust) => cust.customerid === customer.customerid)} // Set the checked state of the checkbox based on whether the customer is in `dropCust`
|
||||
onChange={(event) => handleCheckboxChange(event, customer)}
|
||||
/>
|
||||
}
|
||||
label={
|
||||
<div style={{ width: '100%' }}>
|
||||
<Typography variant="subtitle1" sx={{ textAlign: 'left' }}>
|
||||
{`${customer.firstname} (${customer.contactno})`}
|
||||
</Typography>
|
||||
|
||||
<Typography variant="body2" color="secondary" sx={{ textAlign: 'left' }}>
|
||||
{customer.address}
|
||||
</Typography>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</FormGroup>
|
||||
))}
|
||||
</Stack>
|
||||
)}
|
||||
</DialogContent>
|
||||
<Divider />
|
||||
<DialogActions sx={{ p: 2.5 }}>
|
||||
<Button
|
||||
color={dropCust?.length !== 0 ? 'primary' : 'error'}
|
||||
variant="outlined"
|
||||
sx={{
|
||||
'&:hover': {
|
||||
bgcolor: dropCust?.length !== 0 ? theme.palette.primary.main : theme.palette.error.main,
|
||||
color: 'white'
|
||||
}
|
||||
}}
|
||||
onClick={() => {
|
||||
setIsCustomerOpen(false);
|
||||
{
|
||||
dropCust?.length !== 0 && setShowMap(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{dropCust?.length !== 0 ? 'Continue' : 'Close'}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MultipleOrders;
|
||||
@@ -1,53 +0,0 @@
|
||||
import { LoadScriptNext, GoogleMap, Marker } from '@react-google-maps/api';
|
||||
|
||||
// distance function
|
||||
function distance(lat1, lng1, lat2, lng2) {
|
||||
const R = 6371;
|
||||
const dLat = (lat2 - lat1) * (Math.PI / 180);
|
||||
const dLng = (lng2 - lng1) * (Math.PI / 180);
|
||||
|
||||
const a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1 * (Math.PI / 180)) * Math.cos(lat2 * (Math.PI / 180)) * Math.sin(dLng / 2) ** 2;
|
||||
|
||||
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
}
|
||||
|
||||
const containerStyle = {
|
||||
width: '100%',
|
||||
height: '300px'
|
||||
};
|
||||
|
||||
export default function RidersPinPoint({ pickCust, dropCust }) {
|
||||
// Ensure valid lat/lng
|
||||
const center = pickCust?.latitude && pickCust?.longitude ? { lat: Number(pickCust.latitude), lng: Number(pickCust.longitude) } : null;
|
||||
|
||||
// If center missing, don't render map
|
||||
if (!center) return null;
|
||||
|
||||
const sortedRiders = dropCust
|
||||
?.map((r) => ({
|
||||
...r,
|
||||
distance: distance(center.lat, center.lng, Number(r.latitude), Number(r.longitude))
|
||||
}))
|
||||
.sort((a, b) => a.distance - b.distance);
|
||||
|
||||
return (
|
||||
<LoadScriptNext googleMapsApiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY}>
|
||||
<GoogleMap mapContainerStyle={containerStyle} zoom={11} center={center}>
|
||||
<Marker position={center} icon={{ url: 'http://maps.google.com/mapfiles/ms/icons/purple-dot.png' }} />
|
||||
|
||||
{sortedRiders?.map((r, index) => (
|
||||
<Marker
|
||||
key={index}
|
||||
position={{ lat: Number(r.latitude), lng: Number(r.longitude) }}
|
||||
label={{
|
||||
text: (index + 1).toString(),
|
||||
color: 'white',
|
||||
fontSize: '14px',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</GoogleMap>
|
||||
</LoadScriptNext>
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,76 +1,55 @@
|
||||
import { Button } from '@mui/material';
|
||||
import { LoadScriptNext, GoogleMap, Marker, OverlayView } from '@react-google-maps/api';
|
||||
import { MapContainer, TileLayer, Marker, Tooltip } from 'react-leaflet';
|
||||
import L from 'leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
|
||||
const containerStyle = {
|
||||
width: '100%',
|
||||
height: 'calc(100vh - 150px)'
|
||||
};
|
||||
|
||||
// Green marker
|
||||
const GreenIcon = new L.Icon({
|
||||
iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png',
|
||||
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
shadowSize: [41, 41]
|
||||
});
|
||||
|
||||
// Red marker
|
||||
const RedIcon = new L.Icon({
|
||||
iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png',
|
||||
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
shadowSize: [41, 41]
|
||||
});
|
||||
|
||||
export default function RiderLocationMap({ riderLocations }) {
|
||||
console.log('riderLocations', riderLocations);
|
||||
|
||||
const center = {
|
||||
lat: Number(riderLocations?.[0]?.latitude || 11.0056),
|
||||
lng: Number(riderLocations?.[0]?.longitude || 76.9661)
|
||||
};
|
||||
const GreenIcon = {
|
||||
url: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png',
|
||||
scaledSize: new window.google.maps.Size(25, 41),
|
||||
anchor: new window.google.maps.Point(12, 41)
|
||||
};
|
||||
|
||||
const RedIcon = {
|
||||
url: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png',
|
||||
scaledSize: new window.google.maps.Size(25, 41),
|
||||
anchor: new window.google.maps.Point(12, 41)
|
||||
};
|
||||
const center = [Number(riderLocations?.[0]?.latitude || 11.0056), Number(riderLocations?.[0]?.longitude || 76.9661)];
|
||||
|
||||
return (
|
||||
<LoadScriptNext googleMapsApiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY}>
|
||||
<GoogleMap mapContainerStyle={containerStyle} zoom={12} center={center}>
|
||||
{riderLocations &&
|
||||
riderLocations?.map((r, index) => {
|
||||
const lat = Number(r.latitude);
|
||||
const lng = Number(r.longitude);
|
||||
return (
|
||||
<div key={index}>
|
||||
{/* Marker */}
|
||||
<Marker
|
||||
position={{ lat, lng }}
|
||||
icon={r.status == 'active' ? GreenIcon : RedIcon}
|
||||
label={{
|
||||
fontSize: '14px',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
/>
|
||||
<OverlayView position={{ lat, lng }} mapPaneName={OverlayView.OVERLAY_LAYER}>
|
||||
<div
|
||||
style={{
|
||||
background: 'none',
|
||||
color: 'green',
|
||||
padding: '2px 8px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '12px',
|
||||
fontWeight: 600,
|
||||
whiteSpace: 'nowrap',
|
||||
transform: 'translate(-50%, -140%)',
|
||||
pointerEvents: 'none',
|
||||
ml: 20
|
||||
}}
|
||||
>
|
||||
<Button variant="contained" color="primary" size="small">
|
||||
{` ${r.username} `}
|
||||
{/* <br /> */}
|
||||
{/* {`${r.contactno || '##### ##### '} `} */}
|
||||
<br />
|
||||
{`(${r.orderid || ''}) `}
|
||||
</Button>
|
||||
</div>
|
||||
</OverlayView>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</GoogleMap>
|
||||
</LoadScriptNext>
|
||||
<MapContainer center={center} zoom={12} style={containerStyle}>
|
||||
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" attribution="© OpenStreetMap contributors" />
|
||||
{riderLocations &&
|
||||
riderLocations.map((r, index) => {
|
||||
const lat = Number(r.latitude);
|
||||
const lng = Number(r.longitude);
|
||||
return (
|
||||
<Marker key={index} position={[lat, lng]} icon={r.status == 'active' ? GreenIcon : RedIcon}>
|
||||
<Tooltip permanent direction="top" offset={[0, -35]} opacity={1} className="rider-location-tooltip">
|
||||
<Button variant="contained" color="primary" size="small">
|
||||
{` ${r.username} `}
|
||||
<br />
|
||||
{`(${r.orderid || ''}) `}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Marker>
|
||||
);
|
||||
})}
|
||||
</MapContainer>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user