diff --git a/package-lock.json b/package-lock.json index 9b4d0fb..c06388b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@tanstack/react-query": "^5.102.8", + "country-codes-list": "^3.2.0", "react": "^19.2.8", "react-dom": "^19.2.8" }, @@ -59,7 +60,6 @@ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", @@ -886,7 +886,6 @@ "integrity": "sha512-YJ7EqCstVTzIr0fMr7qul/977en+pQHrfmuKIo6Zr9i75Be21dr3MovcfvGtyvi2HAUrRerWps5sMO9I7WaxDw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.18.0" } @@ -897,7 +896,6 @@ "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -957,7 +955,6 @@ "integrity": "sha512-zYvrmj9Yxd63UGaXw+kdt6A0F0s0qveJyuatIM77bYC2DE4pgmg7a50u8LR7PRtXd0x+h+Tl3eXabGm06SWd3Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.70.0", "@typescript-eslint/types": "8.70.0", @@ -1192,7 +1189,6 @@ "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1283,7 +1279,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.11.23", "caniuse-lite": "^1.0.30001810", @@ -1340,6 +1335,15 @@ "dev": true, "license": "MIT" }, + "node_modules/country-codes-list": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/country-codes-list/-/country-codes-list-3.2.0.tgz", + "integrity": "sha512-gR0IFGPRtqOSifQfFYlUodjJLCuRg36wBCYRpR81rZ2Z2swwVZF9v1If2z18bWuhXmOZhmIw9+L/Ikw1ojpkNw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1433,7 +1437,6 @@ "integrity": "sha512-NPXn6r5zl4uET1DAVPaOwzX3rut4c0wcmw3dWJAfOsTM5+TogXo0DDjz8pwm/hL8cyVNpHqeK4JpN0NjnyFFNw==", "dev": true, "license": "MIT", - "peer": true, "workspaces": [ "packages/*" ], @@ -1889,7 +1892,6 @@ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@keyv/serialize": "^1.1.1" } @@ -2337,7 +2339,6 @@ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -2435,7 +2436,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz", "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -2584,7 +2584,6 @@ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2671,7 +2670,6 @@ "integrity": "sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.7", @@ -2796,7 +2794,6 @@ "integrity": "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 1782863..4c50b2a 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@tanstack/react-query": "^5.102.8", + "country-codes-list": "^3.2.0", "react": "^19.2.8", "react-dom": "^19.2.8" }, diff --git a/src/components/ViewCity.tsx b/src/components/ViewCity.tsx index f11f128..9941306 100644 --- a/src/components/ViewCity.tsx +++ b/src/components/ViewCity.tsx @@ -1,12 +1,13 @@ import useGetWeather from "../hooks/fetchWeather/useGetWeather" -import useGetCityCoordinates from "../hooks/useGetCityCoordinates" +import useGetCityCoordinates from "../hooks/fetchCities/useGetCityCoordinates" interface ViewCityProp { city: string } export default function ViewCity(arg: ViewCityProp) { - const data = useGetCityCoordinates(arg.city) + const cityFilter = { cityName: arg.city } + const data = useGetCityCoordinates(cityFilter) const { isLoading, error, result } = useGetWeather( data.result[0]?.latitude, diff --git a/src/hooks/fetchCities/types.ts b/src/hooks/fetchCities/types.ts new file mode 100644 index 0000000..bd79d27 --- /dev/null +++ b/src/hooks/fetchCities/types.ts @@ -0,0 +1,47 @@ +export type citySearchResult = { + results: { + name: string + latitude: number + longitude: number + elevation: number + timezone: string + }[] +} + +export const countryCodes = [ + "AU", + "AT", + "AZ", + "BE", + "BR", + "CA", + "CN", + "DK", + "FI", + "FR", + "DE", + "GR", + "HU", + "IE", + "IT", + "JP", + "MX", + "NL", + "NO", + "PL", + "PT", + "RU", + "ES", + "SE", + "CH", + "TR", + "UK", + "US", +] as const + +export type CountryCode = (typeof countryCodes)[number] + +export type citySearchFilter = { + cityName: string + countryCode?: CountryCode +} diff --git a/src/hooks/fetchCities/useGetCityCoordinates.ts b/src/hooks/fetchCities/useGetCityCoordinates.ts new file mode 100644 index 0000000..6199fd7 --- /dev/null +++ b/src/hooks/fetchCities/useGetCityCoordinates.ts @@ -0,0 +1,20 @@ +import { useQuery } from "@tanstack/react-query" +import type { citySearchResult, citySearchFilter } from "./types" + +const useGetCityCoordinates = (filter: citySearchFilter) => { + const queryString = `?name=${filter.cityName}${filter.countryCode ? `&countryCode=${filter.countryCode}` : ""}` + + const { isLoading, error, data } = useQuery({ + queryKey: ["citySearch", filter.cityName], + queryFn: () => + fetch( + `https://geocoding-api.open-meteo.com/v1/search${queryString}` + ).then((res) => res.json() as Promise), + }) + + const result = data?.results ?? [] + + return { isLoading, error, result } +} + +export default useGetCityCoordinates diff --git a/src/hooks/useGetCityCoordinates.ts b/src/hooks/useGetCityCoordinates.ts deleted file mode 100644 index ffa0b74..0000000 --- a/src/hooks/useGetCityCoordinates.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { useQuery } from "@tanstack/react-query" - -export type citySearchResult = { - results: { - name: string - latitude: number - longitude: number - elevation: number - timezone: string - }[] -} - -const useGetCityCoordinates = (cityName: string) => { - const { isLoading, error, data } = useQuery({ - queryKey: ["citySearch", cityName], - queryFn: () => - fetch( - `https://geocoding-api.open-meteo.com/v1/search?name=${cityName}` - ).then((res) => res.json() as Promise), - }) - - const result = data?.results ?? [] - - return { isLoading, error, result } -} - -export default useGetCityCoordinates