refactor: Refactor frontend views and components

This commit is contained in:
aldrin 2021-08-09 14:28:26 +02:00
parent 9c763c4b3b
commit 517f79c9f9
8 changed files with 104 additions and 169 deletions

View File

@ -1,16 +1,25 @@
<template> <template>
<div id="app"> <div id="app">
<Navbar /> <navbar />
<router-view /> <section class="container">
<div class="columns is-centered">
<router-view />
</div>
</section>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue } from "vue-property-decorator"; import { Component, Vue } from "vue-property-decorator";
import Navbar from "@/components/Navbar.vue"; import Navbar from "@/components/Navbar.vue";
import { user } from "@/api";
@Component({ components: { Navbar } }) @Component({ components: { Navbar } })
export default class App extends Vue {} export default class App extends Vue {
public async created(): Promise<void> {
if (!user.isAuthenticated && this.$route.name !== "login") {
this.$router.push({ name: "login" });
}
}
}
</script> </script>
<style lang="scss"></style>

View File

@ -1,4 +1,5 @@
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import Vue from "vue";
type HTTPMethod = "GET" | "POST" | "PUT" | "PATCH"; type HTTPMethod = "GET" | "POST" | "PUT" | "PATCH";
@ -95,3 +96,5 @@ export class User {
}); });
} }
} }
export const user = Vue.observable(new User());

View File

@ -1,30 +0,0 @@
<template>
<div style="display: flex">
<b-input v-if="isEditing" v-model="editorValue" />
<span v-else>{{ value }}</span>
<b-button @click="toggleEditor" style="margin-left: auto">{{
isEditing ? "Speichern" : "Bearbeiten"
}}</b-button>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
@Component
export default class InlineEditor extends Vue {
@Prop() private value: string | undefined;
private editorValue = "";
private isEditing = false;
private created() {
this.editorValue = this.value || "";
}
private toggleEditor() {
this.isEditing = !this.isEditing;
this.$emit("input", this.editorValue);
}
}
</script>

View File

@ -1,74 +0,0 @@
<template>
<form class="box" @submit.prevent="doAction">
<div v-if="errorMessage" class="notification is-danger">
{{ errorMessage }}
</div>
<b-field label="Benutzername">
<b-input type="text" v-model="user.username" />
</b-field>
<b-field label="Kennwort">
<b-input type="password" v-model="user.password" />
</b-field>
<b-field v-if="mode === 'signup'" label="Kennwort wiederholen">
<b-input type="password" v-model="password2" />
</b-field>
<div class="buttons">
<b-button native-type="submit" type="is-primary">
{{ mode === "login" ? "Anmelden" : "Konto anlegen" }}
</b-button>
<router-link v-if="mode === 'login'" to="/signup"
>Konto anlegen</router-link
>
<router-link v-else to="/login">Anmelden</router-link>
</div>
</form>
</template>
<script lang="ts">
import { Component, Prop, Watch } from "vue-property-decorator";
import { mixins } from "vue-class-component";
import { User } from "@/api";
import { Route } from "vue-router";
import { NotifyMixin } from "@/mixins";
@Component
export default class LoginForm extends mixins(NotifyMixin) {
@Prop() private user!: User;
private mode: "login" | "signup" = "login";
private password2 = "";
private errorMessage = "";
public created(): void {
if (this.$route.name === "signup") this.mode = "signup";
}
@Watch("$route")
public routeChanged(to: Route): void {
if (to.name === "signup") {
this.mode = "signup";
} else {
this.mode = "login";
}
}
private async doAction() {
try {
if (this.mode === "login") {
await this.user.login();
if (this.$route.name !== "home") this.$router.push({ name: "home" });
} else {
await this.user.signup();
this.$router.push({ name: "login" });
this.showSuccess("Du kannst dich nun anmelden.");
}
} catch {
this.errorMessage = "Fehler";
}
}
}
</script>
<style lang="scss"></style>

View File

@ -1,29 +1,25 @@
import Vue from "vue"; import Vue from "vue";
import VueRouter, { RouteConfig } from "vue-router"; import VueRouter, { RouteConfig } from "vue-router";
import MainPage from "../views/MainPage.vue"; import LoginView from "../views/Login.vue";
import UserView from "../views/User.vue";
Vue.use(VueRouter); Vue.use(VueRouter);
const routes: Array<RouteConfig> = [ const routes: Array<RouteConfig> = [
{ {
path: "/", path: "/",
name: "home", name: "index",
component: MainPage, component: UserView,
}, },
{ {
path: "/login", path: "/login",
name: "login", name: "login",
component: MainPage, component: LoginView,
}, },
{ {
path: "/signup", path: "/signup",
name: "signup", name: "signup",
component: MainPage, component: LoginView,
},
{
path: "/confirm/:uid/:token",
name: "confirm",
component: MainPage,
}, },
]; ];

