From 043757bffdb39c0760c0d86e2d93d4d7c9d11f54 Mon Sep 17 00:00:00 2001 From: Arthur DANJOU Date: Wed, 4 Sep 2024 22:30:58 +0200 Subject: [PATCH] Add weather --- app/components/App/Tab.vue | 2 +- app/components/App/Weather.vue | 82 ++++++++++++++++++++++++++++++++++ app/pages/index.vue | 1 + nuxt.config.ts | 4 ++ server/api/weather.get.ts | 35 ++++++++++----- types/types.ts | 15 ++++++- 6 files changed, 125 insertions(+), 14 deletions(-) create mode 100644 app/components/App/Weather.vue diff --git a/app/components/App/Tab.vue b/app/components/App/Tab.vue index 6a24391..5196eaf 100644 --- a/app/components/App/Tab.vue +++ b/app/components/App/Tab.vue @@ -59,7 +59,7 @@ function visitLink(clickType: 'self' | 'extern') { +import type { WeatherType } from '~~/types/types' + +const { coords, error } = useGeolocation() + +const { data, status, refresh } = await useAsyncData(async () => await useRequestFetch()('/api/weather', { + method: 'GET', + query: { + lon: coords.value.longitude, + lat: coords.value.latitude, + }, +})) + +watchOnce(coords, async () => await refresh()) + +const getIcon = computed(() => { + if (!data.value) + return 'i-ph:cloud-fog-duotone' + switch (data.value.weather.type.toLowerCase()) { + case 'clouds': + return 'i-ph:cloud-duotone' + case 'rain': + return 'i-ph:cloud-rain-duotone' + case 'drizzle': + return 'i-ph:cloud-snow-duotone' + case 'clear': + return 'i-ph:sun-duotone' + case 'snow': + return 'i-ph:cloud-snow-duotone' + case 'thunderstorm': + return 'i-ph:cloud-lightning-duotone' + default: + return 'i-ph:cloud-fog-duotone' + } +}) + + + diff --git a/app/pages/index.vue b/app/pages/index.vue index 0fd1b6b..3f8e31a 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -118,6 +118,7 @@ defineShortcuts({ +
{ +export default defineEventHandler(async (event) => { const config = useRuntimeConfig(event) + const { user } = await requireUserSession(event) + const query = getQuery(event) + + if (Number(query.lon) === Infinity || Number(query.lat) === Infinity) { + return createError('Invalid coordinates') + } const openWeather = await $fetch('https://api.openweathermap.org/data/2.5/weather', { params: { - lat: config.openWeather.lat, - lon: config.openWeather.lon, + lon: query.lon, + lat: query.lat, appid: config.openWeather.apiKey, - lang: config.openWeather.lang, + lang: user.language.split('-')[0] ?? 'en', units: config.openWeather.units, }, }) + return { - weather: openWeather.weather[0].description, + weather: { + type: openWeather.weather[0].main, + description: openWeather.weather[0].description, + }, city: openWeather.name, - temp: openWeather.main.feels_like, - } -}, { - maxAge: 60 * 60, // 1 hour - name: 'weather', + temp: { + feels_like: openWeather.main.feels_like, + min: openWeather.main.temp_min, + max: openWeather.main.temp_max, + humidity: openWeather.main.humidity, + }, + wind: openWeather.wind.speed, + } as WeatherType }) diff --git a/types/types.ts b/types/types.ts index ad23283..d9b6340 100644 --- a/types/types.ts +++ b/types/types.ts @@ -80,11 +80,16 @@ export const UpdateUserSchemaType = z.infer export interface OpenWeatherType { weather: Array<{ + main: string description: string }> - main: { + temp: { feels_like: number + temp_min: number + temp_max: number + humidity: number } + wind: { speed: number } name: string } @@ -94,7 +99,13 @@ export interface WeatherType { type: string description: string } - temp: number + temp: { + feels_like: number + min: number + max: number + humidity: number + } + wind: number } export const locales = [