@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.
Files changed (36) hide show
  1. package/dist/entities/quote/quote.d.ts +1 -2
  2. package/dist/helpers.d.ts +0 -9
  3. package/dist/helpers.js +0 -54
  4. package/dist/helpers.js.map +1 -1
  5. package/dist/hooks/lep/lepLoadLocation.d.ts +6 -0
  6. package/dist/hooks/lep/lepLoadLocation.js +177 -207
  7. package/dist/hooks/lep/lepLoadLocation.js.map +1 -1
  8. package/dist/hooks/lep/lepShipcons.js +7 -25
  9. package/dist/hooks/lep/lepShipcons.js.map +1 -1
  10. package/dist/hooks/lep/nerdMap/nerdMap.js +40 -28
  11. package/dist/hooks/lep/nerdMap/nerdMap.js.map +1 -1
  12. package/dist/hooks/locationsForm/locationFormSales/locationFormSales.d.ts +1 -1
  13. package/dist/hooks/locationsForm/locationFormSales/locationFormSales.js +3 -4
  14. package/dist/hooks/locationsForm/locationFormSales/locationFormSales.js.map +1 -1
  15. package/dist/hooks/locationsForm/locationFormSales/locationFormSalesMain.d.ts +5 -0
  16. package/dist/hooks/locationsForm/locationFormSales/locationFormSalesMain.js +56 -173
  17. package/dist/hooks/locationsForm/locationFormSales/locationFormSalesMain.js.map +1 -1
  18. package/dist/hooks/quote/constants.js +2 -2
  19. package/dist/hooks/quote/constants.js.map +1 -1
  20. package/dist/hooks/quote/form.js +5 -16
  21. package/dist/hooks/quote/form.js.map +1 -1
  22. package/dist/hooks/quote/helpers.d.ts +0 -1
  23. package/dist/hooks/quote/helpers.js +330 -286
  24. package/dist/hooks/quote/helpers.js.map +1 -1
  25. package/dist/hooks/quote/result.js.map +1 -1
  26. package/dist/hooks/quote/template.js +2 -2
  27. package/dist/hooks/quote/template.js.map +1 -1
  28. package/dist/redux/locationV1/locationV1Endpoints.d.ts +12 -12
  29. package/dist/redux/quote/quoteAction.d.ts +3 -2
  30. package/dist/redux/quote/quoteAction.js +3 -2
  31. package/dist/redux/quote/quoteAction.js.map +1 -1
  32. package/dist/redux/quote/quoteCustomerPortalEndpoints.d.ts +1 -4
  33. package/dist/redux/quote/quoteCustomerPortalEndpoints.js.map +1 -1
  34. package/dist/redux/quote/quoteReducer.js +5 -5
  35. package/dist/redux/quote/quoteReducer.js.map +1 -1
  36. 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.id === row.id) + 1;
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
- else {
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.id));
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, row, id, }) => {
291
- const apiRef = useGridApiContext();
292
- const { getSuggestions } = useGoogleMapsAutocompleteCache();
278
+ const ZipCodeRenderCell = ({ value, errors, }) => {
279
+ const fetchAutocompleteSuggestions = google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions;
280
+ const [googleMapsPredictions, setGoogleMapsPredictions] = useState([]);
293
281
  useEffect(() => {
294
- let active = true;
295
- if (!value) {
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
- if (!active || !suggestions?.[0])
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
- return () => {
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) => (errors ? theme.palette.danger[500] : undefined),
325
- }, 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: "*" })] })) }));
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
- export const ZipCodeRenderEditCell = ({ id, field, hasFocus, value: initialValue, row, }) => {
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
- let active = true;
340
- if (!initialValue) {
341
- setInputValue("");
342
- return;
343
- }
344
- if (row.placeId) {
345
- const cached = getCacheByPlaceId(row.placeId);
346
- setInputValue(cached?.[0]?.placePrediction?.text?.text || initialValue);
347
- return;
348
- }
349
- getSuggestions(initialValue)
350
- .then((suggestions) => {
351
- if (!active)
352
- return;
353
- const text = suggestions?.[0]?.placePrediction?.text?.text || initialValue;
354
- setInputValue(text);
355
- })
356
- .catch(() => {
357
- if (active)
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 loadSuggestions = useMemo(() => debounce(async (val) => {
365
- if (!val)
366
- return;
367
- const results = await getSuggestions({
368
- input: val,
369
- includedPrimaryTypes: ["(regions)"],
370
- includedRegionCodes: ["US"],
371
- language: "en-US",
372
- region: "us",
373
- });
374
- setOptions(results);
375
- }, 300), [getSuggestions]);
376
- const handleChange = async (_, newValue) => {
377
- if (!newValue) {
378
- apiRef.current.updateRows([
379
- {
380
- id: id,
381
- zip: "",
382
- placeId: undefined,
383
- },
384
- ]);
385
- return;
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
- if (typeof newValue === "string") {
388
- setInputValue(newValue);
389
- apiRef.current.updateRows([
390
- {
391
- id: id,
392
- zip: newValue,
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
- 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"
425
- ? option
426
- : option.placePrediction?.text.text || "", onChange: handleChange, onInputChange: (_, v) => {
427
- if (v === inputValue)
428
- return;
429
- setInputValue(v);
430
- loadSuggestions(v);
431
- apiRef.current.setEditCellValue({
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
- }, renderInput: (params) => (_jsx(TextField, { ...params, inputRef: ref, placeholder: "Enter zip or city, state...", autoFocus: true })) }));
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 zip = useMemo(() => {
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 idNum = Number(props.value);
719
- if (idNum)
720
- getLocation(idNum, true);
721
- }, [props.value]);
722
- const findBounds = useCallback(() => {
723
- if (!zip)
724
- return;
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?.length) {
731
- const result = results.find((r) => r.address_components?.some((a) => a.types.includes("country"))) || results[0];
732
- const center = new google.maps.LatLng(result.geometry.location.lat(), result.geometry.location.lng());
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
- }, [zip]);
742
- useEffect(() => {
743
- if (props.row.zip || props.row.quoteZip) {
744
- findBounds();
745
- }
746
- }, [props.row.zip, props.row.quoteZip, findBounds]);
747
- const getGoogleAddresses = useCallback(async (searchText) => {
748
- if (!searchText)
749
- return;
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
- return;
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": { borderWidth: "0px !important" },
785
+ "& fieldset": {
786
+ borderWidth: "0px !important",
787
+ },
799
788
  }, options: [
800
789
  ...(locationSuggestions ?? []),
801
790
  ...(googleMapsPredictions ?? []),
802
- ], open: open, onOpen: () => setOpen(true), onClose: () => setOpen(false), value: location || "", inputValue: locationInputValue, freeSolo: true, filterOptions: (x) => x, getOptionLabel: (option) => typeof option === "string"
803
- ? option
804
- : locationEntityTypeGuard(option)
805
- ? option.name
806
- : option.placePrediction?.mainText?.text || "", onChange: handleValueChange, onInputChange: (_e, v) => {
807
- setLocationInputValue(v);
808
- debouncedSearch(v);
809
- }, 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) => {
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: () => setOpenDialog(false), open: openDialog, openLocationForm: (place) => onEditLocationClick(place, id, field), customerPortal: customerPortal })] }));
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 [inputValue, setInputValue] = useState("");
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 (!zip)
845
- return;
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?.[0]) {
851
- const loc = results[0].geometry.location;
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: loc,
892
+ center: center,
854
893
  radius: 10000,
855
894
  });
856
- setBounds(circle.getBounds() || undefined);
895
+ const bounds = circle.getBounds() || undefined;
896
+ setBounds(bounds);
857
897
  }
