🔥 React-select dans la sélection de la commune

pull/763/head
Mael 2019-11-05 11:59:22 +01:00
parent 5dbb93eeca
commit fecdab29f8
1 changed files with 90 additions and 43 deletions

View File

@ -1,43 +1,52 @@
import React from 'react'
import ReactSelect from 'react-select'
import 'react-select/dist/react-select.css'
import { T } from 'Components'
import React, { useCallback, useMemo, useState } from 'react'
import { debounce } from '../../../utils'
import { FormDecorator } from '../FormDecorator'
import './Select.css'
const tauxVersementTransport = codeCommune => {
return fetch(
async function tauxVersementTransport(codeCommune) {
const response = await fetch(
'https://versement-transport.netlify.com/.netlify/functions/taux-par-code-commune?codeCommune=' +
codeCommune,
{
method: 'GET'
}
).then(response => response.json())
codeCommune
)
if (!response.ok) {
return null
}
const json = await response.json()
return json
}
let getOptions = input =>
input.length < 3
? Promise.resolve({ options: [] })
: fetch(
`https://geo.api.gouv.fr/communes?nom=${input}&fields=nom,code,departement,region&boost=population`
)
.then(response => {
if (!response.ok)
return [{ nom: 'Aucune commune trouvée', disabled: true }]
return response.json()
})
.then(json => ({ options: json }))
.catch(function(error) {
console.log(
'Erreur dans la recherche de communes à partir du code postal',
error
) // eslint-disable-line no-console
return { options: [] }
})
async function searchCommunes(input) {
const response = await fetch(
`https://geo.api.gouv.fr/communes?nom=${input}&fields=nom,code,departement,region&boost=population`
)
if (!response.ok) {
return null
}
const json = await response.json()
return json
}
export default FormDecorator('select')(function Select({
setFormValue,
submit
}) {
const [searchResults, setSearchResults] = useState()
const [isLoading, setLoadingState] = useState(false)
const handleSearch = useCallback(
function(value) {
searchCommunes(value).then(results => {
setLoadingState(false)
setSearchResults(results)
})
},
[setSearchResults, setLoadingState]
)
const debouncedHandleSearch = useMemo(() => debounce(300, handleSearch), [
handleSearch
])
let submitOnChange = option => {
tauxVersementTransport(option.code)
.then(({ taux }) => {
@ -66,22 +75,60 @@ export default FormDecorator('select')(function Select({
return (
<div className="select-answer commune">
<ReactSelect.Async
onChange={submitOnChange}
labelKey="nom"
optionRenderer={({ nom, departement }) =>
nom + ` (${departement?.nom})`
}
filterOptions={options => {
// Do no filtering, just return all options
return options
<input
type="search"
css={`
padding: 0.4rem;
margin: 0.2rem 0;
width: 100%;
border: 1px solid var(--lighterTextColour);
border-radius: 0.3rem;
color: inherit;
font-size: inherit;
transition: border-color 0.1s;
position: relative;
:focus {
border-color: var(--colour);
}
`}
placeholder="Saisissez le nom d'une commune"
onChange={e => {
if (e.target.value.length < 2) {
setSearchResults(undefined)
return
}
setLoadingState(true)
debouncedHandleSearch(e.target.value)
}}
placeholder="Entrez le nom de commune"
noResultsText="Nous n'avons trouvé aucune commune"
searchPromptText={null}
loadingPlaceholder="Recherche en cours..."
loadOptions={getOptions}
/>
{!isLoading && (searchResults && searchResults.length === 0) && (
<p>
<T>Aucun résultat</T>
</p>
)}
{searchResults &&
searchResults.map(result => {
const { nom, departement } = result
return (
<button
onClick={() => submitOnChange(result)}
key={nom + departement?.nom}
css={`
text-align: left;
width: 100%;
padding: 0 0.4rem;
border-radius: 0.3rem;
:hover,
:focus {
background-color: var(--lighterColour);
}
`}>
{nom + ` (${departement?.nom})`}
</button>
)
})}
</div>
)
})