added stuff
parent
e4e38b7605
commit
07afa7b356
File diff suppressed because it is too large
Load Diff
|
@ -8,8 +8,10 @@
|
|||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.0",
|
||||
"core-js": "^2.6.5",
|
||||
"vue": "^2.6.10",
|
||||
"vue-qrcode-reader": "^2.0.4",
|
||||
"vue-router": "^3.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
121
src/App.vue
121
src/App.vue
|
@ -1,31 +1,120 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<div id="nav">
|
||||
<router-link to="/">Home</router-link> |
|
||||
<router-link to="/about">About</router-link>
|
||||
</div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
font-family: "Avenir", Helvetica, Arial, sans-serif;
|
||||
@font-face {
|
||||
font-family: "syne";
|
||||
src: url("./assets/fonts/syne-bold-webfont.woff2") format("woff2"),
|
||||
url("./assets/fonts/syne-bold-webfont.woff") format("woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "syne";
|
||||
src: url("./assets/fonts/syne-extra-webfont.woff2") format("woff2"),
|
||||
url("./assets/fonts/syne-extra-webfont.woff") format("woff");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "syne";
|
||||
src: url("./assets/fonts/syne-italic-webfont.woff2") format("woff2"),
|
||||
url("./assets/fonts/syne-italic-webfont.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "synemono";
|
||||
src: url("./assets/fonts/syne-mono-webfont.woff2") format("woff2"),
|
||||
url("./assets/fonts/syne-mono-webfont.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "syne";
|
||||
src: url("./assets/fonts/syne-regular-webfont.woff2") format("woff2"),
|
||||
url("./assets/fonts/syne-regular-webfont.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Material Icons";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local("Material Icons"), local("MaterialIcons-Regular"),
|
||||
url("./assets/fonts/MaterialIcons-Regular.woff2") format("woff2"),
|
||||
url("./assets/fonts/MaterialIcons-Regular.woff") format("woff"),
|
||||
url("./assets/fonts/MaterialIcons-Regular.ttf") format("truetype");
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
font-family: "Material Icons";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px; /* Preferred icon size */
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
text-transform: none;
|
||||
letter-spacing: normal;
|
||||
word-wrap: normal;
|
||||
white-space: nowrap;
|
||||
direction: ltr;
|
||||
|
||||
/* Support for all WebKit browsers. */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
/* Support for Safari and Chrome. */
|
||||
text-rendering: optimizeLegibility;
|
||||
|
||||
/* Support for Firefox. */
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
/* Support for IE. */
|
||||
font-feature-settings: "liga";
|
||||
}
|
||||
|
||||
:root {
|
||||
--yellow-ofo: #ffe706;
|
||||
--yellow-ofo-rgb: 253, 230, 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,
|
||||
Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji,
|
||||
Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #212529;
|
||||
text-align: left;
|
||||
background-color: var(--yellow-ofo);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
}
|
||||
#nav {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
#nav a {
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#nav a.router-link-exact-active {
|
||||
color: #42b983;
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.camera .wrapper .inside {
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 34 KiB |
|
@ -1,114 +0,0 @@
|
|||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br />
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-cli documentation</a
|
||||
>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>babel</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>eslint</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
|
||||
>Forum</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
|
||||
>Community Chat</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
|
||||
>Twitter</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-router</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-devtools#vue-devtools"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>vue-devtools</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-loader</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/awesome-vue"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>awesome-vue</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "HelloWorld",
|
||||
props: {
|
||||
msg: String
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
|
@ -14,13 +14,9 @@ export default new Router({
|
|||
component: Home
|
||||
},
|
||||
{
|
||||
path: "/about",
|
||||
name: "about",
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "about" */ "./views/About.vue")
|
||||
path: "/unlock",
|
||||
name: "unlock",
|
||||
component: () => import("./views/Unlock.vue")
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
<template>
|
||||
<div class="about">
|
||||
<h1>This is an about page</h1>
|
||||
</div>
|
||||
</template>
|
|
@ -1,18 +1,68 @@
|
|||
<template>
|
||||
<div class="home">
|
||||
<img alt="Vue logo" src="../assets/logo.png" />
|
||||
<HelloWorld msg="Welcome to Your Vue.js App" />
|
||||
<img class="logo" alt="logo" src="../assets/logo.png" />
|
||||
<h1><router-link to="/unlock">sblocca</router-link></h1>
|
||||
<p>
|
||||
verifica che la bici sia ancora carica 🔋. Se, usando i pulsanti viene
|
||||
emesso un <em>bip</em> 🔊, procedi con lo sblocco 🔓. Altrimenti utilizza
|
||||
il
|
||||
<a
|
||||
href="https://upload.disroot.org/r/uWcukzZ5#s/84kbXpkxXpX3kR2x1KwyVNX2Us93Zy1tSNC3oZ864="
|
||||
>metodo manuale</a
|
||||
>
|
||||
🛠️.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// @ is an alias to /src
|
||||
import HelloWorld from "@/components/HelloWorld.vue";
|
||||
|
||||
export default {
|
||||
name: "home",
|
||||
components: {
|
||||
HelloWorld
|
||||
}
|
||||
name: "home"
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.home {
|
||||
/* display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center; */
|
||||
max-width: 500px;
|
||||
height: 100%;
|
||||
padding: 15px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.logo {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* img {
|
||||
max-width: 100%;
|
||||
} */
|
||||
|
||||
h1 {
|
||||
font-family: "syne", serif;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
padding: 15px;
|
||||
border: 3px solid black;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
p a {
|
||||
color: black;
|
||||
}
|
||||
|
||||
p a:hover {
|
||||
color: black;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<h2 class="inquadra">
|
||||
Inquadra il qrcode
|
||||
</h2>
|
||||
<div class="camera">
|
||||
<qrcode-drop-zone @decode="onDecode" @init="logErrors">
|
||||
<qrcode-stream :camera="camera" @decode="onDecode" @init="onInit" />
|
||||
</qrcode-drop-zone>
|
||||
|
||||
<qrcode-capture v-if="noStreamApiSupport" @decode="onDecode" />
|
||||
</div>
|
||||
<p v-if="isInvalid">non è un qrcode di ofo 😟</p>
|
||||
<p v-if="errored">si è verificato un errore, riprova!</p>
|
||||
<div v-if="loading" class="loading">⏳⏳⏳</div>
|
||||
<div class="decode-result">
|
||||
<div
|
||||
class="decode-number"
|
||||
v-for="letter in split(bikePin)"
|
||||
v-bind:key="letter"
|
||||
>
|
||||
{{ letter }}
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="bikePin">
|
||||
🔓inserisci il codice! ricordati che il codice è unico per ogni
|
||||
bicicletta, riusalo 🤯
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { QrcodeStream, QrcodeDropZone, QrcodeCapture } from "vue-qrcode-reader";
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
name: "Unlock",
|
||||
components: { QrcodeStream, QrcodeDropZone, QrcodeCapture },
|
||||
data() {
|
||||
return {
|
||||
result: "",
|
||||
error: "",
|
||||
loading: false,
|
||||
bikePin: "",
|
||||
errored: false,
|
||||
noStreamApiSupport: false,
|
||||
camera: "auto",
|
||||
isInvalid: undefined
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async onDecode(result) {
|
||||
this.bikePin = "";
|
||||
this.errored = false;
|
||||
this.turnCameraOff();
|
||||
if (result.startsWith("http://ofo.com/oneplate/")) {
|
||||
const code = +result.split("/").slice(-1);
|
||||
this.result = code;
|
||||
this.getCode(code);
|
||||
} else {
|
||||
this.isInvalid = true;
|
||||
}
|
||||
|
||||
await this.timeout(3000);
|
||||
this.turnCameraOn();
|
||||
this.isInvalid = undefined;
|
||||
},
|
||||
logErrors(promise) {
|
||||
promise.catch(console.error);
|
||||
},
|
||||
async onInit(promise) {
|
||||
try {
|
||||
await promise;
|
||||
} catch (error) {
|
||||
if (error.name === "StreamApiNotSupportedError") {
|
||||
this.noStreamApiSupport = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
resetValidationState() {
|
||||
this.isInvalid = undefined;
|
||||
},
|
||||
getCode(bikeId) {
|
||||
this.loading = true;
|
||||
axios
|
||||
.get("https://api.coindesk.com/v1/bpi/currentprice.json") //add here the api enpoint w/ bikeId param
|
||||
.then(response => {
|
||||
//const pin = response.data //get pin from api response
|
||||
const pin = "1234";
|
||||
this.bikePin = pin;
|
||||
})
|
||||
.catch(error => {
|
||||
this.errored = true;
|
||||
this.result = "";
|
||||
})
|
||||
.finally(() => {
|
||||
this.result = "";
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
turnCameraOn() {
|
||||
this.camera = "auto";
|
||||
},
|
||||
|
||||
turnCameraOff() {
|
||||
this.camera = "off";
|
||||
},
|
||||
timeout(ms) {
|
||||
return new Promise(resolve => {
|
||||
window.setTimeout(resolve, ms);
|
||||
});
|
||||
},
|
||||
split(text) {
|
||||
return text.split("");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
max-width: 500px;
|
||||
height: 100%;
|
||||
padding: 15px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.camera {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.camera .wrapper::before {
|
||||
top: -6px;
|
||||
bottom: -6px;
|
||||
left: 45px;
|
||||
right: 45px;
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
background: var(--yellow-ofo);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.camera .wrapper::after {
|
||||
left: -6px;
|
||||
right: -6px;
|
||||
top: 45px;
|
||||
bottom: 45px;
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
background: var(--yellow-ofo);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.camera .wrapper {
|
||||
padding: 10px;
|
||||
border: 5px solid black;
|
||||
margin: 0 auto;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.inquadra,
|
||||
.loading {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.inquadra {
|
||||
font-family: "syne", serif;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.decode-result {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.decode-number {
|
||||
padding: 15px;
|
||||
border: 2px solid black;
|
||||
margin: 5px;
|
||||
font-weight: bold;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue