Convert all view components to use Composition API
might as well start getting used to this new hotness
This commit is contained in:
parent
5e238aa2aa
commit
7a14101e01
6 changed files with 191 additions and 235 deletions
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue