<template> <div class="w-full md:max-w-md"> <div class="flex flex-col items-center"> <p class="text-xl font-medium">Mitglied-Kommunikation hinzufügen</p> </div> <br /> <form class="flex flex-col gap-4 py-2" @submit.prevent="triggerCreate"> <div> <Listbox v-model="selectedCommunicationType" name="communication"> <ListboxLabel>Kommunikationsart</ListboxLabel> <div class="relative mt-1"> <ListboxButton class="rounded-md shadow-sm relative block w-full px-3 py-2 border border-gray-300 focus:border-primary placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-0 focus:z-10 sm:text-sm resize-none" > <span class="block truncate w-full text-start"> {{ communicationTypes.length != 0 ? (selectedCommunicationType?.type ?? "bitte auswählen") : "keine Auswahl vorhanden" }}</span > <span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"> <ChevronUpDownIcon class="h-5 w-5 text-gray-400" aria-hidden="true" /> </span> </ListboxButton> <transition leave-active-class="transition duration-100 ease-in" leave-from-class="opacity-100" leave-to-class="opacity-0" > <ListboxOptions class="absolute mt-1 max-h-60 z-20 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black/5 focus:outline-none sm:text-sm h-32 overflow-y-auto" > <ListboxOption v-if="communicationTypes.length == 0" disabled as="template"> <li :class="['relative cursor-default select-none py-2 pl-10 pr-4']"> <span :class="['font-normal', 'block truncate']">keine Auswahl vorhanden</span> </li> </ListboxOption> <ListboxOption v-slot="{ active, selected }" v-for="type in communicationTypes" :key="type.id" :value="type" as="template" > <li :class="[ active ? 'bg-red-200 text-amber-900' : 'text-gray-900', 'relative cursor-default select-none py-2 pl-10 pr-4', ]" > <span :class="[selected ? 'font-medium' : 'font-normal', 'block truncate']">{{ type.type }}</span> <span v-if="selected" class="absolute inset-y-0 left-0 flex items-center pl-3 text-primary"> <CheckIcon class="h-5 w-5" aria-hidden="true" /> </span> </li> </ListboxOption> </ListboxOptions> </transition> </div> </Listbox> </div> <div v-if="selectedCommunicationType?.fields.includes('mobile')"> <label for="mobile">Telefon</label> <input type="text" id="mobile" required /> </div> <div v-if="selectedCommunicationType?.fields.includes('email')"> <label for="email">Mail-Adresse</label> <input type="text" id="email" required /> </div> <div v-if="selectedCommunicationType?.fields.includes('city')"> <label for="city">Stadt</label> <input type="text" id="city" required /> </div> <div v-if="selectedCommunicationType?.fields.includes('street')"> <label for="street">Straße</label> <input type="text" id="street" required /> </div> <div v-if="selectedCommunicationType?.fields.includes('streetNumber')"> <label for="streetNumber">Hausnummer</label> <input type="number" id="streetNumber" min="0" required /> </div> <div v-if="selectedCommunicationType?.fields.includes('streetNumberAddition')"> <label for="streetNumberAddition">Hausnummer-Zusatz (optional)</label> <input type="text" id="streetNumberAddition" /> </div> <div class="flex flex-row items-center gap-2"> <input type="checkbox" id="preferred" /> <label for="preferred">bevorzugt?</label> </div> <div class="flex flex-row items-center gap-2"> <input type="checkbox" id="isNewsletterMain" /> <label for="isNewsletterMain">Newsletter hier hin versenden?</label> </div> <div v-if="selectedCommunicationType?.fields.includes('mobile')" class="flex flex-row items-center gap-2"> <input type="checkbox" id="isSMSAlarming" /> <label for="isSMSAlarming">SMS-Alarmierung hier hin versenden?</label> </div> <div class="flex flex-row gap-2"> <button primary type="submit" :disabled="status == 'loading' || status?.status == 'success'">erstellen</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 == 'loading' || status?.status == 'success'"> abbrechen </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 { Listbox, ListboxButton, ListboxOptions, ListboxOption, ListboxLabel } from "@headlessui/vue"; import { CheckIcon, ChevronUpDownIcon } from "@heroicons/vue/20/solid"; import { useCommunicationStore } from "@/stores/admin/communication"; import type { CreateCommunicationViewModel } from "@/viewmodels/admin/communication.models"; import { useCommunicationTypeStore } from "@/stores/admin/communicationType"; import type { CommunicationTypeViewModel } from "@/viewmodels/admin/communicationType.models"; </script> <script lang="ts"> export default defineComponent({ data() { return { status: null as null | "loading" | { status: "success" | "failed"; reason?: string }, timeout: undefined as any, selectedCommunicationType: undefined as undefined | CommunicationTypeViewModel, }; }, computed: { ...mapState(useCommunicationTypeStore, ["communicationTypes"]), }, mounted() { this.fetchCommunicationTypes(); }, beforeUnmount() { try { clearTimeout(this.timeout); } catch (error) {} }, methods: { ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useCommunicationStore, ["createCommunication"]), ...mapActions(useCommunicationTypeStore, ["fetchCommunicationTypes"]), triggerCreate(e: any) { if (this.selectedCommunicationType == undefined) return; let formData = e.target.elements; let createCommunication: CreateCommunicationViewModel = { 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, isSMSAlarming: formData.isSMSAlarming?.checked, typeId: this.selectedCommunicationType.id, }; this.createCommunication(createCommunication) .then(() => { this.status = { status: "success" }; this.timeout = setTimeout(() => { this.closeModal(); }, 1500); }) .catch(() => { this.status = { status: "failed" }; }); }, }, }); </script>