WIP Progress on skeleton of the Vue app.

This commit is contained in:
2019-03-04 18:46:54 -06:00
parent bcde5fbfc0
commit 1b94245078
37 changed files with 536 additions and 256 deletions

25
web/src/views/Login.vue Normal file
View File

@ -0,0 +1,25 @@
<template>
<div class="login">
<h1>Personal Measure</h1>
<form @submit.prevent=login() class=login-form v-show="!waiting">
<input type=text
name=email
v-model="loginForm.email"
placeholder="email address">
</input>
<input type=password
name=password
v-model="loginForm.password"
placeholder="password">
</input>
<button class="btn-action">Login</button>
<div class=flash>{{flashMessage}}</div>
</form>
<div class=loading v-show="waiting">
<img src="/img/mickey-open-door.gif">
<div>logging you in...</div>
</div>
</div>
</template>
<script lang="ts" src="./login.ts"></script>
<style lang="scss" src="./login.scss"></style>

View File

@ -1,5 +1,5 @@
<template>
<nav v-bind:class='collapsed ? "collapsed" : "expanded"'>
<nav v-if='user' v-bind:class='collapsed ? "collapsed" : "expanded"'>
<h1 class=logo>
<span class=expanded>Personal Measure</span>
<span class=collapsed>PM</span>

View File

@ -1,6 +1,17 @@
import { Component, Vue } from 'vue-property-decorator';
import { Route, RawLocation } from 'vue-router';
import userStore from '@/store-modules/user';
import { NavNext } from '@/types';
@Component({
components: { }
})
export default class Home extends Vue {}
@Component({})
export default class Dashboard extends Vue {
public get user() {
return userStore.user;
}
public beforeRouteEnter<V extends Vue>( to: Route, from: Route, next: NavNext): void {
next();
}
}

View File

@ -1,4 +0,0 @@
import { Component, Vue } from 'vue-property-decorator';
@Component({})
export default class Dashboard extends Vue {}

36
web/src/views/login.scss Normal file
View File

@ -0,0 +1,36 @@
@import '~@/styles/vars';
.login {
margin: 4rem auto;
text-align: center;
width: 36rem;
.login-form {
align-items: center;
display: flex;
flex-direction: column;
margin-top: 2em;
input {
border: solid thin lighten($fg-primary, 25%);
border-radius: .25em;
font-size: 150%;
margin-bottom: 1em;
padding: .5em;
}
.btn-action {
font-size: 150%;
}
}
.loading {
margin: 1em 0;
img {
border-radius: 10em;
width: 32em;
}
}
}

40
web/src/views/login.ts Normal file
View File

@ -0,0 +1,40 @@
import { Route } from 'vue-router';
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import { LoginSubmit } from '@/models';
import userStore from '@/store-modules/user';
@Component({})
export default class Login extends Vue {
private loginForm: LoginSubmit = {
email: '',
password: ''
};
private waiting = false;
private flashMessage = '';
private redirect: string | undefined = undefined;
public async login() {
this.waiting = true;
this.flashMessage = '';
try {
await userStore.login(this.loginForm);
this.$router.push({ path: this.redirect || '/' });
} catch (e) {
if (e.response.status === 401) {
this.flashMessage = 'invlid username or password';
}
}
this.waiting = false;
}
/*
@Watch('$route', { immediate: true })
private onRouteChange(route: Route) {
this.redirect = route.query && route.query.redirect as string;
}
*/
}
// TODO: styling of flash message

View File

@ -2,6 +2,7 @@ import { Component, Vue } from 'vue-property-decorator';
import { library } from '@fortawesome/fontawesome-svg-core';
import { faAngleDoubleLeft, faAngleDoubleRight,
faHome, faPencilRuler, faThLarge, faUser } from '@fortawesome/free-solid-svg-icons';
import userStore from '@/store-modules/user';
// import UiIconButton from 'keen-ui/src/UiIconButton.vue';
library.add(faAngleDoubleLeft, faAngleDoubleRight, faHome, faPencilRuler, faThLarge, faUser);
@ -23,4 +24,8 @@ export default class NavBar extends Vue {
this.collapsed = !this.collapsed;
return this.collapsed;
}
public get user() {
return userStore.user;
}
}