@nerdjs/sales-kit 4.0.53-beta.1 → 4.0.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entities/quote/quote.d.ts +1 -2
- package/dist/helpers.d.ts +0 -9
- package/dist/helpers.js +0 -54
- package/dist/helpers.js.map +1 -1
- package/dist/hooks/lep/lepLoadLocation.d.ts +6 -0
- package/dist/hooks/lep/lepLoadLocation.js +177 -207
- package/dist/hooks/lep/lepLoadLocation.js.map +1 -1
- package/dist/hooks/lep/lepShipcons.js +7 -25
- package/dist/hooks/lep/lepShipcons.js.map +1 -1
- package/dist/hooks/lep/nerdMap/nerdMap.js +40 -28
- package/dist/hooks/lep/nerdMap/nerdMap.js.map +1 -1
- package/dist/hooks/locationsForm/locationFormSales/locationFormSales.d.ts +1 -1
- package/dist/hooks/locationsForm/locationFormSales/locationFormSales.js +3 -4
- package/dist/hooks/locationsForm/locationFormSales/locationFormSales.js.map +1 -1
- package/dist/hooks/locationsForm/locationFormSales/locationFormSalesMain.d.ts +5 -0
- package/dist/hooks/locationsForm/locationFormSales/locationFormSalesMain.js +56 -173
- package/dist/hooks/locationsForm/locationFormSales/locationFormSalesMain.js.map +1 -1
- package/dist/hooks/quote/constants.js +2 -2
- package/dist/hooks/quote/constants.js.map +1 -1
- package/dist/hooks/quote/form.js +5 -16
- package/dist/hooks/quote/form.js.map +1 -1
- package/dist/hooks/quote/helpers.d.ts +0 -1
- package/dist/hooks/quote/helpers.js +330 -286
- package/dist/hooks/quote/helpers.js.map +1 -1
- package/dist/hooks/quote/result.js.map +1 -1
- package/dist/hooks/quote/template.js +2 -2
- package/dist/hooks/quote/template.js.map +1 -1
- package/dist/redux/locationV1/locationV1Endpoints.d.ts +12 -12
- package/dist/redux/quote/quoteAction.d.ts +3 -2
- package/dist/redux/quote/quoteAction.js +3 -2
- package/dist/redux/quote/quoteAction.js.map +1 -1
- package/dist/redux/quote/quoteCustomerPortalEndpoints.d.ts +1 -4
- package/dist/redux/quote/quoteCustomerPortalEndpoints.js.map +1 -1
- package/dist/redux/quote/quoteReducer.js +5 -5
- package/dist/redux/quote/quoteReducer.js.map +1 -1
- package/package.json +2 -2
|
@@ -20,7 +20,6 @@ import { LocationForm } from "../locationsForm";
|
|
|
20
20
|
import { FREIGHT_CLASS, LTL, SHIPPERS, TL } from "./constants";
|
|
21
21
|
import { LocationFormSales } from "../locationsForm/locationFormSales/locationFormSales";
|
|
22
22
|
import { unstable_debounce as debounce } from "@mui/utils";
|
|
23
|
-
import { getCacheByPlaceId, useGoogleMapsAutocompleteCache, } from "../../helpers";
|
|
24
23
|
export const getStopsColumnDef = (dispatch, stopKind, rows, customerPortal, onEditLocationClick, errors) => {
|
|
25
24
|
const date = {
|
|
26
25
|
headerName: "Date",
|
|
@@ -48,7 +47,7 @@ export const getStopsColumnDef = (dispatch, stopKind, rows, customerPortal, onEd
|
|
|
48
47
|
editable: false,
|
|
49
48
|
width: 40,
|
|
50
49
|
valueGetter: (_v, row) => {
|
|
51
|
-
return rows.findIndex((r) => r.
|
|
50
|
+
return rows.findIndex((r) => r.key === row.key) + 1;
|
|
52
51
|
},
|
|
53
52
|
renderCell: (p) => (_jsx(Avatar, { size: "sm", variant: "soft", children: p.value })),
|
|
54
53
|
},
|
|
@@ -78,36 +77,25 @@ export const getStopsColumnDef = (dispatch, stopKind, rows, customerPortal, onEd
|
|
|
78
77
|
valueSetter(value, row) {
|
|
79
78
|
if (value && typeof value != "string")
|
|
80
79
|
if (typeof value != "number")
|
|
81
|
-
if (locationEntityTypeGuard(value))
|
|
82
|
-
console.warn(value);
|
|
80
|
+
if (locationEntityTypeGuard(value))
|
|
83
81
|
return {
|
|
84
82
|
...row,
|
|
85
83
|
locationId: value.id,
|
|
86
84
|
zip: value.address.zip,
|
|
87
|
-
placeId: undefined,
|
|
88
85
|
};
|
|
89
|
-
|
|
90
|
-
else {
|
|
91
|
-
console.warn(value, "2");
|
|
86
|
+
else
|
|
92
87
|
return {
|
|
93
88
|
...row,
|
|
94
89
|
locationId: value.id,
|
|
95
90
|
zip: value.zip,
|
|
96
|
-
placeId: undefined,
|
|
97
91
|
};
|
|
98
|
-
|
|
99
|
-
else {
|
|
100
|
-
console.warn(value, "HOHO");
|
|
92
|
+
else
|
|
101
93
|
return {
|
|
102
94
|
...row,
|
|
103
95
|
locationId: value,
|
|
104
|
-
placeId: undefined,
|
|
105
96
|
};
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
console.warn(value, "HAHA");
|
|
109
|
-
return { ...row, locationId: undefined, placeId: undefined };
|
|
110
|
-
}
|
|
97
|
+
else
|
|
98
|
+
return { ...row, locationId: undefined };
|
|
111
99
|
},
|
|
112
100
|
},
|
|
113
101
|
{
|
|
@@ -132,7 +120,7 @@ export const getStopsColumnDef = (dispatch, stopKind, rows, customerPortal, onEd
|
|
|
132
120
|
getActions: (p) => [
|
|
133
121
|
_jsx(GridActionsCellItem, { icon: _jsx("i", { style: { fontSize: 14 }, className: "fa-sharp fa-solid fa-trash" }), label: `Delete`, onClick: (e) => {
|
|
134
122
|
e.stopPropagation();
|
|
135
|
-
dispatch(removeStop(p.row.
|
|
123
|
+
dispatch(removeStop(p.row.key));
|
|
136
124
|
}, color: "inherit" }, "delete"),
|
|
137
125
|
],
|
|
138
126
|
},
|
|
@@ -287,153 +275,144 @@ export const getPalletsColumnDef = (deleteAction, customerPortal, perPalletClass
|
|
|
287
275
|
});
|
|
288
276
|
return ret;
|
|
289
277
|
};
|
|
290
|
-
const ZipCodeRenderCell = ({ value, errors,
|
|
291
|
-
const
|
|
292
|
-
const
|
|
278
|
+
const ZipCodeRenderCell = ({ value, errors, }) => {
|
|
279
|
+
const fetchAutocompleteSuggestions = google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions;
|
|
280
|
+
const [googleMapsPredictions, setGoogleMapsPredictions] = useState([]);
|
|
293
281
|
useEffect(() => {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
if (!row.placeId)
|
|
299
|
-
getSuggestions({
|
|
282
|
+
if (value) {
|
|
283
|
+
fetchAutocompleteSuggestions({
|
|
300
284
|
input: value,
|
|
301
|
-
includedPrimaryTypes: ["(regions)"],
|
|
302
285
|
includedRegionCodes: ["US"],
|
|
286
|
+
includedPrimaryTypes: ["(regions)"],
|
|
303
287
|
language: "en-US",
|
|
304
288
|
region: "us",
|
|
305
|
-
}).then((suggestions) => {
|
|
306
|
-
|
|
307
|
-
return;
|
|
308
|
-
const text = suggestions[0].placePrediction?.text?.text || value;
|
|
309
|
-
apiRef.current.updateRows([
|
|
310
|
-
{
|
|
311
|
-
id: id,
|
|
312
|
-
zip: text,
|
|
313
|
-
placeId: suggestions[0].placePrediction?.placeId || undefined,
|
|
314
|
-
},
|
|
315
|
-
]);
|
|
289
|
+
}).then(({ suggestions }) => {
|
|
290
|
+
setGoogleMapsPredictions(suggestions);
|
|
316
291
|
});
|
|
317
|
-
|
|
318
|
-
active = false;
|
|
319
|
-
};
|
|
292
|
+
}
|
|
320
293
|
}, [value]);
|
|
321
294
|
return (_jsx(Box, { width: "100%", children: value ? (_jsx(Typography, { level: "body-sm", sx: {
|
|
322
295
|
display: "inline",
|
|
323
|
-
opacity: errors ? 1 : 0.5,
|
|
324
|
-
color: (theme) =>
|
|
325
|
-
}, children:
|
|
296
|
+
opacity: value || errors ? 1 : 0.5,
|
|
297
|
+
color: (theme) => errors && !value ? theme.palette.danger[500] : undefined,
|
|
298
|
+
}, children: googleMapsPredictions?.[0]
|
|
299
|
+
? googleMapsPredictions[0].placePrediction?.text.text || ""
|
|
300
|
+
: value })) : (_jsxs(_Fragment, { children: [_jsx(Typography, { display: "inline", level: "body-sm", sx: {
|
|
301
|
+
opacity: value || errors ? 1 : 0.5,
|
|
302
|
+
color: (theme) => errors && !value ? theme.palette.danger[500] : undefined,
|
|
303
|
+
}, children: "Enter zip or city, state... " }), _jsx(Typography, { display: "inline", color: "danger", children: "*" })] })) }));
|
|
326
304
|
};
|
|
327
|
-
|
|
305
|
+
const ZipCodeRenderEditCell = ({ value: _value, id, field, hasFocus, }) => {
|
|
328
306
|
const apiRef = useGridApiContext();
|
|
307
|
+
const [googleMapsPredictions, setGoogleMapsPredictions] = useState([]);
|
|
308
|
+
const fetchAutocompleteSuggestions = google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions;
|
|
329
309
|
const ref = useRef(null);
|
|
330
|
-
const { getSuggestions } = useGoogleMapsAutocompleteCache();
|
|
331
|
-
const [options, setOptions] = useState([]);
|
|
332
|
-
const [inputValue, setInputValue] = useState("");
|
|
333
310
|
const [open, setOpen] = useState(false);
|
|
311
|
+
const [value, setValue] = useState(null);
|
|
334
312
|
useLayoutEffect(() => {
|
|
335
|
-
if (hasFocus)
|
|
313
|
+
if (hasFocus) {
|
|
336
314
|
ref.current?.focus();
|
|
315
|
+
}
|
|
337
316
|
}, [hasFocus]);
|
|
338
317
|
useEffect(() => {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
setInputValue(initialValue);
|
|
359
|
-
});
|
|
360
|
-
return () => {
|
|
361
|
-
active = false;
|
|
362
|
-
};
|
|
318
|
+
if (_value)
|
|
319
|
+
fetchAutocompleteSuggestions({
|
|
320
|
+
input: _value,
|
|
321
|
+
includedPrimaryTypes: ["(regions)"],
|
|
322
|
+
language: "en-US",
|
|
323
|
+
region: "us",
|
|
324
|
+
includedRegionCodes: ["US"],
|
|
325
|
+
}).then(async ({ suggestions }) => {
|
|
326
|
+
const result = suggestions[0];
|
|
327
|
+
if (result) {
|
|
328
|
+
if (result.placePrediction?.text.text) {
|
|
329
|
+
setValue(result.placePrediction?.text.text);
|
|
330
|
+
}
|
|
331
|
+
else
|
|
332
|
+
setValue(_value);
|
|
333
|
+
}
|
|
334
|
+
else
|
|
335
|
+
setValue(_value);
|
|
336
|
+
});
|
|
363
337
|
}, []);
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
338
|
+
const handleValueChange = async (_, newValue) => {
|
|
339
|
+
setValue(newValue);
|
|
340
|
+
if (typeof newValue != "string" && newValue != null) {
|
|
341
|
+
if (newValue.placePrediction?.text.text) {
|
|
342
|
+
const _place = newValue.placePrediction.toPlace();
|
|
343
|
+
if (_place) {
|
|
344
|
+
const place = (await _place.fetchFields({ fields: ["addressComponents"] })).place;
|
|
345
|
+
const mainText = place.addressComponents?.[0]?.longText;
|
|
346
|
+
let _value = mainText;
|
|
347
|
+
if (Number.isNaN(Number(mainText)) &&
|
|
348
|
+
place.addressComponents?.[2]?.shortText) {
|
|
349
|
+
_value =
|
|
350
|
+
place.addressComponents?.[0]?.longText +
|
|
351
|
+
", " +
|
|
352
|
+
place.addressComponents?.[2]?.shortText;
|
|
353
|
+
}
|
|
354
|
+
apiRef.current?.setEditCellValue({
|
|
355
|
+
id,
|
|
356
|
+
field,
|
|
357
|
+
value: _value,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
386
361
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
placeId: undefined,
|
|
394
|
-
},
|
|
395
|
-
]);
|
|
396
|
-
return;
|
|
362
|
+
else {
|
|
363
|
+
apiRef.current?.setEditCellValue({
|
|
364
|
+
id,
|
|
365
|
+
field,
|
|
366
|
+
value: newValue,
|
|
367
|
+
});
|
|
397
368
|
}
|
|
398
|
-
const place = newValue.placePrediction?.toPlace();
|
|
399
|
-
if (!place)
|
|
400
|
-
return;
|
|
401
|
-
const result = await place.fetchFields({
|
|
402
|
-
fields: ["addressComponents"],
|
|
403
|
-
});
|
|
404
|
-
const components = result.place.addressComponents || [];
|
|
405
|
-
const city = components.find((c) => c.types.includes("locality"))?.longText ||
|
|
406
|
-
components.find((c) => c.types.includes("postal_town"))?.longText ||
|
|
407
|
-
components.find((c) => c.types.includes("administrative_area_level_2"))
|
|
408
|
-
?.longText ||
|
|
409
|
-
"";
|
|
410
|
-
const state = components.find((c) => c.types.includes("administrative_area_level_1"))
|
|
411
|
-
?.shortText || "";
|
|
412
|
-
const zip = components.find((c) => c.types.includes("postal_code"))?.longText || "";
|
|
413
|
-
const main = city || zip;
|
|
414
|
-
const finalValue = main && state ? `${main}, ${state}` : main || state || "";
|
|
415
|
-
setInputValue(finalValue);
|
|
416
|
-
apiRef.current.updateRows([
|
|
417
|
-
{
|
|
418
|
-
id: id,
|
|
419
|
-
zip: finalValue,
|
|
420
|
-
placeId: newValue.placePrediction?.placeId || undefined,
|
|
421
|
-
},
|
|
422
|
-
]);
|
|
423
369
|
};
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
370
|
+
const getGoogleAddresses = async (_event, value) => {
|
|
371
|
+
if (value) {
|
|
372
|
+
const { suggestions } = await fetchAutocompleteSuggestions({
|
|
373
|
+
input: value,
|
|
374
|
+
includedRegionCodes: ["US"],
|
|
375
|
+
includedPrimaryTypes: ["(regions)"],
|
|
376
|
+
language: "en-US",
|
|
377
|
+
region: "us",
|
|
378
|
+
});
|
|
379
|
+
setGoogleMapsPredictions(suggestions);
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
const debouncedChangeHandler = useMemo(() => debounce(getGoogleAddresses, 300), []);
|
|
383
|
+
return (_jsx(Autocomplete, { fullWidth: true, sx: {
|
|
384
|
+
"& fieldset": {
|
|
385
|
+
borderWidth: "0px !important",
|
|
386
|
+
},
|
|
387
|
+
}, onClose: () => {
|
|
388
|
+
setOpen(false);
|
|
389
|
+
}, options: googleMapsPredictions || [], open: open, onOpen: () => setOpen(true), value: value || "", freeSolo: true, onChange: handleValueChange, onKeyDown: (e) => {
|
|
390
|
+
if (e.key === "Enter" && open) {
|
|
391
|
+
e.stopPropagation();
|
|
392
|
+
setOpen(false);
|
|
393
|
+
}
|
|
394
|
+
}, onInputChange: (e, v) => {
|
|
395
|
+
debouncedChangeHandler(e, v);
|
|
396
|
+
apiRef.current?.setEditCellValue({
|
|
432
397
|
id,
|
|
433
398
|
field,
|
|
434
399
|
value: v,
|
|
435
400
|
});
|
|
436
|
-
},
|
|
401
|
+
}, getOptionLabel: (option) => {
|
|
402
|
+
if (typeof option != "string") {
|
|
403
|
+
return option.placePrediction?.text.text || "";
|
|
404
|
+
}
|
|
405
|
+
else
|
|
406
|
+
return option;
|
|
407
|
+
}, filterOptions: (x) => x, renderInput: (params) => (_jsx(TextField, { tabIndex: 0, ...params, placeholder: "Enter zip or city, state...", autoFocus: apiRef.current?.getRowMode(id) === "edit" ? false : true, inputRef: ref, InputProps: {
|
|
408
|
+
...params.InputProps,
|
|
409
|
+
tabIndex: 0,
|
|
410
|
+
onKeyDown: (e) => {
|
|
411
|
+
if (e.key === "Tab") {
|
|
412
|
+
e.stopPropagation();
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
} })), renderOption: (props, c) => (_jsx(LocationOption, { cellInput: true, props: props, c: c }, locationEntityTypeGuard(c) ? c.id : c.placePrediction?.placeId)) }));
|
|
437
416
|
};
|
|
438
417
|
const NumberEditCell = ({ id, value, field }) => {
|
|
439
418
|
const apiRef = useGridApiContext();
|
|
@@ -693,126 +672,152 @@ export function AccessorialInput({ accessorialIDs: _accessorialIDs, onChange, })
|
|
|
693
672
|
* @returns {ReactElement} The autocomplete
|
|
694
673
|
*/
|
|
695
674
|
export function LocationInputCell(props) {
|
|
696
|
-
const { id, field, hasFocus, onEditLocationClick, customerPortal } = props;
|
|
675
|
+
const { id, value, field, hasFocus, onEditLocationClick, customerPortal } = props;
|
|
697
676
|
const apiRef = useGridApiContext();
|
|
698
677
|
const [openDialog, setOpenDialog] = useState(false);
|
|
699
678
|
const [locationInputValue, setLocationInputValue] = useState("");
|
|
700
|
-
const [open, setOpen] = useState(false);
|
|
701
679
|
const [searchExistingLocation, { data: existingLocations }] = useLazySearchExistingLocationQuery();
|
|
702
680
|
const [searchLocation, { data: locationSuggestions }] = useLazySearchLocationQuery();
|
|
681
|
+
const [bounds, setBounds] = useState();
|
|
703
682
|
const [googleMapsPredictions, setGoogleMapsPredictions] = useState([]);
|
|
704
683
|
const fetchAutocompleteSuggestions = google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions;
|
|
705
684
|
const googleMapsGeocoder = new google.maps.Geocoder();
|
|
706
685
|
const [getLocation, { data: location }] = useLazyGetLocationQuery();
|
|
707
|
-
const [bounds, setBounds] = useState();
|
|
708
686
|
const ref = useRef(null);
|
|
709
|
-
const
|
|
710
|
-
const z = props.row.zip || props.row.quoteZip || "";
|
|
711
|
-
return [...z.matchAll(/\d/g)].map((m) => m[0]).join("") || z;
|
|
712
|
-
}, [props.row.zip, props.row.quoteZip]);
|
|
687
|
+
const [open, setOpen] = useState(false);
|
|
713
688
|
useLayoutEffect(() => {
|
|
714
|
-
if (hasFocus)
|
|
689
|
+
if (hasFocus) {
|
|
715
690
|
ref.current?.focus();
|
|
691
|
+
}
|
|
716
692
|
}, [hasFocus]);
|
|
717
693
|
useEffect(() => {
|
|
718
|
-
const
|
|
719
|
-
if (
|
|
720
|
-
getLocation(
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
694
|
+
const id = Number(value);
|
|
695
|
+
if (id) {
|
|
696
|
+
getLocation(id, true);
|
|
697
|
+
}
|
|
698
|
+
}, [value]);
|
|
699
|
+
useEffect(() => {
|
|
700
|
+
if (props.row.zip || props.row.quoteZip) {
|
|
701
|
+
findBounds();
|
|
702
|
+
}
|
|
703
|
+
}, [props.row]);
|
|
704
|
+
const handleValueChange = async (_, newValue) => {
|
|
705
|
+
if (typeof newValue != "string") {
|
|
706
|
+
if (newValue && locationEntityTypeGuard(newValue)) {
|
|
707
|
+
apiRef.current?.setEditCellValue({
|
|
708
|
+
id,
|
|
709
|
+
field,
|
|
710
|
+
value: newValue,
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
else if (newValue) {
|
|
714
|
+
const place = newValue.placePrediction?.toPlace();
|
|
715
|
+
await place?.fetchFields({
|
|
716
|
+
fields: ["formattedAddress"],
|
|
717
|
+
});
|
|
718
|
+
if (place && place.formattedAddress) {
|
|
719
|
+
try {
|
|
720
|
+
const existingLocations = await searchExistingLocation(place.formattedAddress).unwrap();
|
|
721
|
+
if (existingLocations.length > 0)
|
|
722
|
+
setOpenDialog(true);
|
|
723
|
+
else {
|
|
724
|
+
onEditLocationClick(place, id, field);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
catch {
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
else {
|
|
733
|
+
apiRef.current?.setEditCellValue({
|
|
734
|
+
id,
|
|
735
|
+
field,
|
|
736
|
+
value: newValue,
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
const findBounds = () => {
|
|
725
742
|
googleMapsGeocoder.geocode({
|
|
726
|
-
address: zip,
|
|
743
|
+
address: props.row.zip || props.row.quoteZip,
|
|
727
744
|
componentRestrictions: { country: "US" },
|
|
728
745
|
language: "en-US",
|
|
729
746
|
}, (results, status) => {
|
|
730
|
-
if (status === google.maps.GeocoderStatus.OK && results
|
|
731
|
-
const result = results.find((r) => r.address_components
|
|
732
|
-
|
|
747
|
+
if (status === google.maps.GeocoderStatus.OK && results != undefined) {
|
|
748
|
+
const result = results.find((r) => r.address_components.find((a) => a.types.includes("country"))
|
|
749
|
+
?.short_name === "US") || results[0];
|
|
750
|
+
const lat = result.geometry.location.lat();
|
|
751
|
+
const lng = result.geometry.location.lng();
|
|
752
|
+
const center = new google.maps.LatLng(lat, lng);
|
|
733
753
|
const circle = new google.maps.Circle({
|
|
734
|
-
center,
|
|
754
|
+
center: center,
|
|
735
755
|
radius: 10000,
|
|
736
756
|
});
|
|
737
757
|
const bounds = circle.getBounds() || undefined;
|
|
738
758
|
setBounds(bounds);
|
|
739
759
|
}
|
|
740
760
|
});
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
if (
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
const { suggestions } = await fetchAutocompleteSuggestions({
|
|
751
|
-
input: searchText,
|
|
752
|
-
locationBias: bounds,
|
|
753
|
-
language: "en-US",
|
|
754
|
-
region: "us",
|
|
755
|
-
includedRegionCodes: ["US"],
|
|
756
|
-
});
|
|
757
|
-
setGoogleMapsPredictions(suggestions || []);
|
|
758
|
-
}, [bounds]);
|
|
759
|
-
const debouncedSearch = useMemo(() => debounce((value) => {
|
|
760
|
-
searchLocation({
|
|
761
|
-
zip,
|
|
762
|
-
location: value,
|
|
763
|
-
});
|
|
764
|
-
getGoogleAddresses(value);
|
|
765
|
-
}, 400), [zip, bounds, searchLocation, getGoogleAddresses]);
|
|
766
|
-
const handleValueChange = async (_, newValue) => {
|
|
767
|
-
if (!newValue || typeof newValue === "string") {
|
|
768
|
-
apiRef.current?.setEditCellValue({ id, field, value: undefined });
|
|
769
|
-
return;
|
|
770
|
-
}
|
|
771
|
-
if (locationEntityTypeGuard(newValue)) {
|
|
772
|
-
console.warn(newValue);
|
|
773
|
-
apiRef.current?.setEditCellValue({
|
|
774
|
-
id,
|
|
775
|
-
field,
|
|
776
|
-
value: newValue,
|
|
761
|
+
};
|
|
762
|
+
const getGoogleAddresses = async (searchText) => {
|
|
763
|
+
if (searchText) {
|
|
764
|
+
const { suggestions } = await fetchAutocompleteSuggestions({
|
|
765
|
+
input: searchText,
|
|
766
|
+
locationBias: bounds,
|
|
767
|
+
language: "en-US",
|
|
768
|
+
region: "us",
|
|
769
|
+
includedRegionCodes: ["US"],
|
|
777
770
|
});
|
|
778
|
-
|
|
779
|
-
}
|
|
780
|
-
const place = newValue.placePrediction?.toPlace();
|
|
781
|
-
await place?.fetchFields({ fields: ["formattedAddress"] });
|
|
782
|
-
if (!place?.formattedAddress)
|
|
783
|
-
return;
|
|
784
|
-
try {
|
|
785
|
-
const existing = await searchExistingLocation(place.formattedAddress).unwrap();
|
|
786
|
-
if (existing.length > 0) {
|
|
787
|
-
setOpenDialog(true);
|
|
788
|
-
}
|
|
789
|
-
else {
|
|
790
|
-
onEditLocationClick(place, id, field);
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
catch {
|
|
794
|
-
return;
|
|
771
|
+
setGoogleMapsPredictions(suggestions);
|
|
795
772
|
}
|
|
796
773
|
};
|
|
774
|
+
const onInputChange = useCallback((e) => {
|
|
775
|
+
const zip = props.row.zip || props.row.quoteZip || "";
|
|
776
|
+
const _zip = [...zip.matchAll(/\d/g)].map((m) => m[0]).join("");
|
|
777
|
+
searchLocation({
|
|
778
|
+
zip: _zip ? _zip : zip,
|
|
779
|
+
location: e.target.value,
|
|
780
|
+
});
|
|
781
|
+
getGoogleAddresses(e.target.value);
|
|
782
|
+
}, [props.row]);
|
|
783
|
+
const debouncedChangeHandler = useMemo(() => debounce(onInputChange, 500), []);
|
|
797
784
|
return (_jsxs(_Fragment, { children: [_jsx(Autocomplete, { fullWidth: true, sx: {
|
|
798
|
-
"& fieldset": {
|
|
785
|
+
"& fieldset": {
|
|
786
|
+
borderWidth: "0px !important",
|
|
787
|
+
},
|
|
799
788
|
}, options: [
|
|
800
789
|
...(locationSuggestions ?? []),
|
|
801
790
|
...(googleMapsPredictions ?? []),
|
|
802
|
-
], open: open,
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
},
|
|
791
|
+
], open: open, onClose: () => {
|
|
792
|
+
setOpen(false);
|
|
793
|
+
}, onOpen: () => setOpen(true), value: location || "", onChange: handleValueChange, inputValue: locationInputValue, onKeyDown: (e) => {
|
|
794
|
+
if (e.key === "Enter" && open) {
|
|
795
|
+
e.stopPropagation();
|
|
796
|
+
setOpen(false);
|
|
797
|
+
}
|
|
798
|
+
}, freeSolo: true, onInputChange: (_e, v) => setLocationInputValue(v), getOptionLabel: (option) => {
|
|
799
|
+
if (typeof option != "string") {
|
|
800
|
+
if (locationEntityTypeGuard(option)) {
|
|
801
|
+
return option.name;
|
|
802
|
+
}
|
|
803
|
+
return option.placePrediction?.mainText?.text || "";
|
|
804
|
+
}
|
|
805
|
+
else
|
|
806
|
+
return option;
|
|
807
|
+
}, filterOptions: (x) => x, renderInput: (params) => (_jsx(TextField, { tabIndex: 0, variant: "outlined", ...params, size: "small", placeholder: "Pick a location...", autoFocus: apiRef.current?.getRowMode(id) === "edit" ? false : true, onChange: (e) => {
|
|
808
|
+
debouncedChangeHandler(e);
|
|
809
|
+
}, inputRef: ref, InputProps: {
|
|
810
|
+
...params.InputProps,
|
|
811
|
+
tabIndex: 0,
|
|
812
|
+
} })), renderOption: (props, c) => (_jsx(LocationOption, { cellInput: true, props: props, c: c }, locationEntityTypeGuard(c) ? c.id : c.placePrediction?.placeId)) }), _jsx(ExistingLocations, { updateCell: (value) => {
|
|
810
813
|
apiRef.current?.setEditCellValue({
|
|
811
814
|
id,
|
|
812
815
|
field,
|
|
813
|
-
value,
|
|
816
|
+
value: value,
|
|
814
817
|
});
|
|
815
|
-
}, existingLocations: existingLocations, close: () =>
|
|
818
|
+
}, existingLocations: existingLocations, close: () => {
|
|
819
|
+
setOpenDialog(false);
|
|
820
|
+
}, open: openDialog, openLocationForm: (place) => onEditLocationClick(place, id, field), customerPortal: customerPortal })] }));
|
|
816
821
|
}
|
|
817
822
|
export const LocationInput = ({ zip, locationID, onChange, customerPortal, autoCompleteProps, }) => {
|
|
818
823
|
const [locationFormOpen, setLocationFormOpen] = useState({
|
|
@@ -820,92 +825,131 @@ export const LocationInput = ({ zip, locationID, onChange, customerPortal, autoC
|
|
|
820
825
|
place: undefined,
|
|
821
826
|
});
|
|
822
827
|
const [openDialog, setOpenDialog] = useState(false);
|
|
823
|
-
const [
|
|
824
|
-
const [googleMapsPredictions, setGoogleMapsPredictions] = useState([]);
|
|
825
|
-
const googleMapsGeocoder = new google.maps.Geocoder();
|
|
826
|
-
const [bounds, setBounds] = useState();
|
|
828
|
+
const [locationInputValue, setLocationInputValue] = useState("");
|
|
827
829
|
const [searchExistingLocation, { data: existingLocations }] = useLazySearchExistingLocationQuery();
|
|
828
830
|
const [searchLocation, { data: locationSuggestions }] = useLazySearchLocationQuery();
|
|
831
|
+
const [bounds, setBounds] = useState();
|
|
832
|
+
const [googleMapsPredictions, setGoogleMapsPredictions] = useState([]);
|
|
833
|
+
const fetchAutocompleteSuggestions = google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions;
|
|
834
|
+
const googleMapsGeocoder = new google.maps.Geocoder();
|
|
829
835
|
const [getLocation] = useLazyGetLocationQuery();
|
|
830
836
|
const [location, setLocation] = useState();
|
|
831
|
-
const { getSuggestions } = useGoogleMapsAutocompleteCache();
|
|
832
837
|
useEffect(() => {
|
|
833
838
|
if (locationID) {
|
|
834
839
|
getLocation(locationID, true)
|
|
835
840
|
.unwrap()
|
|
836
|
-
.then(setLocation)
|
|
841
|
+
.then((d) => setLocation(d))
|
|
837
842
|
.catch(() => undefined);
|
|
838
843
|
}
|
|
839
|
-
else
|
|
844
|
+
else
|
|
840
845
|
setLocation(undefined);
|
|
841
|
-
}
|
|
842
846
|
}, [locationID]);
|
|
843
847
|
useEffect(() => {
|
|
844
|
-
if (
|
|
845
|
-
|
|
848
|
+
if (zip) {
|
|
849
|
+
findBounds();
|
|
850
|
+
}
|
|
851
|
+
}, [zip]);
|
|
852
|
+
const handleValueChange = async (_, newValue) => {
|
|
853
|
+
if (typeof newValue != "string")
|
|
854
|
+
if (newValue && locationEntityTypeGuard(newValue)) {
|
|
855
|
+
onChange(newValue);
|
|
856
|
+
}
|
|
857
|
+
else if (newValue) {
|
|
858
|
+
const place = newValue.placePrediction?.toPlace();
|
|
859
|
+
await place?.fetchFields({
|
|
860
|
+
fields: ["formattedAddress"],
|
|
861
|
+
});
|
|
862
|
+
if (place && place.formattedAddress) {
|
|
863
|
+
try {
|
|
864
|
+
const existingLocations = await searchExistingLocation(place?.formattedAddress).unwrap();
|
|
865
|
+
if (existingLocations.length > 0)
|
|
866
|
+
setOpenDialog(true);
|
|
867
|
+
else {
|
|
868
|
+
setLocationFormOpen({ open: true, place: place });
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
catch {
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
else {
|
|
877
|
+
onChange(newValue);
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
const findBounds = () => {
|
|
846
881
|
googleMapsGeocoder.geocode({
|
|
847
882
|
address: zip,
|
|
848
883
|
componentRestrictions: { country: "US" },
|
|
884
|
+
language: "en",
|
|
849
885
|
}, (results, status) => {
|
|
850
|
-
if (status === google.maps.GeocoderStatus.OK && results
|
|
851
|
-
const
|
|
886
|
+
if (status === google.maps.GeocoderStatus.OK && results != undefined) {
|
|
887
|
+
const result = results[0];
|
|
888
|
+
const lat = result.geometry.location.lat();
|
|
889
|
+
const lng = result.geometry.location.lng();
|
|
890
|
+
const center = new google.maps.LatLng(lat, lng);
|
|
852
891
|
const circle = new google.maps.Circle({
|
|
853
|
-
center:
|
|
892
|
+
center: center,
|
|
854
893
|
radius: 10000,
|
|
855
894
|
});
|
|
856
|
-
|
|
895
|
+
const bounds = circle.getBounds() || undefined;
|
|
896
|
+
setBounds(bounds);
|
|
857
897
|
}
|
|
858
898
|
});
|
|
859
|
-
}
|
|
860
|
-
const
|
|
861
|
-
if (
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
return;
|
|
869
|
-
}
|
|
870
|
-
const place = newValue.placePrediction?.toPlace();
|
|
871
|
-
if (!place)
|
|
872
|
-
return;
|
|
873
|
-
const result = await place.fetchFields({
|
|
874
|
-
fields: ["formattedAddress"],
|
|
899
|
+
};
|
|
900
|
+
const getGoogleAddresses = async (searchText) => {
|
|
901
|
+
if (searchText) {
|
|
902
|
+
const { suggestions } = await fetchAutocompleteSuggestions({
|
|
903
|
+
input: searchText,
|
|
904
|
+
locationBias: bounds,
|
|
905
|
+
language: "en-US",
|
|
906
|
+
region: "us",
|
|
907
|
+
includedRegionCodes: ["US"],
|
|
875
908
|
});
|
|
876
|
-
|
|
877
|
-
if (!formatted)
|
|
878
|
-
return;
|
|
879
|
-
const existing = await searchExistingLocation(formatted).unwrap();
|
|
880
|
-
if (existing.length > 0) {
|
|
881
|
-
setOpenDialog(true);
|
|
882
|
-
return;
|
|
883
|
-
}
|
|
884
|
-
setLocationFormOpen({ open: true, place });
|
|
909
|
+
setGoogleMapsPredictions(suggestions);
|
|
885
910
|
}
|
|
886
911
|
};
|
|
887
|
-
const
|
|
888
|
-
searchLocation({ zip, location: v });
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
912
|
+
const onInputChange = useCallback((v) => {
|
|
913
|
+
searchLocation({ zip: zip, location: v });
|
|
914
|
+
getGoogleAddresses(v);
|
|
915
|
+
}, [zip]);
|
|
916
|
+
const debouncedChangeHandler = useMemo(() => debounce(onInputChange, 500), []);
|
|
917
|
+
return (_jsxs(_Fragment, { children: [_jsxs(FormControl, { children: [_jsx(FormLabel, { children: "Pick a location..." }), _jsx(JoyAutocomplete, { size: "sm", ...autoCompleteProps, slotProps: {
|
|
918
|
+
listbox: {
|
|
919
|
+
sx: {
|
|
920
|
+
zIndex: (theme) => theme.zIndex.modal,
|
|
921
|
+
},
|
|
922
|
+
},
|
|
923
|
+
}, options: [
|
|
924
|
+
...(locationSuggestions ?? []),
|
|
925
|
+
...(googleMapsPredictions ?? []),
|
|
926
|
+
], filterOptions: (x) => x, value: location || "", onChange: handleValueChange, inputValue: locationInputValue, freeSolo: true, onInputChange: (_e, v) => {
|
|
927
|
+
setLocationInputValue(v);
|
|
928
|
+
debouncedChangeHandler(v);
|
|
929
|
+
}, getOptionLabel: (option) => {
|
|
930
|
+
if (typeof option != "string") {
|
|
931
|
+
if (locationEntityTypeGuard(option)) {
|
|
932
|
+
return option.name;
|
|
933
|
+
}
|
|
934
|
+
return option.placePrediction?.mainText?.text || "";
|
|
935
|
+
}
|
|
936
|
+
else
|
|
937
|
+
return option;
|
|
938
|
+
}, endDecorator: _jsx(IconButton, { sx: {
|
|
939
|
+
display: location ? "inherit" : "none",
|
|
940
|
+
}, size: "small", onClick: () => {
|
|
941
|
+
setLocationFormOpen({ open: true, place: location });
|
|
942
|
+
}, children: _jsx("i", { className: "fa-solid fa-pen-to-square" }) }), renderOption: (props, c) => typeof c !== "string" ? (_jsx(LocationOption, { props: props, c: c, cellInput: false }, locationEntityTypeGuard(c) ? c.id : c.placePrediction?.placeId)) : (c) })] }), customerPortal ? (_jsx(LocationForm, { open: locationFormOpen.open, onClose: () => setLocationFormOpen({ open: false, place: undefined }), place: locationFormOpen.place, onConfirm: (value) => {
|
|
943
|
+
onChange(value);
|
|
944
|
+
} })) : (_jsx(LocationFormSales, { onClose: () => setLocationFormOpen({ open: false, place: undefined }), open: locationFormOpen.open, place: locationFormOpen.place, onCreateLocation: (value) => {
|
|
945
|
+
onChange(value);
|
|
946
|
+
}, onSaveLocation: (value) => {
|
|
947
|
+
onChange(value);
|
|
948
|
+
} })), _jsx(ExistingLocations, { updateCell: (value) => {
|
|
949
|
+
onChange(value);
|
|
950
|
+
}, existingLocations: existingLocations, close: () => {
|
|
951
|
+
setOpenDialog(false);
|
|
952
|
+
}, open: openDialog, openLocationForm: (place, open) => setLocationFormOpen({ open, place }), customerPortal: customerPortal })] }));
|
|
909
953
|
};
|
|
910
954
|
/**
|
|
911
955
|
*
|