73
src/views/Login.vue Normal file
View File

@ -0,0 +1,73 @@
<template>
<div class="column is-3-widescreen is-4-desktop is-5-tablet">
<form class="box" @submit.prevent="doAction">
<div v-if="errorMessage" class="notification is-danger">
{{ errorMessage }}
</div>
<b-field label="Benutzername">
<b-input type="text" v-model="user.username" />
</b-field>
<b-field label="Kennwort">
<b-input type="password" v-model="user.password" />
</b-field>
<b-field v-if="mode === 'signup'" label="Kennwort wiederholen">
<b-input type="password" v-model="password2" />
</b-field>
<div class="buttons">
<b-button native-type="submit" type="is-primary">
{{ mode === "login" ? "Anmelden" : "Konto anlegen" }}
</b-button>
<router-link v-if="mode === 'login'" to="/signup"
>Konto anlegen</router-link
>
<router-link v-else to="/login">Anmelden</router-link>
</div>
</form>
</div>
</template>
<script lang="ts">
import { Component, Watch } from "vue-property-decorator";
import { user } from "@/api";
import { NotifyMixin } from "@/mixins";
import { mixins } from "vue-class-component";
import { Route } from "vue-router";
@Component
export default class Login extends mixins(NotifyMixin) {
user = user;
private mode: "login" | "signup" = "login";
private password2 = "";
private errorMessage = "";
public created(): void {
if (this.$route.name === "signup") this.mode = "signup";
}
@Watch("$route")
public routeChanged(to: Route): void {
if (to.name === "signup") {
this.mode = "signup";
} else {
this.mode = "login";
}
}
private async doAction() {
try {
if (this.mode === "login") {
await this.user.login();
if (this.$route.name !== "home") this.$router.push({ name: "home" });
} else {
await this.user.signup();
this.$router.push({ name: "login" });
this.showSuccess("Du kannst dich nun anmelden.");
}
} catch {
this.errorMessage = "Fehler";
}
}
}
</script>

View File

@ -1,35 +0,0 @@
<template>
<section class="container">
<div class="columns is-centered">
<div
v-if="user.isAuthenticated"
class="column is-5-fullhd is-6-widescreen is-7-desktop is-7-tablet"
>
<UserTable :user="user" />
</div>
<div v-else class="column is-3-widescreen is-4-desktop is-5-tablet">
<LoginForm :user="user" />
</div>
</div>
</section>
</template>
<script lang="ts">
import { Component } from "vue-property-decorator";
import LoginForm from "@/components/LoginForm.vue";
import { mixins } from "vue-class-component";
import { User } from "@/api";
import UserTable from "@/components/UserTable.vue";
import { NotifyMixin } from "@/mixins";
@Component({ components: { UserTable, LoginForm } })
export default class Home extends mixins(NotifyMixin) {
private user = new User();
public async created(): Promise<void> {
if (!this.user.isAuthenticated && this.$route.name !== "login") {
this.$router.push({ name: "login" });
}
}
}
</script>

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <div class="column is-5-fullhd is-6-widescreen is-7-desktop is-7-tablet">
<b-notification type="is-info" aria-close-label="Close notification"> <b-notification type="is-info" aria-close-label="Close notification">
Dein Konto ist noch nicht aktiv. Dein Konto ist noch nicht aktiv.
<a v-if="user.isTrusted" @click="activate()">Jetzt aktivieren</a> <a v-if="user.isTrusted" @click="activate()">Jetzt aktivieren</a>
@ -12,15 +12,11 @@
</tr> </tr>
<tr> <tr>
<td>Benutzername</td> <td>Benutzername</td>
<td> <td>{{ user.username }}</td>
<InlineEditor v-model="user.username" @input="user.save()" />
</td>
</tr> </tr>
<tr> <tr>
<td>Vertrauensperson</td> <td>Vertrauensperson</td>
<td> <td></td>
<inline-editor v-model="user.confidantEmail" @input="user.save()" />
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -28,15 +24,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Vue } from "vue-property-decorator";
import { User } from "@/api"; import { user } from "@/api";
import InlineEditor from "@/components/InlineEditor.vue";
@Component({ @Component
components: { InlineEditor }, export default class Home extends Vue {
}) user = user;
export default class UserTable extends Vue {
@Prop() private user!: User;
async activate(): Promise<void> { async activate(): Promise<void> {
await this.user.activate(); await this.user.activate();