198 lines
5.2 KiB
Vue
198 lines
5.2 KiB
Vue
<script setup>
|
|
const props = defineProps({
|
|
targetType: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
targetId: {
|
|
type: [String, Number],
|
|
default: null
|
|
},
|
|
displayName: {
|
|
type: String,
|
|
default: ""
|
|
},
|
|
title: {
|
|
type: String,
|
|
default: "Telefonie"
|
|
},
|
|
description: {
|
|
type: String,
|
|
default: "Lege fest, unter welcher internen Nebenstelle dieses Ziel erreichbar ist."
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits(["saved"])
|
|
|
|
const toast = useToast()
|
|
const loading = ref(false)
|
|
const saving = ref(false)
|
|
const deleting = ref(false)
|
|
const extension = ref("")
|
|
const enabled = ref(true)
|
|
const existingId = ref(null)
|
|
|
|
const canUseExtension = computed(() => Boolean(props.targetId))
|
|
const statusLabel = computed(() => {
|
|
if (!canUseExtension.value) return "Kein Ziel verknüpft"
|
|
if (!extension.value) return "Keine Nebenstelle"
|
|
return enabled.value ? `Nebenstelle ${extension.value}` : `Nebenstelle ${extension.value} inaktiv`
|
|
})
|
|
const statusColor = computed(() => {
|
|
if (!canUseExtension.value) return "neutral"
|
|
if (!extension.value) return "neutral"
|
|
return enabled.value ? "success" : "warning"
|
|
})
|
|
|
|
const loadExtension = async () => {
|
|
if (!canUseExtension.value) return
|
|
loading.value = true
|
|
|
|
try {
|
|
const res = await useNuxtApp().$api("/api/telephony/extensions/target", {
|
|
params: {
|
|
targetType: props.targetType,
|
|
targetId: props.targetId
|
|
}
|
|
})
|
|
existingId.value = res?.extension?.id || null
|
|
extension.value = res?.extension?.extension || ""
|
|
enabled.value = res?.extension ? res.extension.enabled !== false : true
|
|
} catch (error) {
|
|
toast.add({
|
|
title: "Nebenstelle konnte nicht geladen werden",
|
|
description: error?.data?.error || error?.message,
|
|
color: "error"
|
|
})
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const saveExtension = async () => {
|
|
if (!canUseExtension.value || saving.value) return
|
|
saving.value = true
|
|
|
|
try {
|
|
const res = await useNuxtApp().$api("/api/telephony/extensions/target", {
|
|
method: "PUT",
|
|
body: {
|
|
targetType: props.targetType,
|
|
targetId: props.targetId,
|
|
extension: extension.value,
|
|
displayName: props.displayName,
|
|
enabled: enabled.value
|
|
}
|
|
})
|
|
existingId.value = res?.id || existingId.value
|
|
extension.value = res?.extension || extension.value
|
|
enabled.value = res?.enabled !== false
|
|
toast.add({ title: "Nebenstelle gespeichert", color: "success" })
|
|
emit("saved", res)
|
|
} catch (error) {
|
|
toast.add({
|
|
title: "Nebenstelle konnte nicht gespeichert werden",
|
|
description: error?.data?.error || error?.message,
|
|
color: "error"
|
|
})
|
|
} finally {
|
|
saving.value = false
|
|
}
|
|
}
|
|
|
|
const deleteExtension = async () => {
|
|
if (!canUseExtension.value || deleting.value) return
|
|
deleting.value = true
|
|
|
|
try {
|
|
await useNuxtApp().$api("/api/telephony/extensions/target", {
|
|
method: "DELETE",
|
|
params: {
|
|
targetType: props.targetType,
|
|
targetId: props.targetId
|
|
}
|
|
})
|
|
existingId.value = null
|
|
extension.value = ""
|
|
enabled.value = true
|
|
toast.add({ title: "Nebenstelle entfernt", color: "success" })
|
|
emit("saved", null)
|
|
} catch (error) {
|
|
toast.add({
|
|
title: "Nebenstelle konnte nicht entfernt werden",
|
|
description: error?.data?.error || error?.message,
|
|
color: "error"
|
|
})
|
|
} finally {
|
|
deleting.value = false
|
|
}
|
|
}
|
|
|
|
watch(() => [props.targetType, props.targetId], loadExtension, { immediate: true })
|
|
</script>
|
|
|
|
<template>
|
|
<UCard>
|
|
<template #header>
|
|
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
|
<div>
|
|
<h3 class="text-base font-semibold text-highlighted">
|
|
{{ title }}
|
|
</h3>
|
|
<p class="mt-1 text-sm text-muted">
|
|
{{ description }}
|
|
</p>
|
|
</div>
|
|
<UBadge :color="statusColor" variant="soft">
|
|
{{ statusLabel }}
|
|
</UBadge>
|
|
</div>
|
|
</template>
|
|
|
|
<UAlert
|
|
v-if="!canUseExtension"
|
|
color="warning"
|
|
icon="i-heroicons-exclamation-triangle"
|
|
title="Noch nicht verfügbar"
|
|
description="Speichere den Datensatz zuerst oder verknüpfe einen Benutzer, bevor eine Nebenstelle vergeben wird."
|
|
/>
|
|
|
|
<div v-else class="grid gap-4 md:grid-cols-[1fr_auto] md:items-end">
|
|
<div class="grid gap-4 sm:grid-cols-[1fr_auto] sm:items-end">
|
|
<UFormField label="Nebenstelle">
|
|
<UInput
|
|
v-model="extension"
|
|
inputmode="tel"
|
|
placeholder="z. B. 1001"
|
|
:loading="loading"
|
|
/>
|
|
</UFormField>
|
|
<UFormField label="Aktiv">
|
|
<USwitch v-model="enabled" />
|
|
</UFormField>
|
|
</div>
|
|
|
|
<div class="flex flex-wrap gap-2 md:justify-end">
|
|
<UButton
|
|
icon="i-heroicons-check"
|
|
:loading="saving"
|
|
:disabled="!extension"
|
|
@click="saveExtension"
|
|
>
|
|
Speichern
|
|
</UButton>
|
|
<UButton
|
|
v-if="existingId"
|
|
icon="i-heroicons-trash"
|
|
color="error"
|
|
variant="soft"
|
|
:loading="deleting"
|
|
@click="deleteExtension"
|
|
>
|
|
Entfernen
|
|
</UButton>
|
|
</div>
|
|
</div>
|
|
</UCard>
|
|
</template>
|