add weather module
This commit is contained in:
389
src/store/weather.ts
Normal file
389
src/store/weather.ts
Normal file
@@ -0,0 +1,389 @@
|
||||
import { create } from "zustand";
|
||||
import { devtools } from "zustand/middleware";
|
||||
import fetchWeatherData from "@/api/weather";
|
||||
|
||||
const iconNumberToPng = {
|
||||
"0": {
|
||||
day: {
|
||||
description: "Sunny",
|
||||
image: "http://openweathermap.org/img/wn/01d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Clear",
|
||||
image: "http://openweathermap.org/img/wn/01n@2x.png",
|
||||
},
|
||||
},
|
||||
"1": {
|
||||
day: {
|
||||
description: "Mainly Sunny",
|
||||
image: "http://openweathermap.org/img/wn/01d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Mainly Clear",
|
||||
image: "http://openweathermap.org/img/wn/01n@2x.png",
|
||||
},
|
||||
},
|
||||
"2": {
|
||||
day: {
|
||||
description: "Partly Cloudy",
|
||||
image: "http://openweathermap.org/img/wn/02d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Partly Cloudy",
|
||||
image: "http://openweathermap.org/img/wn/02n@2x.png",
|
||||
},
|
||||
},
|
||||
"3": {
|
||||
day: {
|
||||
description: "Cloudy",
|
||||
image: "http://openweathermap.org/img/wn/03d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Cloudy",
|
||||
image: "http://openweathermap.org/img/wn/03n@2x.png",
|
||||
},
|
||||
},
|
||||
"45": {
|
||||
day: {
|
||||
description: "Foggy",
|
||||
image: "http://openweathermap.org/img/wn/50d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Foggy",
|
||||
image: "http://openweathermap.org/img/wn/50n@2x.png",
|
||||
},
|
||||
},
|
||||
"48": {
|
||||
day: {
|
||||
description: "Rime Fog",
|
||||
image: "http://openweathermap.org/img/wn/50d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Rime Fog",
|
||||
image: "http://openweathermap.org/img/wn/50n@2x.png",
|
||||
},
|
||||
},
|
||||
"51": {
|
||||
day: {
|
||||
description: "Light Drizzle",
|
||||
image: "http://openweathermap.org/img/wn/09d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Light Drizzle",
|
||||
image: "http://openweathermap.org/img/wn/09n@2x.png",
|
||||
},
|
||||
},
|
||||
"53": {
|
||||
day: {
|
||||
description: "Drizzle",
|
||||
image: "http://openweathermap.org/img/wn/09d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Drizzle",
|
||||
image: "http://openweathermap.org/img/wn/09n@2x.png",
|
||||
},
|
||||
},
|
||||
"55": {
|
||||
day: {
|
||||
description: "Heavy Drizzle",
|
||||
image: "http://openweathermap.org/img/wn/09d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Heavy Drizzle",
|
||||
image: "http://openweathermap.org/img/wn/09n@2x.png",
|
||||
},
|
||||
},
|
||||
"56": {
|
||||
day: {
|
||||
description: "Light Freezing Drizzle",
|
||||
image: "http://openweathermap.org/img/wn/09d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Light Freezing Drizzle",
|
||||
image: "http://openweathermap.org/img/wn/09n@2x.png",
|
||||
},
|
||||
},
|
||||
"57": {
|
||||
day: {
|
||||
description: "Freezing Drizzle",
|
||||
image: "http://openweathermap.org/img/wn/09d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Freezing Drizzle",
|
||||
image: "http://openweathermap.org/img/wn/09n@2x.png",
|
||||
},
|
||||
},
|
||||
"61": {
|
||||
day: {
|
||||
description: "Light Rain",
|
||||
image: "http://openweathermap.org/img/wn/10d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Light Rain",
|
||||
image: "http://openweathermap.org/img/wn/10n@2x.png",
|
||||
},
|
||||
},
|
||||
"63": {
|
||||
day: {
|
||||
description: "Rain",
|
||||
image: "http://openweathermap.org/img/wn/10d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Rain",
|
||||
image: "http://openweathermap.org/img/wn/10n@2x.png",
|
||||
},
|
||||
},
|
||||
"65": {
|
||||
day: {
|
||||
description: "Heavy Rain",
|
||||
image: "http://openweathermap.org/img/wn/10d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Heavy Rain",
|
||||
image: "http://openweathermap.org/img/wn/10n@2x.png",
|
||||
},
|
||||
},
|
||||
"66": {
|
||||
day: {
|
||||
description: "Light Freezing Rain",
|
||||
image: "http://openweathermap.org/img/wn/10d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Light Freezing Rain",
|
||||
image: "http://openweathermap.org/img/wn/10n@2x.png",
|
||||
},
|
||||
},
|
||||
"67": {
|
||||
day: {
|
||||
description: "Freezing Rain",
|
||||
image: "http://openweathermap.org/img/wn/10d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Freezing Rain",
|
||||
image: "http://openweathermap.org/img/wn/10n@2x.png",
|
||||
},
|
||||
},
|
||||
"71": {
|
||||
day: {
|
||||
description: "Light Snow",
|
||||
image: "http://openweathermap.org/img/wn/13d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Light Snow",
|
||||
image: "http://openweathermap.org/img/wn/13n@2x.png",
|
||||
},
|
||||
},
|
||||
"73": {
|
||||
day: {
|
||||
description: "Snow",
|
||||
image: "http://openweathermap.org/img/wn/13d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Snow",
|
||||
image: "http://openweathermap.org/img/wn/13n@2x.png",
|
||||
},
|
||||
},
|
||||
"75": {
|
||||
day: {
|
||||
description: "Heavy Snow",
|
||||
image: "http://openweathermap.org/img/wn/13d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Heavy Snow",
|
||||
image: "http://openweathermap.org/img/wn/13n@2x.png",
|
||||
},
|
||||
},
|
||||
"77": {
|
||||
day: {
|
||||
description: "Snow Grains",
|
||||
image: "http://openweathermap.org/img/wn/13d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Snow Grains",
|
||||
image: "http://openweathermap.org/img/wn/13n@2x.png",
|
||||
},
|
||||
},
|
||||
"80": {
|
||||
day: {
|
||||
description: "Light Showers",
|
||||
image: "http://openweathermap.org/img/wn/09d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Light Showers",
|
||||
image: "http://openweathermap.org/img/wn/09n@2x.png",
|
||||
},
|
||||
},
|
||||
"81": {
|
||||
day: {
|
||||
description: "Showers",
|
||||
image: "http://openweathermap.org/img/wn/09d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Showers",
|
||||
image: "http://openweathermap.org/img/wn/09n@2x.png",
|
||||
},
|
||||
},
|
||||
"82": {
|
||||
day: {
|
||||
description: "Heavy Showers",
|
||||
image: "http://openweathermap.org/img/wn/09d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Heavy Showers",
|
||||
image: "http://openweathermap.org/img/wn/09n@2x.png",
|
||||
},
|
||||
},
|
||||
"85": {
|
||||
day: {
|
||||
description: "Light Snow Showers",
|
||||
image: "http://openweathermap.org/img/wn/13d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Light Snow Showers",
|
||||
image: "http://openweathermap.org/img/wn/13n@2x.png",
|
||||
},
|
||||
},
|
||||
"86": {
|
||||
day: {
|
||||
description: "Snow Showers",
|
||||
image: "http://openweathermap.org/img/wn/13d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Snow Showers",
|
||||
image: "http://openweathermap.org/img/wn/13n@2x.png",
|
||||
},
|
||||
},
|
||||
"95": {
|
||||
day: {
|
||||
description: "Thunderstorm",
|
||||
image: "http://openweathermap.org/img/wn/11d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Thunderstorm",
|
||||
image: "http://openweathermap.org/img/wn/11n@2x.png",
|
||||
},
|
||||
},
|
||||
"96": {
|
||||
day: {
|
||||
description: "Light Thunderstorms With Hail",
|
||||
image: "http://openweathermap.org/img/wn/11d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Light Thunderstorms With Hail",
|
||||
image: "http://openweathermap.org/img/wn/11n@2x.png",
|
||||
},
|
||||
},
|
||||
"99": {
|
||||
day: {
|
||||
description: "Thunderstorm With Hail",
|
||||
image: "http://openweathermap.org/img/wn/11d@2x.png",
|
||||
},
|
||||
night: {
|
||||
description: "Thunderstorm With Hail",
|
||||
image: "http://openweathermap.org/img/wn/11n@2x.png",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const useWeatherStore = create(
|
||||
devtools(
|
||||
(set) => ({
|
||||
weatherData: {},
|
||||
fetchWeatherData: async () => {
|
||||
const data = await fetchWeatherData();
|
||||
|
||||
// Process first location. Add a for-loop for multiple locations or weather models
|
||||
const response = data[0];
|
||||
|
||||
if (response === null) {
|
||||
console.error("Failed to fetch weather data");
|
||||
return;
|
||||
}
|
||||
|
||||
// Attributes for timezone and location
|
||||
const utcOffsetSeconds = response.utcOffsetSeconds();
|
||||
const current = response.current();
|
||||
const hourly = response.hourly();
|
||||
const daily = response.daily();
|
||||
|
||||
if (!current || !hourly || !daily) {
|
||||
console.error("Failed to fetch weather data");
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: The order of weather variables in the URL query and the indices below need to match!
|
||||
const weatherData = {
|
||||
current: {
|
||||
time: current.time(),
|
||||
temperature_2m: current.variables(0)?.value(),
|
||||
precipitation: current.variables(1)?.value(),
|
||||
rain: current.variables(2)?.value(),
|
||||
showers: current.variables(3)?.value(),
|
||||
snowfall: current.variables(4)?.value(),
|
||||
relative_humidity_2m: current.variables(5)?.value(),
|
||||
apparent_temperature: current.variables(6)?.value(),
|
||||
weather_code: current.variables(7)?.value(),
|
||||
cloud_cover: current.variables(8)?.value(),
|
||||
is_day: current.variables(9)?.value(),
|
||||
},
|
||||
hourly: {
|
||||
time: [
|
||||
...Array(
|
||||
(Number(hourly.timeEnd()) -
|
||||
Number(hourly.time())) /
|
||||
hourly.interval(),
|
||||
),
|
||||
].map(
|
||||
(_, i) =>
|
||||
new Date(
|
||||
(Number(hourly.time()) +
|
||||
i * hourly.interval() +
|
||||
utcOffsetSeconds) *
|
||||
1000,
|
||||
),
|
||||
),
|
||||
temperature_2m: hourly.variables(0)?.valuesArray(),
|
||||
precipitation: hourly.variables(1)?.valuesArray(),
|
||||
rain: hourly.variables(2)?.valuesArray(),
|
||||
precipitation_probability: hourly
|
||||
.variables(3)
|
||||
?.valuesArray(),
|
||||
},
|
||||
daily: {
|
||||
time: [
|
||||
...Array(
|
||||
(Number(daily.timeEnd()) -
|
||||
Number(daily.time())) /
|
||||
daily.interval(),
|
||||
),
|
||||
].map(
|
||||
(_, i) =>
|
||||
new Date(
|
||||
(Number(daily.time()) +
|
||||
i * daily.interval() +
|
||||
utcOffsetSeconds) *
|
||||
1000,
|
||||
),
|
||||
),
|
||||
temperature_2m_max: daily.variables(0)?.valuesArray(),
|
||||
temperature_2m_min: daily.variables(1)?.valuesArray(),
|
||||
},
|
||||
};
|
||||
|
||||
const isDay = weatherData.current.is_day === 1;
|
||||
const weatherCode = weatherData.current.weather_code;
|
||||
const url =
|
||||
iconNumberToPng[weatherCode][isDay ? "day" : "night"].image;
|
||||
|
||||
weatherData.current = { ...weatherData.current, icon: url };
|
||||
|
||||
set({ weatherData });
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: "weather-store",
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export { useWeatherStore };
|
||||
Reference in New Issue
Block a user