Files
FEDEO/frontend/components/TelephonyExtensionField.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>