From e1b43921fa304bab120b88611661145f3f84ddd7 Mon Sep 17 00:00:00 2001 From: Juthatip McDevitt Date: Sat, 23 Mar 2024 17:14:49 -0500 Subject: [PATCH] added search functionality --- weather_app/app/components/search/Search.tsx | 39 ++++++++++-- weather_app/app/context/globalContext.js | 67 +++++++++++++++----- weather_app/app/utils/DefaultState.tsx | 9 ++- weather_app/package-lock.json | 6 ++ weather_app/package.json | 1 + 5 files changed, 100 insertions(+), 22 deletions(-) diff --git a/weather_app/app/components/search/Search.tsx b/weather_app/app/components/search/Search.tsx index 0240bf1..3033f63 100644 --- a/weather_app/app/components/search/Search.tsx +++ b/weather_app/app/components/search/Search.tsx @@ -1,12 +1,22 @@ "use client" import { Button } from '@/components/ui/button' -import { Dialog, DialogContent } from '@/components/ui/dialog' -import { DialogTrigger } from '@radix-ui/react-dialog' +import {Dialog, DialogContent, DialogTrigger,} from "@/components/ui/dialog" import { FiCommand } from "react-icons/fi"; -import React from 'react' +import React, { useState } from 'react' import { Command, CommandInput } from '@/components/ui/command'; +import { useGlobalContext, useGlobalContextUpdate } from '@/app/context/globalContext'; const Search = () => { + const {geoList, inputValue, handleInput} = useGlobalContext(); + const {setActiveCity} = useGlobalContextUpdate(); + const [hoverIndex, setHoverIndex] = useState(0); + + const getClickedCoords = (lat: number, lon: number) => { + setActiveCity([lat, lon]); + } + + + return (
@@ -20,9 +30,30 @@ const Search = () => { - +

    Suggestion

    + {geoList?.length === 0 || (!geoList &&

    No Results

    )} + {geoList && geoList.map(( + item: { + name: string; + country: string; + state: string; + lat: number; + lon: number; + }, + index: number, + + ) => { + const {country, state, name} = item; + return (
  • setHoverIndex(index)} className={`py-2 px-2 text-sm rounded-md cursor-pointer + ${hoverIndex === index ? "bg-accent" : ""} + `} onClick={() => { + getClickedCoords(item.lat, item.lon); + }}> +

    {name}, {state} {country}

    +
  • ); + })}
diff --git a/weather_app/app/context/globalContext.js b/weather_app/app/context/globalContext.js index 8df2db0..6a12f6d 100644 --- a/weather_app/app/context/globalContext.js +++ b/weather_app/app/context/globalContext.js @@ -1,7 +1,8 @@ "use Client" import axios from "axios"; import React, { createContext, useContext, useEffect, useState } from "react" - +import DefaultState from "../utils/DefaultState"; +import {debounce} from "lodash"; const GlobalContext = createContext(); const GlobalContextUpdate = createContext(); @@ -12,52 +13,84 @@ export const GlobalContextProvider = ({children}) => { const [airPollution, setAirPollution] = useState({}); const [dailyForecast, setDailyForecast] = useState({}); const [uvIndex, setUvIndex] = useState({}); + const [geoList, setGeoList] = useState(DefaultState); + const [inputValue, setInputValue] = useState(""); + const [activeCity, setActiveCity] = useState([41.8781, -87.6298]); - const fetchForecast = async() => { + + const fetchForecast = async(lat, lon) => { try { - const res = await axios.get("api/weather") + const res = await axios.get(`api/weather?lat=${lat}&lon=${lon}`) setForecast(res.data) } catch (error) { console.log("Error fetching forecast data:", error.message) } }; - const fetchAirPollution = async() => { + const fetchAirPollution = async(lat, lon) => { try { - const res = await axios.get("api/pollution") + const res = await axios.get(`api/pollution?lat=${lat}&lon=${lon}`) setAirPollution(res.data) } catch (error) { console.log("Error fetching air pollution data:", error.message) } }; - const fetchDailyForecast = async() => { + const fetchDailyForecast = async(lat, lon) => { try { - const res = await axios.get("api/dailyForecast") + const res = await axios.get(`api/dailyForecast?lat=${lat}&lon=${lon}`) setDailyForecast(res.data) } catch (error) { console.log("Error fetching air forcast data:", error.message) } }; - const fetchUVIndex = async() => { + const fetchUVIndex = async(lat, lon) => { try { - const res = await axios.get("api/uvIndex") + const res = await axios.get(`api/uvIndex?lat=${lat}&lon=${lon}`) setUvIndex(res.data) } catch (error) { console.log("Error fetching air UVI data:", error.message) } - } + }; + const fetchGeoList = async (search) => { + try { + const res = await axios.get(`api/geoCoordinate?search=${search}`); + setGeoList(res.data) + + } catch (error) { + console.log("Error fetching data:", error.message) + } + }; + + const handleInput = (e) => { + setInputValue(e.target.value); + + if(e.target.value === ""){ + setGeoList(DefaultState); + } + }; + + + useEffect(() => { + const debouncedFetch = debounce((search) => { + fetchGeoList(search); + }, 500) + if(inputValue){ + debouncedFetch(inputValue) + } + return() => debouncedFetch.cancel(); + }, [inputValue]) useEffect(() => { - fetchForecast(); - fetchAirPollution(); - fetchDailyForecast(); - fetchUVIndex(); - }, []); + fetchForecast(activeCity[0], activeCity[1]); + fetchAirPollution(activeCity[0], activeCity[1]); + fetchDailyForecast(activeCity[0], activeCity[1]); + fetchUVIndex(activeCity[0], activeCity[1]); + }, [activeCity]); return( - - {children} + + {children} ) }; diff --git a/weather_app/app/utils/DefaultState.tsx b/weather_app/app/utils/DefaultState.tsx index 1a99a25..264afcf 100644 --- a/weather_app/app/utils/DefaultState.tsx +++ b/weather_app/app/utils/DefaultState.tsx @@ -13,6 +13,13 @@ const DefaultState = [ lat: 43.0722, lon: -89.4008, }, + { + name: "Milwaukee", + country: "US", + state: "Wisconsin", + lat: 43.0006, + lon: -87.9668, + }, { name: "New York", country: "US", @@ -29,5 +36,5 @@ const DefaultState = [ }, ] -export default DefaultState +export default DefaultState; \ No newline at end of file diff --git a/weather_app/package-lock.json b/weather_app/package-lock.json index 7c15967..a115989 100644 --- a/weather_app/package-lock.json +++ b/weather_app/package-lock.json @@ -19,6 +19,7 @@ "cmdk": "^1.0.0", "embla-carousel-react": "^8.0.0", "leaflet": "^1.9.4", + "lodash": "^4.17.21", "lucide-react": "^0.359.0", "moment": "^2.30.1", "next": "14.1.4", @@ -1737,6 +1738,11 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", diff --git a/weather_app/package.json b/weather_app/package.json index 6683ccc..d6dc170 100644 --- a/weather_app/package.json +++ b/weather_app/package.json @@ -20,6 +20,7 @@ "cmdk": "^1.0.0", "embla-carousel-react": "^8.0.0", "leaflet": "^1.9.4", + "lodash": "^4.17.21", "lucide-react": "^0.359.0", "moment": "^2.30.1", "next": "14.1.4",