From 215f2be341b95b178c2a42b053f52b3d4134e2d3 Mon Sep 17 00:00:00 2001 From: Mehul Date: Sat, 9 Nov 2024 20:38:09 -0500 Subject: [PATCH] fix location and add debounce --- frontend/src/components/help/Climate.jsx | 105 +++++++++++++---------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/frontend/src/components/help/Climate.jsx b/frontend/src/components/help/Climate.jsx index 34f2c3b3..3ed12be6 100644 --- a/frontend/src/components/help/Climate.jsx +++ b/frontend/src/components/help/Climate.jsx @@ -15,7 +15,6 @@ const fetchData = async (URL) => { return response.json(); }; - // OpenWeatherAPI Endpoints const url = { currentWeather: (lat, lon) => @@ -25,7 +24,7 @@ const url = { forecast: (lat, lon) => `https://api.openweathermap.org/data/2.5/forecast?lat=${lat}&lon=${lon}`, geocoding: (query) => `https://api.openweathermap.org/geo/1.0/direct?q=${query}&limit=5`, - disaters: (lat, lon) => `https://api.openweathermap.org/data/2.5/onecall?lat=${lat}&lon=${lon}` + disasters: (lat, lon) => `https://api.openweathermap.org/data/2.5/onecall?lat=${lat}&lon=${lon}` }; // Helper functions @@ -49,6 +48,8 @@ export default function Climate() { const [searchTerm, setSearchTerm] = useState(''); const [selectedLocation, setSelectedLocation] = useState(''); const [disasterAlerts, setDisasterAlerts] = useState(null); + const [suggestions, setSuggestions] = useState([]); // For storing location suggestions + const [debounceTimeout, setDebounceTimeout] = useState(null); // For debounce control // Fetch weather data const fetchWeatherData = async (lat, lon) => { @@ -58,12 +59,11 @@ export default function Climate() { const currentWeatherData = await fetchData(url.currentWeather(lat, lon)); const airPollutionData = await fetchData(url.airPollution(lat, lon)); const forecast = await fetchData(url.forecast(lat, lon)); - - const disasterData = await fetchData(url.disaters(lat, lon)); - setDisasterAlerts(disasterData?.alerts || null); + const disasterData = await fetchData(url.disasters(lat, lon)); setWeatherData(currentWeatherData); setAirQualityIndex(airPollutionData.list[0].main.aqi); + setDisasterAlerts(disasterData?.alerts || null); const now = new Date(); const cutoffTime = new Date(now.getTime() + 24 * 60 * 60 * 1000); @@ -83,38 +83,39 @@ export default function Climate() { } }; - // Handle search - const handleSearch = async (e) => { - e.preventDefault(); - if (!searchTerm) { - alert('Please enter a location to search.'); - return; + // Handle search term change with debounce + const handleSearchChange = async (e) => { + const value = e.target.value; + setSearchTerm(value); + + if (debounceTimeout) { + clearTimeout(debounceTimeout); } - setLoading(true); - setError(false); - setWeatherData(null); - setForecastData([]); - setCurrentWeather([]); - setAirQualityIndex(null); + if (value.length === 0) { + setSuggestions([]); + return; + } - try { - const locations = await fetchData(url.geocoding(searchTerm)); - if (locations.length === 0) { - alert('No locations found. Please try a different search term.'); - setLoading(false); - return; + const newDebounceTimeout = setTimeout(async () => { + try { + const locations = await fetchData(url.geocoding(value)); + setSuggestions(locations); // Set the location suggestions + } catch (err) { + console.error('Error fetching geocoding data:', err); } + }, 500); // 500ms debounce time - // Assuming the first result is the most relevant - const { lat, lon, name, state, country } = locations[0]; - setSelectedLocation(`${name}${state ? ', ' + state : ''}, ${country}`); - fetchWeatherData(lat, lon); - } catch (err) { - console.error('Error fetching geocoding data:', err); - setError(true); - setLoading(false); - } + setDebounceTimeout(newDebounceTimeout); + }; + + // Handle suggestion click + const handleSuggestionClick = (location) => { + const { lat, lon, name, state, country } = location; + setSelectedLocation(`${name}${state ? ', ' + state : ''}, ${country}`); + setSearchTerm(`${name}${state ? ', ' + state : ''}, ${country}`); + setSuggestions([]); + fetchWeatherData(lat, lon); }; // Handle current location @@ -146,32 +147,44 @@ export default function Climate() { ); }; - // Use effect to fetch current location weather on component mount - useEffect(() => { - handleCurrentLocation(); - }, []); // Empty dependency array to run only once when the component mounts - return (
-
-
+
+ e.preventDefault()} className="flex w-full mb-4"> setSearchTerm(e.target.value)} + onChange={handleSearchChange} className="p-4 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 w-full transition duration-300 ease-in-out" - placeholder="Search for a location" + placeholder="Search for a location (City, State, Country)" /> + + {/* Display suggestions */} + {suggestions.length > 0 && ( +
+ {suggestions.map((location, index) => ( +
handleSuggestionClick(location)} + > +

{`${location.name}${location.state ? ', ' + location.state : ''}, ${location.country}`}

+
+ ))} +
+ )} + @@ -180,6 +193,7 @@ export default function Climate() { {loading &&

Loading...

} {error &&

Error fetching data. Please try again.

} + {/* Weather details and other components as before */} {weatherData && (
{/* Current Weather */} @@ -260,7 +274,8 @@ export default function Climate() {
)} - {disasterAlerts && disasterAlerts.length > 0 ? ( + {/* Disaster Alerts */} + {disasterAlerts && disasterAlerts.length > 0 ? (

Disaster Alerts

@@ -292,4 +307,4 @@ function WeatherDetail({ icon: Icon, label, value }) {
); -} \ No newline at end of file +}