diff --git "a/v\303\246r/package-lock.json" "b/v\303\246r/package-lock.json"
index 909fe61..3b7ca00 100644
--- "a/v\303\246r/package-lock.json"
+++ "b/v\303\246r/package-lock.json"
@@ -8,6 +8,7 @@
"name": "var.json",
"version": "0.0.0",
"dependencies": {
+ "@tanstack/react-query": "^5.102.8",
"react": "^19.2.8",
"react-dom": "^19.2.8"
},
@@ -848,6 +849,32 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@tanstack/query-core": {
+ "version": "5.102.8",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.102.8.tgz",
+ "integrity": "sha512-ZNjkJ33CqvPNec/6lZBnHqLc3EVGPZ9ySLhYahU9TcuRFdmwXewuj0c4hwSWcGHqEUwcSrKeZ+oGcvPBqXcQcg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/react-query": {
+ "version": "5.102.8",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.102.8.tgz",
+ "integrity": "sha512-TYBea4OuXWD7MhaSHq069TWbFe7rcwWN6kzT7JF0OKi1K6c1gTv2IzD6A6ExJsCMozdkqBWeuIUZmu4KQg0O5A==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/query-core": "5.102.8"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": "^18 || ^19"
+ }
+ },
"node_modules/@types/esrecurse": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
diff --git "a/v\303\246r/package.json" "b/v\303\246r/package.json"
index a151cda..cc694f8 100644
--- "a/v\303\246r/package.json"
+++ "b/v\303\246r/package.json"
@@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
+ "@tanstack/react-query": "^5.102.8",
"react": "^19.2.8",
"react-dom": "^19.2.8"
},
diff --git "a/v\303\246r/src/App.tsx" "b/v\303\246r/src/App.tsx"
index 9ca8e8d..8ef557e 100644
--- "a/v\303\246r/src/App.tsx"
+++ "b/v\303\246r/src/App.tsx"
@@ -3,9 +3,12 @@ import heroImg from './assets/hero.png'
import reactLogo from './assets/react.svg'
import viteLogo from './assets/vite.svg'
import './App.css'
+import useGetWeather from './hooks/fetchWeather/useGetWeather'
function App() {
const [count, setCount] = useState(0)
+ // Example fetch, plz remove asap
+ const { result } = useGetWeather(67, 67, 420)
return (
<>
@@ -16,6 +19,7 @@ function App() {
Edit src/App.tsx and save to test HMR
diff --git "a/v\303\246r/src/hooks/fetchWeather/types.ts" "b/v\303\246r/src/hooks/fetchWeather/types.ts"
new file mode 100644
index 0000000..702841c
--- /dev/null
+++ "b/v\303\246r/src/hooks/fetchWeather/types.ts"
@@ -0,0 +1,178 @@
+export const weatherSymbolCodes = [
+ "clearsky_day",
+ "clearsky_night",
+ "clearsky_polartwilight",
+ "fair_day",
+ "fair_night",
+ "fair_polartwilight",
+ "lightssnowshowersandthunder_day",
+ "lightssnowshowersandthunder_night",
+ "lightssnowshowersandthunder_polartwilight",
+ "lightsnowshowers_day",
+ "lightsnowshowers_night",
+ "lightsnowshowers_polartwilight",
+ "heavyrainandthunder",
+ "heavysnowandthunder",
+ "rainandthunder",
+ "heavysleetshowersandthunder_day",
+ "heavysleetshowersandthunder_night",
+ "heavysleetshowersandthunder_polartwilight",
+ "heavysnow",
+ "heavyrainshowers_day",
+ "heavyrainshowers_night",
+ "heavyrainshowers_polartwilight",
+ "lightsleet",
+ "heavyrain",
+ "lightrainshowers_day",
+ "lightrainshowers_night",
+ "lightrainshowers_polartwilight",
+ "heavysleetshowers_day",
+ "heavysleetshowers_night",
+ "heavysleetshowers_polartwilight",
+ "lightsleetshowers_day",
+ "lightsleetshowers_night",
+ "lightsleetshowers_polartwilight",
+ "snow",
+ "heavyrainshowersandthunder_day",
+ "heavyrainshowersandthunder_night",
+ "heavyrainshowersandthunder_polartwilight",
+ "snowshowers_day",
+ "snowshowers_night",
+ "snowshowers_polartwilight",
+ "fog",
+ "snowshowersandthunder_day",
+ "snowshowersandthunder_night",
+ "snowshowersandthunder_polartwilight",
+ "lightsnowandthunder",
+ "heavysleetandthunder",
+ "lightrain",
+ "rainshowersandthunder_day",
+ "rainshowersandthunder_night",
+ "rainshowersandthunder_polartwilight",
+ "rain",
+ "lightsnow",
+ "lightrainshowersandthunder_day",
+ "lightrainshowersandthunder_night",
+ "lightrainshowersandthunder_polartwilight",
+ "heavysleet",
+ "sleetandthunder",
+ "lightrainandthunder",
+ "sleet",
+ "lightssleetshowersandthunder_day",
+ "lightssleetshowersandthunder_night",
+ "lightssleetshowersandthunder_polartwilight",
+ "lightsleetandthunder",
+ "partlycloudy_day",
+ "partlycloudy_night",
+ "partlycloudy_polartwilight",
+ "sleetshowersandthunder_day",
+ "sleetshowersandthunder_night",
+ "sleetshowersandthunder_polartwilight",
+ "rainshowers_day",
+ "rainshowers_night",
+ "rainshowers_polartwilight",
+ "snowandthunder",
+ "sleetshowers_day",
+ "sleetshowers_night",
+ "sleetshowers_polartwilight",
+ "cloudy",
+ "heavysnowshowersandthunder_day",
+ "heavysnowshowersandthunder_night",
+ "heavysnowshowersandthunder_polartwilight",
+ "heavysnowshowers_day",
+ "heavysnowshowers_night",
+ "heavysnowshowers_polartwilight"
+] as const
+
+export type WeatherSymbolCode = (typeof weatherSymbolCodes)[number]
+
+export type PointGeometry = {
+ coordinates: [longitude: number, latitude: number, altitude: number],
+ type: "Point"
+}
+
+export type ForecastUnits = {
+ air_pressure_at_sea_level?: string,
+ air_temperature?: string,
+ air_temperature_max?: string,
+ air_temperature_min?: string,
+ cloud_area_fraction?: string,
+ cloud_area_fraction_high?: string,
+ cloud_area_fraction_low?: string,
+ cloud_area_fraction_medium?: string,
+ dew_point_temperature?: string,
+ fog_area_fraction?: string,
+ precipitation_amount?: string,
+ precipitation_amount_max?: string,
+ precipitation_amount_min?: string,
+ probability_of_precipitation?: string,
+ probability_of_thunder?: string,
+ relative_humidity?: string,
+ ultraviolet_index_clear_sky_max?: string,
+ wind_from_direction?: string,
+ wind_speed?: string,
+ wind_speed_of_gust?: string
+}
+
+export type ForecastTimeInstant = {
+ air_pressure_at_sea_level?: number,
+ air_temperature?: number,
+ cloud_area_fraction?: number,
+ cloud_area_fraction_high?: number,
+ cloud_area_fraction_low?: number,
+ cloud_area_fraction_medium?: number,
+ dew_point_temperature?: number,
+ fog_area_fraction?: number,
+ relative_humidity?: number,
+ wind_from_direction?: number,
+ wind_speed?: number,
+ wind_speed_of_gust?: number
+}
+
+export type ForecastTimePeriod = {
+ air_temperature_max?: number,
+ air_temperature_min?: number,
+ precipitation_amount?: number,
+ precipitation_amount_max?: number,
+ precipitation_amount_min?: number,
+ probability_of_precipitation?: number,
+ probability_of_thunder?: number,
+ ultraviolet_index_clear_sky_max?: number
+}
+
+export type ForecastSummary = {
+ symbol_code: WeatherSymbolCode
+}
+
+export type ForecastPeriod = {
+ details: ForecastTimePeriod,
+ summary: ForecastSummary
+}
+
+export type ForecastTimeStep = {
+ data: {
+ instant: {
+ details?: ForecastTimeInstant
+ },
+ next_1_hours?: ForecastPeriod,
+ next_6_hours?: ForecastPeriod,
+ next_12_hours?: ForecastPeriod
+ },
+ time: string
+}
+
+export type Forecast = {
+ meta: {
+ units: ForecastUnits,
+ updated_at: string
+ },
+ timeseries: ForecastTimeStep[]
+}
+
+export type METJSONForecast = {
+ geometry: PointGeometry,
+ properties: Forecast,
+ type: "Feature"
+}
+
+export type WeatherApiResponse = METJSONForecast
diff --git "a/v\303\246r/src/hooks/fetchWeather/useGetWeather.ts" "b/v\303\246r/src/hooks/fetchWeather/useGetWeather.ts"
new file mode 100644
index 0000000..3ff66b6
--- /dev/null
+++ "b/v\303\246r/src/hooks/fetchWeather/useGetWeather.ts"
@@ -0,0 +1,19 @@
+import { useQuery } from "@tanstack/react-query"
+import { type WeatherApiResponse } from "./types"
+
+const useGetWeather = (lat: number, lon: number, alt?: number) => {
+ let sanitized_alt = alt
+ if (alt != undefined) {
+ sanitized_alt = alt > 9000 ? 9000 : alt
+ sanitized_alt = sanitized_alt < -500 ? -500 : sanitized_alt
+ }
+
+ const { isLoading, error, data } = useQuery({
+ queryKey: ["citySearch", `${lat}-${lon}`],
+ queryFn: () => fetch(`https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${lat}&lon=${lon}${alt != undefined ? `&altitude=${sanitized_alt}` : ""}`).then((res) => res.json() as Promise