From d9f35602b24c2ecaffbddb25bbdb3d94cfe442c4 Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Sat, 8 Nov 2025 18:54:52 +0100 Subject: [PATCH] Introduced Helpdesk --- components/MainNav.vue | 5 + composables/useHelpdesk.ts | 110 +++++++++++++ pages/helpdesk/[[id]].vue | 325 +++++++++++++++++++++++++++++++++++++ 3 files changed, 440 insertions(+) create mode 100644 composables/useHelpdesk.ts create mode 100644 pages/helpdesk/[[id]].vue diff --git a/components/MainNav.vue b/components/MainNav.vue index d8e0579..2d5d58e 100644 --- a/components/MainNav.vue +++ b/components/MainNav.vue @@ -95,6 +95,11 @@ const links = computed(() => { icon: "i-heroicons-megaphone", defaultOpen: false, children: [ + { + label: "Helpdesk", + to: "/helpdesk", + icon: "i-heroicons-chat-bubble-left-right" + }, { label: "E-Mail", to: "/email/new", diff --git a/composables/useHelpdesk.ts b/composables/useHelpdesk.ts new file mode 100644 index 0000000..d91191c --- /dev/null +++ b/composables/useHelpdesk.ts @@ -0,0 +1,110 @@ +// composables/useHelpdeskApi.ts +import { ref } from 'vue' +import { useNuxtApp } from '#app' + +export function useHelpdeskApi() { + const { $api } = useNuxtApp() + const loading = ref(false) + const error = ref(null) + + const base = '/api/helpdesk' + + // 🔹 Konversationen abrufen + async function getConversations(status?: string) { + loading.value = true + error.value = null + try { + const query = status ? `?status=${status}` : '' + const data = await $api(`${base}/conversations${query}`) + return data + } catch (err: any) { + error.value = err.message || 'Fehler beim Laden der Konversationen' + return [] + } finally { + loading.value = false + } + } + + // 🔹 Einzelne Konversation + async function getConversation(id: string) { + try { + return await $api(`${base}/conversations/${id}`) + } catch (err: any) { + error.value = err.message + return null + } + } + + // 🔹 Nachrichten einer Konversation + async function getMessages(conversationId: string) { + try { + return await $api(`${base}/conversations/${conversationId}/messages`) + } catch (err: any) { + error.value = err.message + return [] + } + } + + // 🔹 Neue Nachricht senden + async function sendMessage(conversationId: string, text: string) { + try { + return await $api(`${base}/conversations/${conversationId}/messages`, { + method: 'POST', + body: { text }, + }) + } catch (err: any) { + error.value = err.message + throw err + } + } + + async function replyMessage(conversationId: string, text: string) { + try { + return await $api(`${base}/conversations/${conversationId}/reply`, { + method: 'POST', + body: { text }, + }) + } catch (err: any) { + error.value = err.message + throw err + } + } + + // 🔹 Neuen Kontakt (manuell) anlegen + async function createContact(payload: { email?: string; phone?: string; display_name?: string }) { + try { + return await $api(`${base}/contacts`, { + method: 'POST', + body: payload, + }) + } catch (err: any) { + error.value = err.message + throw err + } + } + + // 🔹 Konversation-Status ändern + async function updateConversationStatus(conversationId: string, status: string) { + try { + return await $api(`${base}/conversations/${conversationId}/status`, { + method: 'PATCH', + body: { status }, + }) + } catch (err: any) { + error.value = err.message + throw err + } + } + + return { + loading, + error, + getConversations, + getConversation, + getMessages, + sendMessage, + createContact, + updateConversationStatus, + replyMessage, + } +} diff --git a/pages/helpdesk/[[id]].vue b/pages/helpdesk/[[id]].vue new file mode 100644 index 0000000..6564161 --- /dev/null +++ b/pages/helpdesk/[[id]].vue @@ -0,0 +1,325 @@ + + +