🔥 React-select dans la sélection de la commune
parent
5dbb93eeca
commit
fecdab29f8
|
@ -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>
|
||||
)
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue