Convert all view components to use Composition API

might as well start getting used to this new hotness
This commit is contained in:
Lance Edgar 2024-06-09 15:45:38 -05:00
parent 5e238aa2aa
commit 7a14101e01
6 changed files with 191 additions and 235 deletions

View file

@ -2,17 +2,6 @@
import appsettings from '../appsettings' import appsettings from '../appsettings'
</script> </script>
<script>
export default {
data() {
return {
appsettings,
}
},
}
</script>
<template> <template>
<div class="about"> <div class="about">
<h4 class="is-size-4">{{ appsettings.appTitle }} {{ appsettings.appVersion }}</h4> <h4 class="is-size-4">{{ appsettings.appTitle }} {{ appsettings.appVersion }}</h4>

View file

@ -1,19 +1,13 @@
<script setup> <script setup>
import { mapStores } from 'pinia' import { onActivated } from 'vue'
import { useWeatherStore } from '../stores/weather' import { useWeatherStore } from '../stores/weather'
</script>
<script> const weatherStore = useWeatherStore()
export default {
computed: { onActivated(() => {
...mapStores(useWeatherStore), weatherStore.getWeather()
}, })
activated() {
this.weatherStore.getWeather()
},
}
</script> </script>
<template> <template>

View file

@ -1,22 +1,12 @@
<script setup> <script setup>
import { mapStores } from 'pinia'
import { useLocationStore } from '../stores/location' import { useLocationStore } from '../stores/location'
</script>
<script> const locationStore = useLocationStore()
export default {
computed: { function deleteLocation(location) {
...mapStores(useLocationStore), locationStore.removeLocation(location)
},
methods: {
deleteLocation(location) {
this.locationStore.removeLocation(location)
},
},
} }
</script> </script>
<template> <template>

View file