858
898
  });
859
- }, [zip]);
860
- const handleValueChange = async (_, newValue) => {
861
- if (typeof newValue !== "string") {
862
- if (!newValue) {
863
- onChange(undefined);
864
- return;
865
- }
866
- if (locationEntityTypeGuard(newValue)) {
867
- onChange(newValue);
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
- const formatted = result.place.formattedAddress;
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 debouncedSearch = useMemo(() => debounce(async (v) => {
888
- searchLocation({ zip, location: v });
889
- const googleResults = await getSuggestions({
890
- input: v,
891
- locationBias: bounds,
892
- includedRegionCodes: ["US"],
893
- language: "en-US",
894
- region: "us",
895
- });
896
- setGoogleMapsPredictions(googleResults);
897
- }, 400), [zip, bounds]);
898
- 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"
899
- ? option
900
- : locationEntityTypeGuard(option)
901
- ? option.name
902
- : option.placePrediction?.mainText?.text || "", onChange: handleValueChange, onInputChange: (_, v) => {
903
- setInputValue(v);
904
- debouncedSearch(v);
905
- }, endDecorator: location ? (_jsx(IconButton, { size: "small", onClick: () => setLocationFormOpen({
906
- open: true,
907
- place: location,
908
- }), 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 })] }));
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
  *