Implement ComboAdresseSearch
This commit is contained in:
parent
b6c94a3758
commit
8a2f079acb
6 changed files with 60 additions and 96 deletions
|
@ -11,3 +11,7 @@
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form [data-react-class='MapEditor'] [data-reach-combobox-input] {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
44
app/javascript/components/ComboAdresseSearch.js
Normal file
44
app/javascript/components/ComboAdresseSearch.js
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import React, { useCallback } from 'react';
|
||||||
|
import { ReactQueryCacheProvider } from 'react-query';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import ComboSearch from './ComboSearch';
|
||||||
|
import { queryCache } from './shared/queryCache';
|
||||||
|
|
||||||
|
function ComboAdresseSearch({
|
||||||
|
mandatory,
|
||||||
|
placeholder,
|
||||||
|
hiddenFieldId,
|
||||||
|
onChange,
|
||||||
|
transformResult = ({ properties: { label } }) => [label, label],
|
||||||
|
allowInputValues = true
|
||||||
|
}) {
|
||||||
|
const transformResults = useCallback((_, { features }) => features);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactQueryCacheProvider queryCache={queryCache}>
|
||||||
|
<ComboSearch
|
||||||
|
placeholder={placeholder}
|
||||||
|
required={mandatory}
|
||||||
|
hiddenFieldId={hiddenFieldId}
|
||||||
|
onChange={onChange}
|
||||||
|
allowInputValues={allowInputValues}
|
||||||
|
scope="adresse"
|
||||||
|
minimumInputLength={2}
|
||||||
|
transformResult={transformResult}
|
||||||
|
transformResults={transformResults}
|
||||||
|
/>
|
||||||
|
</ReactQueryCacheProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboAdresseSearch.propTypes = {
|
||||||
|
placeholder: PropTypes.string,
|
||||||
|
mandatory: PropTypes.bool,
|
||||||
|
hiddenFieldId: PropTypes.string,
|
||||||
|
transformResult: PropTypes.func,
|
||||||
|
allowInputValues: PropTypes.bool,
|
||||||
|
onChange: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ComboAdresseSearch;
|
|
@ -1,88 +0,0 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import { getJSON } from '@utils';
|
|
||||||
import {
|
|
||||||
Combobox,
|
|
||||||
ComboboxInput,
|
|
||||||
ComboboxPopover,
|
|
||||||
ComboboxList,
|
|
||||||
ComboboxOption
|
|
||||||
} from '@reach/combobox';
|
|
||||||
import '@reach/combobox/styles.css';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
let cache = {};
|
|
||||||
const useAddressSearch = (searchTerm) => {
|
|
||||||
const [addresses, setAddresses] = useState([]);
|
|
||||||
useEffect(() => {
|
|
||||||
if (searchTerm.trim() !== '') {
|
|
||||||
let isFresh = true;
|
|
||||||
fetchAddresses(searchTerm).then((addresses) => {
|
|
||||||
if (isFresh) setAddresses(addresses);
|
|
||||||
});
|
|
||||||
return () => (isFresh = false);
|
|
||||||
}
|
|
||||||
}, [searchTerm]);
|
|
||||||
return addresses;
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchAddresses = (value) => {
|
|
||||||
if (cache[value]) {
|
|
||||||
return Promise.resolve(cache[value]);
|
|
||||||
}
|
|
||||||
const url = `https://api-adresse.data.gouv.fr/search/`;
|
|
||||||
return getJSON(url, { q: value, limit: 5 }, 'get').then((result) => {
|
|
||||||
if (result) {
|
|
||||||
cache[value] = result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const SearchInput = ({ getCoords }) => {
|
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
|
||||||
const addresses = useAddressSearch(searchTerm);
|
|
||||||
const handleSearchTermChange = (event) => {
|
|
||||||
setSearchTerm(event.target.value);
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<Combobox aria-label="addresses">
|
|
||||||
<ComboboxInput
|
|
||||||
placeholder="Rechercher une adresse : saisissez au moins 2 caractères"
|
|
||||||
className="address-search-input"
|
|
||||||
style={{
|
|
||||||
font: 'inherit',
|
|
||||||
padding: '.25rem .5rem',
|
|
||||||
width: '100%',
|
|
||||||
minHeight: '62px'
|
|
||||||
}}
|
|
||||||
onChange={handleSearchTermChange}
|
|
||||||
/>
|
|
||||||
{addresses.features && (
|
|
||||||
<ComboboxPopover className="shadow-popup">
|
|
||||||
{addresses.features.length > 0 ? (
|
|
||||||
<ComboboxList>
|
|
||||||
{addresses.features.map((feature) => {
|
|
||||||
const str = `${feature.properties.name}, ${feature.properties.city}`;
|
|
||||||
return (
|
|
||||||
<ComboboxOption
|
|
||||||
onClick={() => getCoords(feature.geometry.coordinates)}
|
|
||||||
key={str}
|
|
||||||
value={str}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ComboboxList>
|
|
||||||
) : (
|
|
||||||
<span style={{ display: 'block', margin: 8 }}>Aucun résultat</span>
|
|
||||||
)}
|
|
||||||
</ComboboxPopover>
|
|
||||||
)}
|
|
||||||
</Combobox>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
SearchInput.propTypes = {
|
|
||||||
getCoords: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SearchInput;
|
|
|
@ -9,7 +9,7 @@ import { getJSON, ajax, fire } from '@utils';
|
||||||
|
|
||||||
import { getMapStyle, SwitchMapStyle } from '../MapStyles';
|
import { getMapStyle, SwitchMapStyle } from '../MapStyles';
|
||||||
|
|
||||||
import SearchInput from './SearchInput';
|
import ComboAdresseSearch from '../ComboAdresseSearch';
|
||||||
import {
|
import {
|
||||||
polygonCadastresFill,
|
polygonCadastresFill,
|
||||||
polygonCadastresLine,
|
polygonCadastresLine,
|
||||||
|
@ -279,9 +279,11 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
marginBottom: '50px'
|
marginBottom: '50px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SearchInput
|
<ComboAdresseSearch
|
||||||
getCoords={(searchTerm) => {
|
placeholder="Rechercher une adresse : saisissez au moins 2 caractères"
|
||||||
setCoords(searchTerm);
|
allowInputValues={false}
|
||||||
|
onChange={(_, { geometry: { coordinates } }) => {
|
||||||
|
setCoords(coordinates);
|
||||||
setZoom([17]);
|
setZoom([17]);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
3
app/javascript/loaders/ComboAdresseSearch.js
Normal file
3
app/javascript/loaders/ComboAdresseSearch.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import Loadable from '../components/Loadable';
|
||||||
|
|
||||||
|
export default Loadable(() => import('../components/ComboAdresseSearch'));
|
|
@ -1,4 +1,3 @@
|
||||||
= form.select :value, [champ.value].compact,
|
- hidden_field_id = SecureRandom.uuid
|
||||||
{ include_blank: true },
|
= form.hidden_field :value, { data: { uuid: hidden_field_id } }
|
||||||
required: champ.mandatory?,
|
= react_component("ComboAdresseSearch", mandatory: champ.mandatory?, hiddenFieldId: hidden_field_id)
|
||||||
class: 'select2 adresse'
|
|
||||||
|
|
Loading…
Reference in a new issue