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