Add Vue Router for proper application flow

This commit is contained in:
karl 2022-04-16 23:53:00 +02:00
parent f5adc66f60
commit 773f1b9825
8 changed files with 244 additions and 27 deletions

80
package-lock.json generated
View File

@ -9,7 +9,8 @@
"version": "0.1.0",
"dependencies": {
"core-js": "^3.8.3",
"vue": "^3.2.13"
"vue": "^3.2.13",
"vue-router": "^4.0.14"
},
"devDependencies": {
"@babel/core": "^7.12.16",
@ -2798,6 +2799,11 @@
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
"dev": true
},
"node_modules/@vue/devtools-api": {
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz",
"integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ=="
},
"node_modules/@vue/reactivity": {
"version": "3.2.32",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.32.tgz",
@ -10487,6 +10493,20 @@
"node": ">=8"
}
},
"node_modules/vue-router": {
"version": "4.0.14",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.14.tgz",
"integrity": "sha512-wAO6zF9zxA3u+7AkMPqw9LjoUCjSxfFvINQj3E/DceTt6uEz1XZLraDhdg2EYmvVwTBSGlLYsUw8bDmx0754Mw==",
"dependencies": {
"@vue/devtools-api": "^6.0.0"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/vue-style-loader": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
@ -13038,7 +13058,8 @@
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.4.tgz",
"integrity": "sha512-dBwiD6mT9+V2HTHcwaWE8qFNgTk5I/NUvxYVeUN3Mmmpo4y/1RxXnr7BlKGnaQsTypb2RFk3KowqIJtg7s+E3Q==",
"dev": true
"dev": true,
"requires": {}
},
"@vue/cli-service": {
"version": "5.0.4",
@ -13306,6 +13327,11 @@
}
}
},
"@vue/devtools-api": {
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.1.4.tgz",
"integrity": "sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ=="
},
"@vue/reactivity": {
"version": "3.2.32",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.32.tgz",
@ -13564,13 +13590,15 @@
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
"integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
"dev": true
"dev": true,
"requires": {}
},
"acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true
"dev": true,
"requires": {}
},
"acorn-walk": {
"version": "8.2.0",
@ -13629,7 +13657,8 @@
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
"dev": true
"dev": true,
"requires": {}
},
"ansi-colors": {
"version": "4.1.1",
@ -14453,7 +14482,8 @@
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.2.2.tgz",
"integrity": "sha512-Ufadglr88ZLsrvS11gjeu/40Lw74D9Am/Jpr3LlYm5Q4ZP5KdlUhG+6u2EjyXeZcxmZ2h1ebCKngDjolpeLHpg==",
"dev": true
"dev": true,
"requires": {}
},
"css-loader": {
"version": "6.7.1",
@ -14638,7 +14668,8 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz",
"integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==",
"dev": true
"dev": true,
"requires": {}
},
"csso": {
"version": "4.2.0",
@ -16027,7 +16058,8 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
"dev": true
"dev": true,
"requires": {}
},
"ieee754": {
"version": "1.2.1",
@ -17395,25 +17427,29 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.1.tgz",
"integrity": "sha512-5JscyFmvkUxz/5/+TB3QTTT9Gi9jHkcn8dcmmuN68JQcv3aQg4y88yEHHhwFB52l/NkaJ43O0dbksGMAo49nfQ==",
"dev": true
"dev": true,
"requires": {}
},
"postcss-discard-duplicates": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz",
"integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==",
"dev": true
"dev": true,
"requires": {}
},
"postcss-discard-empty": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz",
"integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==",
"dev": true
"dev": true,
"requires": {}
},
"postcss-discard-overridden": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz",
"integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==",
"dev": true
"dev": true,
"requires": {}
},
"postcss-loader": {
"version": "6.2.1",
@ -17503,7 +17539,8 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
"dev": true
"dev": true,
"requires": {}
},
"postcss-modules-local-by-default": {
"version": "4.0.0",
@ -17538,7 +17575,8 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz",
"integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==",
"dev": true
"dev": true,
"requires": {}
},
"postcss-normalize-display-values": {
"version": "5.1.0",
@ -19017,6 +19055,14 @@
}
}
},
"vue-router": {
"version": "4.0.14",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.14.tgz",
"integrity": "sha512-wAO6zF9zxA3u+7AkMPqw9LjoUCjSxfFvINQj3E/DceTt6uEz1XZLraDhdg2EYmvVwTBSGlLYsUw8bDmx0754Mw==",
"requires": {
"@vue/devtools-api": "^6.0.0"
}
},
"vue-style-loader": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
@ -19338,7 +19384,8 @@
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
"dev": true
"dev": true,
"requires": {}
}
}
},
@ -19465,7 +19512,8 @@
"version": "7.5.7",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
"integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
"dev": true
"dev": true,
"requires": {}
},
"y18n": {
"version": "5.0.8",

View File

@ -9,7 +9,8 @@
},
"dependencies": {
"core-js": "^3.8.3",
"vue": "^3.2.13"
"vue": "^3.2.13",
"vue-router": "^4.0.14"
},
"devDependencies": {
"@babel/core": "^7.12.16",

View File

@ -1,17 +1,21 @@
<template>
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
<h1>Sunscreen</h1>
<router-view />
<div class="footer">
<p>
Source for sun time calculations: Sánchez-Pérez, J.F., Vicente-Agullo, D.,
Barberá, M. et al. Relationship between ultraviolet index (UVI) and
first-, second- and third-degree sunburn using the Probit methodology. Sci
Rep 9, 733 (2019). https://doi.org/10.1038/s41598-018-36850-x
</p>
<p>Source for weather data: OpenWeatherMap. https://openweathermap.org/</p>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
name: "App",
};
</script>
<style>
@ -23,4 +27,14 @@ export default {
color: #2c3e50;
margin-top: 60px;
}
.footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
background-color: lightyellow;
text-align: left;
padding: 1em;
}
</style>

45
src/StartPage.vue Normal file
View File

@ -0,0 +1,45 @@
<template>
<form :action="urlAction">
<div>
Select skin type:
<select v-model="skinType" required>
<option disabled value="">Skin Type:</option>
<option value="0">I (Pale)</option>
<option value="1">II (Fair)</option>
<option value="2">III (Light Brown)</option>
<option value="3">IV (Olive Brown)</option>
</select>
</div>
<div>
Location: <input type="number" v-model="lat" step="any" required /><input
type="number"
v-model="lon"
step="any"
required
/>
</div>
<button type="submit">Go</button>
</form>
</template>
<script>
export default {
name: "StartPage",
data() {
return {
skinType: "",
lat: "",
lon: "",
};
},
computed: {
urlAction() {
return "/" + this.skinType + "/" + +this.lat + "/" + this.lon + "/";
},
},
};
</script>

21
src/SunscreenPage.vue Normal file
View File

@ -0,0 +1,21 @@
<template>
<SunTime :skin="skin" :lat="lat" :lon="lon" />
</template>
<script>
import SunTime from "./components/SunTime.vue";
export default {
name: "SunscreenPage",
components: {
SunTime,
},
data: function () {
return {
skin: this.$route.params.skin,
lat: this.$route.params.lat,
lon: this.$route.params.lon,
};
},
};
</script>

View File

@ -0,0 +1,62 @@
<template>
<div v-if="loaded">
<div v-if="minutesToBurn < 100">
<div style="font-size: 12em">{{ minutesToBurn }}</div>
<div style="font-size: 2em">minutes until sunburn</div>
</div>
<div v-else>
<div style="font-size: 8em">No risk!</div>
</div>
</div>
</template>
<script>
// Calculate the intensity and then the dose; compare them to the dose limits
// Source: https://www.nature.com/articles/s41598-018-36850-x
function get_dose_per_minute_for_uv_index(uv_index) {
let uv_intensity = 15.1 * uv_index + 35.5; // W/m²
uv_intensity /= 1000.0; // kW/m²
let dose_per_second = Math.pow(uv_intensity, 4 / 3);
return dose_per_second * 60.0;
}
export default {
name: "SunTime",
props: {
skin: String,
lat: String,
lon: String,
},
data() {
return {
minutesToBurn: 0,
loaded: false,
};
},
async mounted() {
// Dosage where sunburn occurs for each skin type (I, II, III, IV)
// Source: https://www.nature.com/articles/s41598-018-36850-x
let sunburn_begin_doses = [84.9, 115, 143, 195];
let apiKey = "db1a2f091413e833154a6de21adb3076";
let openweathermap_onecall = await fetch(
`https://api.openweathermap.org/data/2.5/onecall?lat=${this.lat}&lon=${this.lon}&exclude=hourly,daily&appid=${apiKey}`
);
openweathermap_onecall = await openweathermap_onecall.json();
console.log(openweathermap_onecall);
let current_uvi = openweathermap_onecall["current"]["uvi"];
this.minutesToBurn = Math.floor(
sunburn_begin_doses[this.skin] /
get_dose_per_minute_for_uv_index(current_uvi)
);
this.loaded = true;
},
};
</script>

View File

@ -1,4 +1,7 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).mount('#app')
createApp(App)
.use(router)
.mount('#app')

23
src/router/index.js Normal file
View File

@ -0,0 +1,23 @@
import { createWebHistory, createRouter } from "vue-router";
import StartPage from "@/StartPage.vue";
import SunscreenPage from "@/SunscreenPage.vue";
const routes = [
{
path: "/",
name: "StartPage",
component: StartPage,
},
{
path: "/:skin/:lat/:lon",
name: "SunscreenPage",
component: SunscreenPage,
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;