all repos — caroster @ 3e13ed81f9961ed582333d0e9296921db2ed91d9

[Octree] Group carpool to your event https://caroster.io

frontend/containers/AddressAutofill/index.tsx (view raw)

  1import {useState} from 'react';
  2import TextField, {TextFieldProps} from '@mui/material/TextField';
  3import InputAdornment from '@mui/material/InputAdornment';
  4import PlaceOutlinedIcon from '@mui/icons-material/PlaceOutlined';
  5import Autocomplete from '@mui/material/Autocomplete';
  6import {debounce} from '@mui/material/utils';
  7import {SessionToken, AddressAutofillSuggestion} from '@mapbox/search-js-core';
  8import {useTranslation} from 'react-i18next';
  9import useLocale from '../../hooks/useLocale';
 10
 11interface Props {
 12  address: string;
 13  onSelect: ({
 14    location,
 15    address,
 16  }: {
 17    location: [number, number];
 18    address: string;
 19  }) => void;
 20  label: string;
 21  textFieldProps?: TextFieldProps;
 22}
 23
 24const AddressAutofill = ({
 25  address = '',
 26  onSelect,
 27  label,
 28  textFieldProps,
 29}: Props) => {
 30  const {t} = useTranslation();
 31  const {locale} = useLocale();
 32  const [value, setValue] = useState(address);
 33  const sessionToken = new SessionToken();
 34
 35  const [options, setOptions] = useState(
 36    [] as Array<AddressAutofillSuggestion>
 37  );
 38
 39  const onChange = async (e, selectedOption) => {
 40    const body = await fetch(
 41      '/api/mapbox/autofill/retrieve?' +
 42        new URLSearchParams({
 43          sessionToken,
 44          locale,
 45        }),
 46      {body: JSON.stringify(selectedOption), method: 'POST'}
 47    ).then(response => response.json());
 48    setValue(selectedOption);
 49    onSelect({
 50      address: selectedOption.full_address,
 51      location: body.features[0]?.geometry?.coordinates,
 52    });
 53  };
 54
 55  const updateOptions = debounce(async (e, search: string) => {
 56    if (search !== '') {
 57      await fetch(
 58        '/api/mapbox/autofill/suggest?' +
 59          new URLSearchParams({
 60            search,
 61            sessionToken,
 62            locale,
 63          })
 64      )
 65        .then(response => response.json())
 66        .then(body => {
 67          setOptions(body.suggestions);
 68        });
 69    }
 70  }, 400);
 71
 72  return (
 73    <Autocomplete
 74      freeSolo
 75      disableClearable
 76      getOptionLabel={option =>
 77        option.full_address || option.place_name || address
 78      }
 79      options={options}
 80      autoComplete
 81      value={value}
 82      filterOptions={x => x}
 83      noOptionsText={t('autocomplete.noMatch')}
 84      onChange={onChange}
 85      onInputChange={updateOptions}
 86      renderInput={params => (
 87        <TextField
 88          label={label}
 89          multiline
 90          maxRows={4}
 91          InputProps={{
 92            type: 'search',
 93            endAdornment: (
 94              <InputAdornment position="end" sx={{mr: -0.5}}>
 95                <PlaceOutlinedIcon />
 96              </InputAdornment>
 97            ),
 98          }}
 99          {...params}
100          {...textFieldProps}
101        />
102      )}
103      renderOption={(props, option) => {
104        return <li {...props}>{option.full_address || option.place_name}</li>;
105      }}
106    />
107  );
108};
109
110export default AddressAutofill;