added search functionality

This commit is contained in:
Juthatip McDevitt 2024-03-23 17:14:49 -05:00
parent 05bbbbf38b
commit e1b43921fa
5 changed files with 100 additions and 22 deletions

View file

@ -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<number>(0);
const getClickedCoords = (lat: number, lon: number) => {
setActiveCity([lat, lon]);
}
return (
<div className=''>
<Dialog>
@ -20,9 +30,30 @@ const Search = () => {
</DialogTrigger>
<DialogContent className='p-0'>
<Command className='rounded-lg border shadow-md'>
<CommandInput placeholder='Search...'/>
<CommandInput value={inputValue} onChangeCapture={handleInput} placeholder='Search...' />
<ul className='px-3 pb-2'>
<p className='p-2 text-muted-foreground text-sm'>Suggestion</p>
{geoList?.length === 0 || (!geoList && <p>No Results</p>)}
{geoList && geoList.map((
item: {
name: string;
country: string;
state: string;
lat: number;
lon: number;
},
index: number,
) => {
const {country, state, name} = item;
return (<li key={index} onMouseEnter={() => setHoverIndex(index)} className={`py-2 px-2 text-sm rounded-md cursor-pointer
${hoverIndex === index ? "bg-accent" : ""}
`} onClick={() => {
getClickedCoords(item.lat, item.lon);
}}>
<p>{name}, {state} {country}</p>
</li>);
})}
</ul>
</Command>
</DialogContent>

View file

@ -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(() => {
fetchForecast();
fetchAirPollution();
fetchDailyForecast();
fetchUVIndex();
}, []);
const debouncedFetch = debounce((search) => {
fetchGeoList(search);
}, 500)
if(inputValue){
debouncedFetch(inputValue)
}
return() => debouncedFetch.cancel();
}, [inputValue])
useEffect(() => {
fetchForecast(activeCity[0], activeCity[1]);
fetchAirPollution(activeCity[0], activeCity[1]);
fetchDailyForecast(activeCity[0], activeCity[1]);
fetchUVIndex(activeCity[0], activeCity[1]);
}, [activeCity]);
return(
<GlobalContext.Provider value={{forecast, airPollution, dailyForecast, uvIndex}}>
<GlobalContextUpdate.Provider>{children}</GlobalContextUpdate.Provider>
<GlobalContext.Provider value={{forecast, airPollution, dailyForecast, uvIndex, geoList, inputValue, handleInput,}}>
<GlobalContextUpdate.Provider value={{setActiveCity}}>{children}</GlobalContextUpdate.Provider>
</GlobalContext.Provider>
)
};

View file

@ -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;

View file

@ -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",

View file

@ -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",