Files
tickte-system/src/lib/teamApi.js
T
2026-10-02 23:57:03 +00:00

104 lines
5.2 KiB
JavaScript

import { account } from './appwrite'
import { createFinanceRequest } from './financeRequest'
import { createJwtCache } from './serverpulsAuth'
/**
* Client fuer den Team-Eingang des Kundenportals (/api/team): alle Mitarbeiter, Appwrite-JWT (Bearer).
* Anfrage-Kern (JWT-Cache, Wiederholung bei 401, deutsche Fehlertexte) wie bei den Finanzen: financeRequest.js.
*/
export const PORTAL_URL =
import.meta.env.VITE_PROJECT_ADMIN_URL || 'https://project.webklar.com'
const request = createFinanceRequest({ baseUrl: `${PORTAL_URL}/api/team`, createJWT: () => account.createJWT() })
// Eigenes JWT fuer Anfragen, die nicht ueber request laufen (Hochladen im Chat-Baustein), 10 Minuten gecacht
const jwtCache = createJwtCache({ createJWT: () => account.createJWT() })
const enc = encodeURIComponent
/** { hasAccess, lastLoginAt } */
export const getCustomerPortalStatus = (customerId) => request(`/customers/${enc(customerId)}/portal`)
/** { entries: [{ id, at, staffName, action, detail }] }, neueste zuerst */
export const getCustomerViewLog = (customerId) => request(`/customers/${enc(customerId)}/protokoll`)
/** Einmal-Link (60 s) in die Kundenansicht des Portals */
export async function createKundenansichtLink(customerId) {
const { openUrl } = await request(`/customers/${enc(customerId)}/kundenansicht`, { method: 'POST', body: {} })
return openUrl
}
/** Einmal-Link fuer die Preview eines Projekts */
export async function createPreviewLink({ subdomain, previewUrl }) {
const { openUrl } = await request('/preview-link', { method: 'POST', body: { subdomain, previewUrl } })
return openUrl
}
// --- Chat (Messenger, Reiter "Chat", Zahl in der Sidebar) ---
/** { chats: [{ customerId, customerName, lastText, lastSender, lastAt, unreadFromCustomer }] } */
export const listChats = () => request('/chats')
/** { unread } */
export const getChatUnreadCount = () => request('/chats/unread-count')
/** { messages }; mit since nur neuere (Abfrage im offenen Gespraech) */
export const getChatMessages = (customerId, since = '') =>
request(`/chats/${enc(customerId)}/messages${since ? `?since=${enc(since)}` : ''}`)
/** { message, notice } */
export const sendChatMessage = (customerId, { text, attachmentIds }) =>
request(`/chats/${enc(customerId)}/messages`, { method: 'POST', body: { text, attachmentIds } })
export const markChatRead = (customerId) => request(`/chats/${enc(customerId)}/read`, { method: 'POST', body: {} })
/** Upload-Adresse fuer den Chat-Baustein (POST roh, DELETE <url>/<id>) */
export const chatUploadUrl = (customerId) => `${PORTAL_URL}/api/team/chats/${enc(customerId)}/attachments`
/** Header fuer den Chat-Baustein (Option requestHeaders) */
export async function teamAuthHeaders() {
return { Authorization: `Bearer ${await jwtCache.get()}` }
}
// --- Gutschriften (Uebernahmegutschriften) ---
const query = (params) => {
const q = new URLSearchParams(Object.entries(params).filter(([, v]) => v !== undefined && v !== null && v !== '')).toString()
return q ? `?${q}` : ''
}
/** { requests, openCount }; status 'open' (Standard) oder 'all', optional nur ein Kunde */
export const listCredits = ({ status = 'open', customerId } = {}) => request(`/takeover-credits${query({ status, customerId })}`)
export const getCreditOpenCount = () => request('/takeover-credits/open-count')
export const getCredit = (id) => request(`/takeover-credits/${enc(id)}`)
export const calcCredit = (body) => request('/takeover-credits/calc', { method: 'POST', body })
export const decideCredit = (id, body) => request(`/takeover-credits/${enc(id)}/decision`, { method: 'POST', body })
export const applyCredit = (id) => request(`/takeover-credits/${enc(id)}/apply`, { method: 'POST', body: {} })
// --- Abo-Angebote ---
export const listOffers = ({ customerId } = {}) => request(`/offers${query({ customerId })}`)
export const getOfferContext = (customerId) => request(`/offers/context/${enc(customerId)}`)
export const createOffer = (body) => request('/offers', { method: 'POST', body })
export const withdrawOffer = (id) => request(`/offers/${enc(id)}/withdraw`, { method: 'POST', body: {} })
export const notifyOffer = (id) => request(`/offers/${enc(id)}/notify`, { method: 'POST', body: {} })
// --- E-Mail-Speicher ---
export const listStorageTasks = () => request('/storage-tasks')
export const getStorageOpenCount = () => request('/storage-tasks/open-count')
export const markStorageDone = (id) => request(`/storage-tasks/${enc(id)}/done`, { method: 'POST', body: {} })
// --- Funktionen (News-Pinnwand, Terminplaner je Projekt) ---
export const getFunktionen = (customerId) => request(`/funktionen/${enc(customerId)}`)
/** Aktivieren (ohne Zahlung) oder Abschalten einer Funktion (key: news | termine); Antwort { projects: [das eine Projekt] }. */
export const setFeature = (customerId, key, { projectId, action, note }) =>
request(`/funktionen/${enc(customerId)}/${enc(key)}`, { method: 'POST', body: { projectId, action, note } })
export const setNewsFeature = (customerId, body) => setFeature(customerId, 'news', body)
// --- Abo-Status (alle Mitarbeiter) ---
/** { productKey, active, status, storageUnits, startedAt, serviceStart, currentPeriodEnd, cancelAt } */
export const getCustomerAboStatus = (customerId) => request(`/customers/${enc(customerId)}/abo`)