added search functionality
This commit is contained in:
parent
05bbbbf38b
commit
e1b43921fa
5 changed files with 100 additions and 22 deletions
|
@ -1,12 +1,22 @@
|
||||||
"use client"
|
"use client"
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Dialog, DialogContent } from '@/components/ui/dialog'
|
import {Dialog, DialogContent, DialogTrigger,} from "@/components/ui/dialog"
|
||||||
import { DialogTrigger } from '@radix-ui/react-dialog'
|
|
||||||
import { FiCommand } from "react-icons/fi";
|
import { FiCommand } from "react-icons/fi";
|
||||||
import React from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Command, CommandInput } from '@/components/ui/command';
|
import { Command, CommandInput } from '@/components/ui/command';
|
||||||
|
import { useGlobalContext, useGlobalContextUpdate } from '@/app/context/globalContext';
|
||||||
|
|
||||||
const Search = () => {
|
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 (
|
return (
|
||||||
<div className=''>
|
<div className=''>
|
||||||
<Dialog>
|
<Dialog>
|
||||||
|
@ -20,9 +30,30 @@ const Search = () => {
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className='p-0'>
|
<DialogContent className='p-0'>
|
||||||
<Command className='rounded-lg border shadow-md'>
|
<Command className='rounded-lg border shadow-md'>
|
||||||
<CommandInput placeholder='Search...'/>
|
<CommandInput value={inputValue} onChangeCapture={handleInput} placeholder='Search...' />
|
||||||
<ul className='px-3 pb-2'>
|
<ul className='px-3 pb-2'>
|
||||||
<p className='p-2 text-muted-foreground text-sm'>Suggestion</p>
|
<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>
|
</ul>
|
||||||
</Command>
|
</Command>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
"use Client"
|
"use Client"
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import React, { createContext, useContext, useEffect, useState } from "react"
|
import React, { createContext, useContext, useEffect, useState } from "react"
|
||||||
|
import DefaultState from "../utils/DefaultState";
|
||||||
|
import {debounce} from "lodash";
|
||||||
|
|
||||||
const GlobalContext = createContext();
|
const GlobalContext = createContext();
|
||||||
const GlobalContextUpdate = createContext();
|
const GlobalContextUpdate = createContext();
|
||||||
|
@ -12,52 +13,84 @@ export const GlobalContextProvider = ({children}) => {
|
||||||
const [airPollution, setAirPollution] = useState({});
|
const [airPollution, setAirPollution] = useState({});
|
||||||
const [dailyForecast, setDailyForecast] = useState({});
|
const [dailyForecast, setDailyForecast] = useState({});
|
||||||
const [uvIndex, setUvIndex] = 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 {
|
try {
|
||||||
const res = await axios.get("api/weather")
|
const res = await axios.get(`api/weather?lat=${lat}&lon=${lon}`)
|
||||||
setForecast(res.data)
|
setForecast(res.data)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Error fetching forecast data:", error.message)
|
console.log("Error fetching forecast data:", error.message)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const fetchAirPollution = async() => {
|
const fetchAirPollution = async(lat, lon) => {
|
||||||
try {
|
try {
|
||||||
const res = await axios.get("api/pollution")
|
const res = await axios.get(`api/pollution?lat=${lat}&lon=${lon}`)
|
||||||
setAirPollution(res.data)
|
setAirPollution(res.data)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Error fetching air pollution data:", error.message)
|
console.log("Error fetching air pollution data:", error.message)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const fetchDailyForecast = async() => {
|
const fetchDailyForecast = async(lat, lon) => {
|
||||||
try {
|
try {
|
||||||
const res = await axios.get("api/dailyForecast")
|
const res = await axios.get(`api/dailyForecast?lat=${lat}&lon=${lon}`)
|
||||||
setDailyForecast(res.data)
|
setDailyForecast(res.data)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Error fetching air forcast data:", error.message)
|
console.log("Error fetching air forcast data:", error.message)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const fetchUVIndex = async() => {
|
const fetchUVIndex = async(lat, lon) => {
|
||||||
try {
|
try {
|
||||||
const res = await axios.get("api/uvIndex")
|
const res = await axios.get(`api/uvIndex?lat=${lat}&lon=${lon}`)
|
||||||
setUvIndex(res.data)
|
setUvIndex(res.data)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Error fetching air UVI data:", error.message)
|
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(() => {
|
useEffect(() => {
|
||||||
fetchForecast();
|
fetchForecast(activeCity[0], activeCity[1]);
|
||||||
fetchAirPollution();
|
fetchAirPollution(activeCity[0], activeCity[1]);
|
||||||
fetchDailyForecast();
|
fetchDailyForecast(activeCity[0], activeCity[1]);
|
||||||
fetchUVIndex();
|
fetchUVIndex(activeCity[0], activeCity[1]);
|
||||||
}, []);
|
}, [activeCity]);
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<GlobalContext.Provider value={{forecast, airPollution, dailyForecast, uvIndex}}>
|
<GlobalContext.Provider value={{forecast, airPollution, dailyForecast, uvIndex, geoList, inputValue, handleInput,}}>
|
||||||
<GlobalContextUpdate.Provider>{children}</GlobalContextUpdate.Provider>
|
<GlobalContextUpdate.Provider value={{setActiveCity}}>{children}</GlobalContextUpdate.Provider>
|
||||||
</GlobalContext.Provider>
|
</GlobalContext.Provider>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,13 @@ const DefaultState = [
|
||||||
lat: 43.0722,
|
lat: 43.0722,
|
||||||
lon: -89.4008,
|
lon: -89.4008,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Milwaukee",
|
||||||
|
country: "US",
|
||||||
|
state: "Wisconsin",
|
||||||
|
lat: 43.0006,
|
||||||
|
lon: -87.9668,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "New York",
|
name: "New York",
|
||||||
country: "US",
|
country: "US",
|
||||||
|
@ -29,5 +36,5 @@ const DefaultState = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export default DefaultState
|
export default DefaultState;
|
||||||
|
|
6
weather_app/package-lock.json
generated
6
weather_app/package-lock.json
generated
|
@ -19,6 +19,7 @@
|
||||||
"cmdk": "^1.0.0",
|
"cmdk": "^1.0.0",
|
||||||
"embla-carousel-react": "^8.0.0",
|
"embla-carousel-react": "^8.0.0",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
"lucide-react": "^0.359.0",
|
"lucide-react": "^0.359.0",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"next": "14.1.4",
|
"next": "14.1.4",
|
||||||
|
@ -1737,6 +1738,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
|
"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": {
|
"node_modules/loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
"cmdk": "^1.0.0",
|
"cmdk": "^1.0.0",
|
||||||
"embla-carousel-react": "^8.0.0",
|
"embla-carousel-react": "^8.0.0",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
"lucide-react": "^0.359.0",
|
"lucide-react": "^0.359.0",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"next": "14.1.4",
|
"next": "14.1.4",
|
||||||
|
|
Loading…
Add table
Reference in a new issue