import React, {useState} from 'react'; import {getJson, patchJson} from '../api'; import Modal from './Modal'; import PickerButton from './PickerButton'; function searchMessage(status) { if (status === 401) return 'Please sign in again to set your location.'; return 'We couldn\'t search for places just now. Please try again.'; } // A button that opens a dialog for saying where you garden: search for a city // or region and pick the right one, or use the browser's location. Choosing // saves it and reloads the page, so the season, suggestions and neighbours // all follow from it. // // Searches run when asked, not as you type: our place search (Nominatim) // asks that clients don't autocomplete. export default function LocationPicker({label, buttonClass, searchUrl, saveUrl}) { const [open, setOpen] = useState(false); const [query, setQuery] = useState(''); const [places, setPlaces] = useState(null); // null: not searched yet const [chosen, setChosen] = useState(null); const [busy, setBusy] = useState(false); const [message, setMessage] = useState(''); function close() { setOpen(false); setPlaces(null); setChosen(null); setMessage(''); } async function lookup(params) { setBusy(true); setMessage(''); setChosen(null); try { const {ok, status, data} = await getJson(`${searchUrl}?${params}`); if (!ok) { setPlaces(null); setMessage(searchMessage(status)); return; } setPlaces(data); if (data.length === 1) setChosen(data[0]); } catch (error) { setMessage(searchMessage()); } finally { setBusy(false); } } function search(event) { event.preventDefault(); if (query.trim().length < 2) { setMessage('Type a city or region to search for.'); return; } lookup(new URLSearchParams({q: query.trim()})); } function useMyLocation() { if (!navigator.geolocation) { setMessage('Your browser can\'t share its location. Search for your city instead.'); return; } setBusy(true); setMessage(''); navigator.geolocation.getCurrentPosition( (position) => lookup(new URLSearchParams({lat: position.coords.latitude, lng: position.coords.longitude})), () => { setBusy(false); setMessage('We couldn\'t get your location. Search for your city instead.'); }, {timeout: 10000} ); } async function save() { setBusy(true); setMessage(''); try { const {ok} = await patchJson(saveUrl, {location: {name: chosen.name, latitude: chosen.latitude, longitude: chosen.longitude}}); if (!ok) throw new Error('save failed'); window.location.reload(); } catch (error) { setBusy(false); setMessage('Something went wrong saving that. Please try again.'); } } return ( <> setOpen(true)} /> {open && (

We use this to match advice to your season and latitude, and to show you what gardeners near you are doing. Your city or region is public, like everything else you record.

setQuery(event.target.value)} />

{busy && Looking…} {message && {message}} {places && places.length === 0 && !busy && !message && ( We couldn't find that. Try a nearby city, or a region. )}
{places && places.length > 0 && (
Places found {places.map((place) => ( ))}
)}
)} ); }