@ -1,109 +1,107 @@
<script setup> <script setup>
import { mapStores } from 'pinia' import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { useWeatherStore } from '../stores/weather' import { useWeatherStore } from '../stores/weather'
import { useLocationStore } from '../stores/location' import { useLocationStore } from '../stores/location'
</script> import { useOruga } from '@oruga-ui/oruga-next'
<script>
export default {
data() { const router = useRouter()
return { const locationStore = useLocationStore()
coordinates: null, const weatherStore = useWeatherStore()
loading: false, const oruga = useOruga()
locationAccessBlocked: false,
const coordinates = ref(null)
const coordinatesInput = ref()
const loading = ref(false)
const locationAccessBlocked = ref(false)
function useCurrentLocation() {
if (locationAccessBlocked.value) {
alert("You must refresh the page first, then try again.")
return
}
navigator.geolocation.getCurrentPosition(loc => {
coordinates.value = `${loc.coords.latitude},${loc.coords.longitude}`
loadCoordinates()
}, error => {
if (error.code == 1) { // PERMISSION_DENIED
locationAccessBlocked.value = true
} }
}, alert(`error.code = ${error.code}\n\n${error.message}`)
})
computed: {
...mapStores(useWeatherStore, useLocationStore),
},
methods: {
useCurrentLocation() {
if (this.locationAccessBlocked) {
alert("You must refresh the page first, then try again.")
return
}
navigator.geolocation.getCurrentPosition(loc => {
this.coordinates = `${loc.coords.latitude},${loc.coords.longitude}`
this.loadCoordinates()
}, error => {
if (error.code == 1) { // PERMISSION_DENIED
this.locationAccessBlocked = true
}
alert(`error.code = ${error.code}\n\n${error.message}`)
})
},
editLocations() {
this.$router.push('/edit-list')
},
async loadCoordinates() {
if (!this.coordinates) {
this.$refs.coordinates.focus()
return
}
const parts = this.coordinates.split(/(?: +| *\, *)/)
const pattern = /^ *-?\d+(?:\.\d+)? *$/
if (parts.length != 2
|| !parts[0].match(pattern)
|| !parts[1].match(pattern)) {
this.$oruga.notification.open({
variant: 'warning',
message: "Coordinates are not valid.",
position: 'bottom',
})
this.$refs.coordinates.focus()
return
}
this.coordinates = `${parts[0]},${parts[1]}`
this.loading = true
const url = `https://api.weather.gov/points/${this.coordinates}`
const response = await fetch(url)
const weather = await response.json()
this.loading = false
if (weather.status == 404) {
this.$oruga.notification.open({
variant: 'warning',
message: weather.title || "Data not found!",
position: 'bottom',
})
return
}
let coords = weather.geometry.coordinates
coords = `${coords[1].toFixed(4)},${coords[0].toFixed(4)}`
const city = weather.properties.relativeLocation.properties.city
const state = weather.properties.relativeLocation.properties.state
const cityState = `${city}, ${state}`
this.locationStore.addLocation(coords, cityState)
this.weatherStore.setCoordinates(coords)
this.weatherStore.setCityState(cityState)
this.weatherStore.setWeather(weather)
// clear this so user sees empty input when they return
this.coordinates = null
this.$router.push('/weather')
},
showWeather(location) {
this.weatherStore.clearWeather()
this.weatherStore.setCoordinates(location.coordinates)
this.weatherStore.setCityState(location.cityState)
this.$router.push('/weather')
},
},
} }
function editLocations() {
router.push('/edit-list')
}
async function loadCoordinates() {
if (!coordinates.value) {
coordinatesInput.value.focus()
return
}
const parts = coordinates.value.split(/(?: +| *\, *)/)
const pattern = /^ *-?\d+(?:\.\d+)? *$/
if (parts.length != 2
|| !parts[0].match(pattern)
|| !parts[1].match(pattern)) {
oruga.notification.open({
variant: 'warning',
message: "Coordinates are not valid.",
position: 'bottom',
})
coordinatesInput.value.focus()
return
}
coordinates.value = `${parts[0]},${parts[1]}`
loading.value = true
const url = `https://api.weather.gov/points/${coordinates.value}`
const response = await fetch(url)
const weather = await response.json()
loading.value = false
if (weather.status == 404) {
oruga.notification.open({
variant: 'warning',
message: weather.title || "Data not found!",
position: 'bottom',
})
return
}
let coords = weather.geometry.coordinates
coords = `${coords[1].toFixed(4)},${coords[0].toFixed(4)}`
const city = weather.properties.relativeLocation.properties.city
const state = weather.properties.relativeLocation.properties.state
const cityState = `${city}, ${state}`
locationStore.addLocation(coords, cityState)
weatherStore.setCoordinates(coords)
weatherStore.setCityState(cityState)
weatherStore.setWeather(weather)
// clear this so user sees empty input when they return
coordinates.value = null
router.push('/weather')
}
function showWeather(location) {
weatherStore.clearWeather()
weatherStore.setCoordinates(location.coordinates)
weatherStore.setCityState(location.cityState)
router.push('/weather')
}
</script> </script>
<template> <template>
@ -112,7 +110,7 @@ export default {
<o-field grouped> <o-field grouped>
<o-input v-model="coordinates" <o-input v-model="coordinates"
ref="coordinates" ref="coordinatesInput"
placeholder="coordinates" placeholder="coordinates"
clearable /> clearable />
<o-button variant="primary" <o-button variant="primary"

View file

@ -1,65 +1,53 @@
<script setup> <script setup>
import { mapStores } from 'pinia' import { ref, onActivated } from 'vue'
import { useWeatherStore } from '../stores/weather' import { useWeatherStore } from '../stores/weather'
</script>
<script>
export default {
data() { const weatherStore = useWeatherStore()
return {
coordinates: null,
hourly: null,
chunks: [],
}
},
computed: { const coordinates = ref(null)
...mapStores(useWeatherStore), const hourly = ref(null)
}, const chunks = ref([])
activated() { onActivated(() => {
if (this.coordinates != this.weatherStore.coordinates) { if (coordinates.value != weatherStore.coordinates) {
this.hourly = null hourly.value = null
this.chunks = [] chunks.value = []
this.fetchHourly() fetchHourly()
} }
}, })
methods: { async function fetchHourly() {
async fetchHourly() { const weather = await weatherStore.getWeather()
coordinates.value = weatherStore.coordinates
const weather = await this.weatherStore.getWeather() const url = weather.properties.forecastHourly
this.coordinates = this.weatherStore.coordinates const response = await fetch(url)
hourly.value = await response.json()
const url = weather.properties.forecastHourly chunks.value = []
const response = await fetch(url) let chunk = null
this.hourly = await response.json() for (let period of hourly.value.properties.periods.slice(0, 12)) {
const date = new Date(period.startTime).toLocaleDateString('en-US', {
this.chunks = [] dateStyle: 'full',
let chunk = null })
for (let period of this.hourly.properties.periods.slice(0, 12)) { if (!chunk || chunk.date != date) {
const date = new Date(period.startTime).toLocaleDateString('en-US', { chunk = {
dateStyle: 'full', date,
}) periods: [],
if (!chunk || chunk.date != date) {
chunk = {
date,
periods: [],
}
this.chunks.push(chunk)
}
chunk.periods.push(period)
} }
}, chunks.value.push(chunk)
}
renderTime(period) { chunk.periods.push(period)
const date = new Date(period.startTime) }
return date.toLocaleTimeString('en-US', {timeStyle: 'short'})
},
},
} }
function renderTime(period) {
const date = new Date(period.startTime)
return date.toLocaleTimeString('en-US', {timeStyle: 'short'})
}
</script> </script>
<template> <template>

View file

@ -1,66 +1,63 @@
<script setup> <script setup>
import { mapStores } from 'pinia' import { ref, computed, onActivated } from 'vue'
import { useRouter } from 'vue-router'
import { useWeatherStore } from '../stores/weather' import { useWeatherStore } from '../stores/weather'
import { useLocationStore } from '../stores/location' import { useLocationStore } from '../stores/location'
</script>
<script>
export default {
data() { const router = useRouter()
return { const locationStore = useLocationStore()
coordinates: null, const weatherStore = useWeatherStore()
alerts: null,
}
},
computed: { const coordinates = ref(null)
...mapStores(useWeatherStore, useLocationStore), const alerts = ref(null)
panelHeadingTitle() {
if (!this.weatherStore.forecast) {
return "Forecast"
}
let generated = new Date(this.weatherStore.forecast.properties.generatedAt) const panelHeadingTitle = computed(() => {
generated = generated.toLocaleTimeString('en-US', {timeStyle: 'short'}) if (!weatherStore.forecast) {
return `Forecast @ ${generated}` return "Forecast"
}, }
},
activated() { let generated = new Date(weatherStore.forecast.properties.generatedAt)
this.fetchWeather() generated = generated.toLocaleTimeString('en-US', {timeStyle: 'short'})
}, return `Forecast @ ${generated}`
})
methods: {
coordinatesUpdated(coordinates) { onActivated(() => {
this.weatherStore.clearWeather() fetchWeather()
this.weatherStore.setCoordinates(coordinates) })
this.fetchWeather()
},
async fetchWeather() {
if (!this.weatherStore.coordinates) { function coordinatesUpdated(coords) {
this.$router.push('/') weatherStore.clearWeather()
return weatherStore.setCoordinates(coords)
} fetchWeather()
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')
},
},
} }
async function fetchWeather() {
if (!weatherStore.coordinates) {
router.push('/')
return
}
const forecast = await weatherStore.getForecast()
coordinates.value = weatherStore.coordinates
alerts.value = weatherStore.alerts
}
function getShortForecast(period) {
return period.shortForecast.replace(/Showers And Thunderstorms/g, 'T-storms')
}
function showHourly(period) {
router.push('/hourly')
}
</script> </script>
<template> <template>