Kundenansicht im Dashboard: Kennung bei jeder Anfrage, Banner mit Beenden, Hinweis bei ersetzter oder abgelaufener Ansicht

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-01 19:36:55 +00:00
1 parent c5afd42a5f
commit c1fda8a717
6 files changed
+443 -5

No files matched your search

+26 -5
View File
@@ -634,6 +634,19 @@ function renderViewAsBanner(me) {
const banner = document.getElementById('viewas-banner')
if (!banner || !me.viewAs) return
banner.classList.remove('hidden')
// Kundenansicht aus dem Ticketsystem (mit Kennung): Beenden fuehrt zurueck auf die Kundenseite im Ticketsystem
if (me.viewId) {
banner.innerHTML = `
<span>Kundenansicht: <strong>${escapeHtml(me.customer?.name || 'Kunde')}</strong> · geöffnet von ${escapeHtml(me.admin?.name || 'Mitarbeiter')}</span>
<button type="button" id="exit-viewas-btn">Beenden</button>
`
document.getElementById('exit-viewas-btn')?.addEventListener('click', async () => {
const { redirect } = await api('/api/auth/kundenansicht/ende', { method: 'POST' }).catch(() => ({}))
window.location.href = redirect || 'https://ticket.webklar.com/customers'
})
return
}
// Alte Ansicht "Als Kunde ansehen" aus dem Admin-Panel (bis das Panel abgeschaltet ist)
banner.innerHTML = `
<span>Admin-Ansicht: Du siehst das Portal als <strong>${escapeHtml(me.customer?.name || 'Kunde')}</strong>.</span>
<button type="button" id="exit-viewas-btn">Zurück zur Admin-Übersicht</button>
@@ -765,6 +778,12 @@ function updateChatBadge(unread) {
}
}
// Nachrichten als gelesen markieren; in der Kundenansicht nicht (der Kunde hat sie ja nicht gelesen)
function markChatRead() {
if (chatState.viewAs) return Promise.resolve()
return api('/api/chat/read', { method: 'POST' }).catch(() => {})
}
async function pollChatMessages() {
if (document.hidden) return
try {
@@ -772,7 +791,7 @@ async function pollChatMessages() {
const data = await api(`/api/chat/messages${q}`)
appendChatMessages(data.messages || [])
if (isChatTabActive() && (data.unread || 0) > 0) {
await api('/api/chat/read', { method: 'POST' }).catch(() => {})
await markChatRead()
updateChatBadge(0)
}
} catch {
@@ -809,7 +828,7 @@ async function initChat() {
})
await pollChatMessages()
await api('/api/chat/read', { method: 'POST' }).catch(() => {})
await markChatRead()
updateChatBadge(0)
chatState.pollTimer = setInterval(() => {
if (isChatTabActive()) pollChatMessages()
@@ -2004,7 +2023,7 @@ function showView(name, { updateHash = true } = {}) {
if (box) box.innerHTML = `<p class="muted">${escapeHtml(err.message || 'Konnte nicht geladen werden.')}</p>`
})
if (name === 'chat') {
api('/api/chat/read', { method: 'POST' }).catch(() => {})
markChatRead()
updateChatBadge(0)
}
if (updateHash) {
@@ -2070,8 +2089,8 @@ async function initDashboardPage() {
if (!me.authenticated) {
const target = new URL(loginUrl, window.location.origin)
// Passwort auf einem anderen Gerät geändert: Hinweis auf der Anmeldeseite
if (me.reason === 'password_changed' && me.message) target.searchParams.set('error', me.message)
// Passwort auf einem anderen Gerät geändert oder Kundenansicht abgelaufen: Hinweis auf der Anmeldeseite
if ((me.reason === 'password_changed' || me.reason === 'view_expired') && me.message) target.searchParams.set('error', me.message)
window.location.href = target.pathname + target.search
return
}
@@ -2085,6 +2104,8 @@ async function initDashboardPage() {
}
const customer = me.customer
// Kundenansicht: ab jetzt traegt jede /api-Anfrage die Kennung dieser Ansicht (public/kundenansicht.js)
if (me.viewId) window.KbView?.setId(me.viewId)
chatState.viewAs = Boolean(me.viewAs)
takeoverState.customer = customer
renderViewAsBanner(me)