"use client"; import { useState, useEffect, useRef } from "react"; import { locationsApi, Country, LocationSearchResult } from "@/lib/api"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { MapPin, Loader2, Globe } from "lucide-react"; interface LocationPickerProps { value: string; // The final string "City, State, Country" onChange: (value: string) => void; } export function LocationPicker({ value, onChange }: LocationPickerProps) { const [countries, setCountries] = useState([]); const [selectedCountry, setSelectedCountry] = useState(""); // ID as string // Search const [query, setQuery] = useState(""); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const [showResults, setShowResults] = useState(false); const wrapperRef = useRef(null); // Initial Load useEffect(() => { locationsApi.listCountries().then(res => { const data = res || []; setCountries(data); // Default to Brazil if available (User is Brazilian based on context) const br = data.find(c => c.iso2 === "BR"); if (br) setSelectedCountry(br.id.toString()); }).catch(console.error); }, []); // Helper to get country name const getCountryName = (id: string) => countries.find(c => c.id.toString() === id)?.name || ""; // Debounce Search useEffect(() => { if (!selectedCountry || query.length < 2) { setResults([]); return; } const timeout = setTimeout(() => { setLoading(true); locationsApi.search(query, selectedCountry) .then(res => setResults(res || [])) .catch(err => { console.error("Search failed", err); setResults([]); }) .finally(() => setLoading(false)); }, 500); return () => clearTimeout(timeout); }, [query, selectedCountry]); // Click Outside to close useEffect(() => { function handleClickOutside(event: MouseEvent) { if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) { setShowResults(false); } } document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, []); const handleSelectResult = (item: LocationSearchResult) => { const countryName = getCountryName(selectedCountry); let finalString = ""; if (item.type === 'city') { // City, State, Country finalString = `${item.name}, ${item.region_name}, ${countryName}`; } else { // State, Country finalString = `${item.name}, ${countryName}`; } onChange(finalString); setQuery(item.name); // Updates visible input to just name or full string? // User image shows "City or state" as input. // Usually we show the full formatted string or just the name. // Let's show full string to be clear. setQuery(finalString); setShowResults(false); }; return (
{/* Country Select (Right in design but logical Left in flow, design shows separate) */} {/* User image: Left: City/State (Input with target icon), Right: Country (Dropdown) */} {/* City/State Search (2/3 width) */}
{ setQuery(e.target.value); setShowResults(true); // If user types manually conform to standard? // We can allow free text, but search helps. onChange(e.target.value); }} onFocus={() => setShowResults(true)} placeholder={selectedCountry ? "Busque cidade ou estado..." : "Selecione o país primeiro"} className="pl-10" disabled={!selectedCountry} /> {loading && (
)}
{/* Results Dropdown */} {showResults && results?.length > 0 && (
{results.map((item) => ( ))}
)}
{/* Country Select (1/3 width) */}
); }