<template> <div class="flex flex-col gap-2 h-full w-full overflow-y-auto"> <Spinner v-if="loading == 'loading'" class="mx-auto" /> <p v-else-if="loading == 'failed'">laden fehlgeschlagen</p> <form v-else-if="wearable != null" class="flex flex-col gap-4 py-2 w-full max-w-xl mx-auto" @submit.prevent="triggerUpdate" > <p class="mx-auto">Kleidung bearbeiten</p> <div> <label for="name">Bezeichnung</label> <input type="text" id="name" required v-model="wearable.name" /> </div> <ScanInput name="code" label="Code" :required="false" v-model="wearable.code" /> <div> <label for="location">Verortung (optional)</label> <input type="text" id="location" v-model="wearable.location" /> </div> <MemberSearchSelectSingle title="Träger (optional)" v-model="wearable.wearerId" /> <div> <label for="commissioned">In-Betrieb-Nahme</label> <input type="date" id="commissioned" required v-model="wearable.commissioned" /> </div> <div> <label for="decommissioned">Außer-Betrieb-Nahme (optional)</label> <input type="date" id="decommissioned" v-model="wearable.decommissioned" /> </div> <div class="flex flex-row justify-end gap-2"> <button primary-outline type="reset" class="w-fit!" :disabled="canSaveOrReset" @click="resetForm"> abbrechen </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> </div> </template> <script setup lang="ts"> import { defineComponent } from "vue"; import { mapActions, mapState } from "pinia"; import { useWearableStore } from "@/stores/admin/unit/wearable/wearable"; import type { CreateWearableViewModel, WearableViewModel, UpdateWearableViewModel, } from "@/viewmodels/admin/unit/wearable/wearable.models"; import Spinner from "@/components/Spinner.vue"; import SuccessCheckmark from "@/components/SuccessCheckmark.vue"; import FailureXMark from "@/components/FailureXMark.vue"; import ScanInput from "@/components/ScanInput.vue"; import isEqual from "lodash.isequal"; import cloneDeep from "lodash.clonedeep"; import MemberSearchSelectSingle from "@/components/search/MemberSearchSelectSingle.vue"; </script> <script lang="ts"> export default defineComponent({ props: { wearableId: String, }, watch: { loadingActive() { if (this.loading == "loading") { this.loading = this.loadingActive; } if (this.loadingActive == "fetched") this.wearable = cloneDeep(this.activeWearableObj); }, }, data() { return { loading: "loading" as "loading" | "fetched" | "failed", status: null as null | "loading" | { status: "success" | "failed"; reason?: string }, wearable: null as null | WearableViewModel, timeout: null as any, }; }, computed: { canSaveOrReset(): boolean { return isEqual(this.activeWearableObj, this.wearable); }, ...mapState(useWearableStore, ["activeWearableObj", "loadingActive"]), }, mounted() { this.fetchItem(); }, beforeUnmount() { try { clearTimeout(this.timeout); } catch (error) {} }, methods: { ...mapActions(useWearableStore, ["updateActiveWearable", "fetchWearableByActiveId"]), resetForm() { this.wearable = cloneDeep(this.activeWearableObj); }, fetchItem() { this.fetchWearableByActiveId(); }, triggerUpdate(e: any) { if (this.wearable == null) return; let formData = e.target.elements; let updateWearable: UpdateWearableViewModel = { id: this.wearable.id, code: formData.code.value || null, name: formData.name.value, location: formData.location.value, commissioned: formData.commissioned.value, decommissioned: formData.decommissioned.value || null, wearerId: this.wearable.wearerId, }; this.status = "loading"; this.updateActiveWearable(updateWearable) .then((res) => { this.fetchItem(); this.status = { status: "success" }; }) .catch((err) => { this.status = { status: "failed" }; }) .finally(() => { this.timeout = setTimeout(() => { this.status = null; }, 2000); }); }, }, }); </script>