68 lines
1.9 KiB
JavaScript
68 lines
1.9 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
|
|
|
export default function AddressAutocomplete({ onSelect }) {
|
|
const [input, setInput] = useState("");
|
|
const [options, setOptions] = useState([]);
|
|
|
|
useEffect(() => {
|
|
if (input.length < 3) {
|
|
setOptions([]);
|
|
return;
|
|
}
|
|
const ctrl = new AbortController();
|
|
fetch(`/api/autocomplete?input=${encodeURIComponent(input)}`, {
|
|
signal: ctrl.signal,
|
|
})
|
|
.then((res) => res.json())
|
|
.then((json) => setOptions(json.predictions || []))
|
|
.catch(() => {})
|
|
.finally(() => {});
|
|
return () => ctrl.abort();
|
|
}, [input]);
|
|
|
|
return (
|
|
<div className="address-autocomplete" style={{ position: "relative" }}>
|
|
<input
|
|
type="text"
|
|
placeholder="Start typing address…"
|
|
value={input}
|
|
onChange={(e) => setInput(e.target.value)}
|
|
style={{ width: "100%", padding: "0.5rem", boxSizing: "border-box" }}
|
|
/>
|
|
{options.length > 0 && (
|
|
<ul
|
|
className="autocomplete-list"
|
|
style={{
|
|
listStyle: "none",
|
|
margin: 0,
|
|
padding: "0.5rem",
|
|
position: "absolute",
|
|
top: "100%",
|
|
left: 0,
|
|
right: 0,
|
|
background: "#fff",
|
|
border: "1px solid #ccc",
|
|
maxHeight: "200px",
|
|
overflowY: "auto",
|
|
zIndex: 1000,
|
|
}}
|
|
>
|
|
{options.map((opt) => (
|
|
<li
|
|
key={opt.place_id}
|
|
onClick={() => {
|
|
setInput(opt.description);
|
|
setOptions([]);
|
|
onSelect(opt.description);
|
|
}}
|
|
style={{ padding: "0.25rem 0", cursor: "pointer" }}
|
|
>
|
|
{opt.description}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|