import { defineStore } from 'pinia' const getDefaults = () => { const coordinates = localStorage.getItem('weather.coordinates') const cityState = localStorage.getItem('weather.cityState') return { coordinates, cityState, weather: null, alerts: null, forecast: null, radarLatestURL: null, radarLoopURL: null, } } export const useWeatherStore = defineStore('weather', { state: () => { return getDefaults() }, actions: { clearWeather(keepCoordinates) { if (!keepCoordinates) { this.setCoordinates(null) this.setCityState(null) } this.setWeather(null) this.setForecast(null) this.radarLatestURL = null this.radarLoopURL = null this.alerts = null }, async getWeather() { if (!this.weather) { let url let response url = `https://api.weather.gov/points/${this.coordinates}` response = await fetch(url) const weather = await response.json() if (weather.status == 404) { throw new Error(`Data not found for ${this.coordinates}`) } const city = weather.properties.relativeLocation.properties.city const state = weather.properties.relativeLocation.properties.state const cityState = `${city}, ${state}` if (this.cityState != cityState) { this.setCityState(cityState) } const station = weather.properties.radarStation this.radarLatestURL = `https://radar.weather.gov/ridge/standard/${station}_0.gif` this.radarLoopURL = `https://radar.weather.gov/ridge/standard/${station}_loop.gif` this.setWeather(weather) // fetch zone to get its official id url = weather.properties.forecastZone response = await fetch(url) const zone = await response.json() // fetch alerts for zone url = `https://api.weather.gov/alerts/active/zone/${zone.properties.id}` response = await fetch(url) const zoneAlerts = await response.json() // fetch county to get its official id url = weather.properties.county response = await fetch(url) const county = await response.json() // fetch alerts for county url = `https://api.weather.gov/alerts/active/zone/${county.properties.id}` response = await fetch(url) const countyAlerts = await response.json() const newAlerts = {} // use latest timestamp from either zone or county newAlerts.updated = zoneAlerts.updated if (countyAlerts.updated > zoneAlerts.updated) { newAlerts.updated = countyAlerts.updated } // collect all alert "features" but de-duplicate them newAlerts.features = {} for (let feature of zoneAlerts.features) { newAlerts.features[feature.properties.id] = feature } for (let feature of countyAlerts.features) { newAlerts.features[feature.properties.id] = feature } newAlerts.features = Object.values(newAlerts.features) // put "likely" before "possible" alerts newAlerts.features.sort((a, b) => { if (a.properties.certainty == 'Likely' && b.properties.certainty != 'Likely') { return -1 } if (a.properties.certainty != 'Likely' && b.properties.certainty == 'Likely') { return 1 } // if (a.properties.certainty == b.properties.certainty) { // return 0 // } // TODO: what else should this do? return 0 }) // we have our final alerts this.alerts = newAlerts } return this.weather }, async getForecast() { if (!this.forecast) { const weather = await this.getWeather(this.coordinates) const url = weather.properties.forecast const response = await fetch(url) const forecast = await response.json() this.setForecast(forecast) } return this.forecast }, setCoordinates(value) { this.coordinates = value localStorage.setItem('weather.coordinates', value) }, setCityState(value) { this.cityState = value localStorage.setItem('weather.cityState', value) }, setWeather(value) { this.weather = value }, setForecast(value) { this.forecast = value }, }, })