myweather/src/views/WeatherView.vue

174 lines
4.3 KiB
Vue
Raw Normal View History

<script setup>
import { mapStores } from 'pinia'
import { useWeatherStore } from '../stores/weather'
import { useLocationStore } from '../stores/location'
</script>
<script>
export default {
data() {
return {
coordinates: null,
alerts: 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}`
},
},
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
this.alerts = this.weatherStore.alerts
},
getShortForecast(period) {
return period.shortForecast.replace(/Showers And Thunderstorms/g, 'T-storms')
},
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>
<div v-if="alerts?.features?.length">
<o-notification variant="warning"
icon="warning"
@click="$router.push('/alerts')"
style="cursor: pointer;">
<p class="has-text-weight-bold">Watches In Effect</p>
<p>Updated {{ new Date(alerts.updated).toLocaleTimeString('en-US', {timeStyle: 'short'}) }}</p>
</o-notification>
</div>
<nav class="panel weather-panel">
<p class="panel-heading">
{{ panelHeadingTitle }}
</p>
<div class="panel-block">
<div v-if="weatherStore.forecast"
style="display: flex; overflow-x: scroll;">
<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>{{ getShortForecast(period) }}</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>
2024-06-08 18:36:44 -05:00
<nav class="panel weather-panel">
<p class="panel-heading">
Radar
</p>
<div class="panel-block">
<div class="columns">
<div class="column">
<img :src="weatherStore.radarLatestURL" />
</div>
<div class="column">
<img :src="weatherStore.radarLoopURL" />
</div>
</div>
2024-06-08 18:36:44 -05:00
</div>
</nav>
</div>
</main>
</template>
<style scoped>
.weather-period {
width: 100px;
flex-shrink: 0;
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>