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

View file

@ -1,24 +1,44 @@
<script setup> <script setup>
import { onActivated } from 'vue' import { ref, onActivated } from 'vue'
import { useWeatherStore } from '../stores/weather' import { useWeatherStore } from '../stores/weather'
const weatherStore = useWeatherStore() const weatherStore = useWeatherStore()
const refreshing = ref(false)
onActivated(() => { 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> </script>
<template> <template>
<main> <main>
<o-button variant="primary" <div class="block"
size="small" style="display: flex; align-items: center; justify-content: space-between;">
icon-left="arrow-left" <o-button variant="primary"
@click="$router.push('/weather')"> icon-left="arrow-left"
Back @click="$router.push('/weather')">
</o-button> 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">{{ weatherStore.cityState }}</h5>
<h5 class="is-size-5">Alerts</h5> <h5 class="is-size-5">Alerts</h5>

View file

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

View file

@ -10,7 +10,7 @@ const locationStore = useLocationStore()
const weatherStore = useWeatherStore() const weatherStore = useWeatherStore()
const coordinates = ref(null) const coordinates = ref(null)
const alerts = ref(null) const refreshing = ref(false)
const panelHeadingTitle = computed(() => { const panelHeadingTitle = computed(() => {
@ -25,27 +25,39 @@ const panelHeadingTitle = computed(() => {
onActivated(() => { onActivated(() => {
fetchWeather()
})
function coordinatesUpdated(coords) {
weatherStore.clearWeather()
weatherStore.setCoordinates(coords)
fetchWeather()
}
async function fetchWeather() {
if (!weatherStore.coordinates) { if (!weatherStore.coordinates) {
router.push('/') router.push('/')
return 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 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> <main>
<div style="display: flex; flex-direction: column;"> <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" <o-select v-if="weatherStore.weather"
v-model="coordinates" v-model="coordinates"
@update:model-value="coordinatesUpdated"> @update:model-value="coordinatesUpdated">
@ -74,15 +87,21 @@ function showHourly(period) {
{{ location.cityState }} {{ location.cityState }}
</option> </option>
</o-select> </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" <o-notification variant="warning"
icon="warning" icon="warning"
@click="$router.push('/alerts')" @click="$router.push('/alerts')"
style="cursor: pointer;"> style="cursor: pointer;">
<p class="has-text-weight-bold">Watches In Effect</p> <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> </o-notification>
</div> </div>
@ -101,6 +120,7 @@ function showHourly(period) {
:key="period.number" :key="period.number"
class="weather-period is-size-7 has-text-weight-bold" class="weather-period is-size-7 has-text-weight-bold"
:class="{daytime: period.isDaytime}" :class="{daytime: period.isDaytime}"
style="cursor: pointer;"
@click="showHourly(period)"> @click="showHourly(period)">
<p>{{ period.name }}</p> <p>{{ period.name }}</p>