myweather/src/views/WeatherView.vue
2024-06-08 18:36:44 -05:00

157 lines
3.6 KiB
Vue

<script setup>
import { mapStores } from 'pinia'
import { useWeatherStore } from '../stores/weather'
import { useLocationStore } from '../stores/location'
</script>
<script>
export default {
data() {
return {
coordinates: null,
}
},
computed: {
...mapStores(useWeatherStore, useLocationStore),
panelHeadingTitle() {
if (!this.weatherStore.forecast) {
return "Forecast"
}
let generated = new Date(this.weatherStore.forecast.properties.generatedAt)
generated = generated.toLocaleTimeString('en-US', {timeStyle: 'short'})
return `Forecast @ ${generated}`
},
radarURL() {
if (this.weatherStore.weather) {
const station = this.weatherStore.weather.properties.radarStation
return `https://radar.weather.gov/ridge/standard/${station}_loop.gif`
}
},
},
activated() {
this.fetchWeather()
},
methods: {
coordinatesUpdated(coordinates) {
this.weatherStore.clearWeather()
this.weatherStore.setCoordinates(coordinates)
this.fetchWeather()
},
async fetchWeather() {
if (!this.weatherStore.coordinates) {
this.$router.push('/')
return
}
const forecast = await this.weatherStore.getForecast()
this.coordinates = this.weatherStore.coordinates
},
showHourly(period) {
this.$router.push('/hourly')
},
},
}
</script>
<template>
<main>
<div style="display: flex; flex-direction: column;">
<o-field>
<o-select v-if="weatherStore.weather"
v-model="coordinates"
@update:model-value="coordinatesUpdated">
<option v-for="location in locationStore.locations"
:key="location.coordinates"
:value="location.coordinates">
{{ location.cityState }}
</option>
</o-select>
</o-field>
<nav class="panel weather-panel">
<p class="panel-heading">
{{ panelHeadingTitle }}
</p>
<div class="panel-block">
<div v-if="weatherStore.forecast"
style="display: flex;">
<div v-for="period in weatherStore.forecast.properties.periods"
:key="period.number"
class="weather-period is-size-7 has-text-weight-bold"
:class="{daytime: period.isDaytime}"
@click="showHourly(period)">
<p>{{ period.name }}</p>
<div>
<img :src="period.icon" />
</div>
<p>{{ period.shortForecast }}</p>
<p>
<span v-if="period.isDaytime">Hi</span>
<span v-else>Lo</span>
{{ period.temperature }} &deg; {{ period.temperatureUnit }}
</p>
</div>
</div>
<div v-if="!weatherStore.forecast">
fetching weather data...
</div>
</div>
</nav>
<nav class="panel weather-panel">
<p class="panel-heading">
Radar
</p>
<div class="panel-block">
<img :src="radarURL" />
</div>
</nav>
</div>
</main>
</template>
<style scoped>
.weather-period {
width: 100px;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
background-color: gray;
color: white;
padding: 0.5rem;
}
.weather-period.daytime {
background-color: white;
color: black;
}
</style>