<template> <MainTemplate :useStagedOverviewLink="false"> <template #topBar> <div class="flex flex-row items-center justify-between pt-5 pb-3 px-7"> <h1 class="font-bold text-xl h-8">Mein Account</h1> </div> </template> <template #main> <Spinner v-if="loading == 'loading'" class="mx-auto" /> <p v-else-if="loading == 'failed'">laden fehlgeschlagen</p> <form v-else-if="user != null" class="flex flex-col gap-4 py-2 w-full max-w-xl mx-auto" @submit.prevent="triggerUpdateUser" > <div> <label for="username">Nutzername</label> <input type="text" id="username" required v-model="user.username" /> </div> <div> <label for="firstname">Vorname</label> <input type="text" id="firstname" required v-model="user.firstname" /> </div> <div> <label for="lastname">Nachname</label> <input type="text" id="lastname" required v-model="user.lastname" /> </div> <div> <label for="mail">Mailadresse</label> <input type="email" id="mail" required v-model="user.mail" /> </div> <div class="flex flex-row justify-end gap-2"> <button primary-outline type="reset" class="w-fit!" :disabled="canSaveOrReset" @click="resetForm"> verwerfen </button> <button primary type="submit" class="w-fit!" :disabled="status == 'loading' || canSaveOrReset"> speichern </button> <Spinner v-if="status == 'loading'" class="my-auto" /> <SuccessCheckmark v-else-if="status?.status == 'success'" /> <FailureXMark v-else-if="status?.status == 'failed'" /> </div> </form> </template> </MainTemplate> </template> <script setup lang="ts"> import { defineComponent, markRaw, defineAsyncComponent } from "vue"; import { mapActions, mapState } from "pinia"; import type { UserViewModel } from "@/viewmodels/admin/management/user.models"; import MainTemplate from "@/templates/Main.vue"; import Spinner from "@/components/Spinner.vue"; import SuccessCheckmark from "@/components/SuccessCheckmark.vue"; import FailureXMark from "@/components/FailureXMark.vue"; import cloneDeep from "lodash.clonedeep"; import isEqual from "lodash.isequal"; </script> <script lang="ts"> export default defineComponent({ data() { return { loading: "loading" as "loading" | "fetched" | "failed", status: null as null | "loading" | { status: "success" | "failed"; reason?: string }, origin: null as null | UserViewModel, user: null as null | UserViewModel, timeout: null as any, }; }, computed: { canSaveOrReset(): boolean { return isEqual(this.origin, this.user); }, }, mounted() { this.fetchItem(); }, beforeUnmount() { try { clearTimeout(this.timeout); } catch (error) {} }, methods: { resetForm() { this.user = cloneDeep(this.origin); }, fetchItem() { this.$http .get(`/user/me`) .then((result) => { this.loading = "fetched"; this.user = result.data; this.origin = cloneDeep(result.data); }) .catch((err) => { this.loading = "failed"; }); }, triggerUpdateUser(e: any) { if (this.user == null) return; let formData = e.target.elements; this.status = "loading"; this.$http .patch(`/user/me`, { username: formData.username.value, firstname: formData.firstname.value, lastname: formData.lastname.value, mail: formData.mail.value, }) .then(() => { this.fetchItem(); this.status = { status: "success" }; }) .catch((err) => { this.status = { status: "failed" }; }) .finally(() => { this.timeout = setTimeout(() => { this.status = null; }, 2000); }); }, }, }); </script>