Add refresh buttons to weather data pages

This commit is contained in:
Lance Edgar 2024-06-09 16:27:04 -05:00
parent 7a14101e01
commit a1f84465cc
4 changed files with 106 additions and 43 deletions

View file

@ -26,9 +26,11 @@ export const useWeatherStore = defineStore('weather', {
actions: {
clearWeather() {
clearWeather(keepCoordinates) {
if (!keepCoordinates) {
this.setCoordinates(null)
this.setCityState(null)
}
this.setWeather(null)
this.setForecast(null)
this.radarLatestURL = null
@ -103,10 +105,10 @@ export const useWeatherStore = defineStore('weather', {
// put "likely" before "possible" alerts
newAlerts.features.sort((a, b) => {
if (a.properties.certainty == 'Likely' && b.properties.certainty == 'Possible') {
if (a.properties.certainty == 'Likely' && b.properties.certainty != 'Likely') {
return -1
}
if (a.properties.certainty == 'Possible' && b.properties.certainty == 'Likely') {
if (a.properties.certainty != 'Likely' && b.properties.certainty == 'Likely') {
return 1
}

View file

@ -1,24 +1,44 @@
<script setup>
import { onActivated } from 'vue'
import { ref, onActivated } from 'vue'
import { useWeatherStore } from '../stores/weather'
const weatherStore = useWeatherStore()
const refreshing = ref(false)
onActivated(() => {
weatherStore.getWeather()
refreshing.value = true
weatherStore.getWeather().then(() => {
refreshing.value = false
})
})
async function refreshAlerts() {
refreshing.value = true
weatherStore.clearWeather(true)
await weatherStore.getWeather()
refreshing.value = false
}
</script>
<template>
<main>
<div class="block"
style="display: flex; align-items: center; justify-content: space-between;">
<o-button variant="primary"
size="small"
icon-left="arrow-left"
@click="$router.push('/weather')">
Back
</o-button>
<o-button variant="primary"
icon-left="refresh"
@click="refreshAlerts()"
:disabled="refreshing">
{{ refreshing ? "Refreshing" : "Refresh" }}
</o-button>
</div>
<h5 class="is-size-5">{{ weatherStore.cityState }}</h5>
<h5 class="is-size-5">Alerts</h5>

View file

@ -6,14 +6,17 @@ import { useWeatherStore } from '../stores/weather'
const weatherStore = useWeatherStore()
const coordinates = ref(null)
const hourly = ref(null)
const chunks = ref([])
const refreshing = ref(false)
onActivated(() => {
if (coordinates.value != weatherStore.coordinates) {
hourly.value = null
refreshing.value = true
chunks.value = []
fetchHourly()
fetchHourly().then(() => {
refreshing.value = false
})
}
})
@ -24,11 +27,11 @@ async function fetchHourly() {
const url = weather.properties.forecastHourly
const response = await fetch(url)
hourly.value = await response.json()
const hourly = await response.json()
chunks.value = []
let chunk = null
for (let period of hourly.value.properties.periods.slice(0, 12)) {
for (let period of hourly.properties.periods.slice(0, 12)) {
const date = new Date(period.startTime).toLocaleDateString('en-US', {
dateStyle: 'full',
})
@ -43,6 +46,16 @@ async function fetchHourly() {
}
}
async function refreshHourly() {
refreshing.value = true
weatherStore.clearWeather(true)
chunks.value = []
await fetchHourly()
refreshing.value = false
}
function renderTime(period) {
const date = new Date(period.startTime)
return date.toLocaleTimeString('en-US', {timeStyle: 'short'})
@ -53,12 +66,20 @@ function renderTime(period) {
<template>
<main>
<div class="block"
style="display: flex; align-items: center; justify-content: space-between;">
<o-button variant="primary"
size="small"
icon-left="arrow-left"
@click="$router.push('/weather')">
Back
</o-button>
<o-button variant="primary"
icon-left="refresh"
@click="refreshHourly()"
:disabled="refreshing">
{{ refreshing ? "Refreshing" : "Refresh" }}
</o-button>
</div>
<h5 class="is-size-5">{{ weatherStore.cityState }}</h5>
<br />

View file

@ -10,7 +10,7 @@ const locationStore = useLocationStore()
const weatherStore = useWeatherStore()
const coordinates = ref(null)
const alerts = ref(null)
const refreshing = ref(false)
const panelHeadingTitle = computed(() => {
@ -25,27 +25,39 @@ const panelHeadingTitle = computed(() => {
onActivated(() => {
fetchWeather()
})
function coordinatesUpdated(coords) {
weatherStore.clearWeather()
weatherStore.setCoordinates(coords)
fetchWeather()
}
async function fetchWeather() {
if (!weatherStore.coordinates) {
router.push('/')
return
}
const forecast = await weatherStore.getForecast()
refreshing.value = true
fetchWeather().then(() => {
refreshing.value = false
})
})
async function coordinatesUpdated(coords) {
refreshing.value = true
weatherStore.clearWeather()
weatherStore.setCoordinates(coords)
await fetchWeather()
refreshing.value = false
}
async function fetchWeather() {
await weatherStore.getForecast()
coordinates.value = weatherStore.coordinates
alerts.value = weatherStore.alerts
}
async function refreshWeather() {
refreshing.value = true
weatherStore.clearWeather(true)
await fetchWeather()
refreshing.value = false
}
@ -64,7 +76,8 @@ function showHourly(period) {
<main>
<div style="display: flex; flex-direction: column;">
<o-field>
<div class="block"
style="display: flex; justify-content: space-between; align-items: center;">
<o-select v-if="weatherStore.weather"
v-model="coordinates"
@update:model-value="coordinatesUpdated">
@ -74,15 +87,21 @@ function showHourly(period) {
{{ location.cityState }}
</option>
</o-select>
</o-field>
<o-button variant="primary"
icon-left="refresh"
@click="refreshWeather()"
:disabled="refreshing">
{{ refreshing ? "Refreshing" : "Refresh" }}
</o-button>
</div>
<div v-if="alerts?.features?.length">
<div v-if="weatherStore.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>
<p>Updated {{ new Date(weatherStore.alerts.updated).toLocaleTimeString('en-US', {timeStyle: 'short'}) }}</p>
</o-notification>
</div>
@ -101,6 +120,7 @@ function showHourly(period) {
:key="period.number"
class="weather-period is-size-7 has-text-weight-bold"
:class="{daytime: period.isDaytime}"
style="cursor: pointer;"
@click="showHourly(period)">
<p>{{ period.name }}</p>