<template> <div class="w-full md:max-w-md"> <div class="flex flex-col items-center"> <p class="text-xl font-medium">Mitglied-Kommunikation bearbeiten</p> </div> <br /> <Spinner v-if="loading == 'loading'" class="mx-auto" /> <p v-else-if="loading == 'failed'" @click="fetchItem" class="cursor-pointer">↺ laden fehlgeschlagen</p> <form v-else-if="communication != null" class="flex flex-col gap-4 py-2" @submit.prevent="triggerCreate"> <div> <p>Type: {{ communication.type.type }}</p> </div> <div v-if="communication.type.fields.includes('mobile')"> <label for="mobile">Telefon</label> <input type="text" id="mobile" required v-model="communication.mobile" /> </div> <div v-if="communication.type.fields.includes('email')"> <label for="email">Mail-Adresse</label> <input type="text" id="email" required v-model="communication.email" /> </div> <div v-if="communication.type.fields.includes('city')"> <label for="city">Stadt</label> <input type="text" id="city" required v-model="communication.city" /> </div> <div v-if="communication.type.fields.includes('street')"> <label for="street">Straße</label> <input type="text" id="street" required v-model="communication.street" /> </div> <div v-if="communication.type.fields.includes('streetNumber')"> <label for="streetNumber">Hausnummer</label> <input type="number" id="streetNumber" min="0" required v-model="communication.streetNumber" /> </div> <div v-if="communication.type.fields.includes('streetNumberAddition')"> <label for="streetNumberAddition">Hausnummer-Zusatz (optional)</label> <input type="text" id="streetNumberAddition" v-model="communication.streetNumberAddition" /> </div> <div class="flex flex-row items-center gap-2"> <input type="checkbox" id="preferred" v-model="communication.preferred" /> <label for="preferred">bevorzugt?</label> </div> <div class="flex flex-row items-center gap-2"> <input type="checkbox" id="isNewsletterMain" v-model="communication.isNewsletterMain" /> <label for="isNewsletterMain">Newsletter hier hin versenden?</label> </div> <div class="flex flex-row gap-2"> <button primary-outline type="reset" :disabled="canSaveOrReset" @click="resetForm">verwerfen</button> <button primary type="submit" :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 class="flex flex-row justify-end"> <div class="flex flex-row gap-4 py-2"> <button primary-outline @click="closeModal" :disabled="status != null">schließen</button> </div> </div> </div> </template> <script setup lang="ts"> import { defineComponent } from "vue"; import { mapState, mapActions } from "pinia"; import { useModalStore } from "@/stores/modal"; import Spinner from "@/components/Spinner.vue"; import SuccessCheckmark from "@/components/SuccessCheckmark.vue"; import FailureXMark from "@/components/FailureXMark.vue"; import { useCommunicationStore } from "@/stores/admin/communication"; import type { CreateCommunicationViewModel, CommunicationViewModel, UpdateCommunicationViewModel, } from "@/viewmodels/admin/communication.models"; import isEqual from "lodash.isEqual"; import cloneDeep from "lodash.clonedeep"; </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 | CommunicationViewModel, communication: null as null | CommunicationViewModel, timeout: undefined as any, }; }, computed: { ...mapState(useCommunicationStore, ["communications"]), ...mapState(useModalStore, ["data"]), canSaveOrReset(): boolean { return isEqual(this.origin, this.communication); }, }, mounted() { this.fetchItem(); }, beforeUnmount() { try { clearTimeout(this.timeout); } catch (error) {} }, methods: { ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useCommunicationStore, ["updateCommunication", "fetchCommunicationById"]), resetForm() { this.communication = cloneDeep(this.origin); }, fetchItem() { this.fetchCommunicationById(this.data) .then((result) => { this.communication = result.data; this.origin = cloneDeep(result.data); this.loading = "fetched"; }) .catch((err) => { this.loading = "failed"; }); }, triggerCreate(e: any) { if (this.communication == null) return; let formData = e.target.elements; let updateCommunication: UpdateCommunicationViewModel = { id: this.communication.id, preferred: formData.preferred.checked, mobile: formData.mobile?.value, email: formData.email?.value, city: formData.city?.value, street: formData.street?.value, streetNumber: formData.streetNumber?.value, streetNumberAddition: formData.streetNumberAddition?.value, isNewsletterMain: formData.isNewsletterMain.checked, }; this.updateCommunication(updateCommunication) .then(() => { this.fetchItem(); this.status = { status: "success" }; }) .catch((err) => { this.status = { status: "failed" }; }) .finally(() => { this.timeout = setTimeout(() => { this.status = null; }, 2000); }); }, }, }); </script>