Terminplaner TP2 C10a: Nachbesserung 1 (Abo-Hinweis vom Server, R111)
GET /api/funktionen liefert bei termine.verfuegbar ein fuenftes Feld hinweis (aboMeldung mit dem Register des Terminplaners, null bei bestellbar true). Die Kachel zeigt diesen Text maskiert an; die Browser-Kopie der Abo-Texte und der Gleichheitstest entfallen. Der Link "Zu Verträge" ist eine gemeinsame Konstante fuer Analyse und Terminplaner und erscheint bei kein_abo. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6ae0f67457
commit
52456dac76
5 files changed
+141
-63
No files matched your search
+12
-20
@@ -112,6 +112,9 @@ function newsTile(projects, price = PRICE) {
|
||||
</article>`
|
||||
}
|
||||
|
||||
// Link in den Hinweisen ohne Wartungs-Abo (kein_abo): Analyse-Kachel, Analyse-Seite und Terminplaner-Kachel teilen ihn
|
||||
const ZU_VERTRAEGE_LINK = '<button type="button" class="kb-link" data-view="vertraege">Zu Verträge</button>'
|
||||
|
||||
/* Analyse: Kachel je nach Zustand der Websites (comingSoon = Schalter aus) */
|
||||
const analyseOf = (project) => project.analyse || { comingSoon: true }
|
||||
const analyseState = (a) => (a.comingSoon ? 'soon' : a.state === 'unknown' ? 'unknown' : a.state === 'disabled' ? 'disabled' : a.state === 'active' ? 'active' : a.eligible ? 'off' : 'blocked')
|
||||
@@ -136,7 +139,7 @@ function analyseTile(projects) {
|
||||
else if (state === 'disabled') { text = 'Bitte melde dich bei uns'; action = '<button type="button" class="kb-btn-primary fn-tile-cta" data-view="chat">Chat öffnen</button>' }
|
||||
else if (state === 'active') action = `<button type="button" class="kb-btn-primary fn-tile-cta" data-view="analyse" data-project="${esc(target.projectId)}">Auswertung ansehen</button>`
|
||||
else if (state === 'off') action = `<button type="button" class="kb-btn-primary fn-tile-cta" data-view="analyse" data-project="${esc(target.projectId)}">Einrichten</button>`
|
||||
else if (a.reason === 'kein_abo') action = '<p class="fn-count">Im Wartungs-Abo enthalten. <button type="button" class="kb-link" data-view="vertraege">Zu Verträge</button></p>'
|
||||
else if (a.reason === 'kein_abo') action = `<p class="fn-count">Im Wartungs-Abo enthalten. ${ZU_VERTRAEGE_LINK}</p>`
|
||||
else action = `<p class="fn-count">${esc(a.reasonText || 'Für diese Website gerade nicht verfügbar.')}</p>`
|
||||
const count = projects.length > 1 && active ? `<p class="fn-count">aktiv für ${active} von ${projects.length} Websites</p>` : ''
|
||||
return `
|
||||
@@ -153,29 +156,15 @@ function analyseTile(projects) {
|
||||
/* Terminplaner: Kachel nur, wenn der Schalter es erlaubt (termine.verfuegbar), sonst "Kommt bald". Die Ansicht selbst
|
||||
(termine.js) wird von app.js geladen; hier steht nur die Kachel, damit funktionen.js keinen weiteren Import braucht.
|
||||
termine (Antwort von /api/funktionen) traegt bei verfuegbar: true bestellbar (true | false | null = Abo nicht lesbar),
|
||||
grund (kein_abo | gekuendigt | nicht_aktiv | null), preis und einrichtung. Das Abo betrifft nur die Bestellung: ohne laufendes
|
||||
Abo gibt es im Zustand Aus keinen Weg in die Ansicht; wer schon bestellt hat oder den Terminplaner nutzt, behaelt seinen. */
|
||||
grund (kein_abo | gekuendigt | nicht_aktiv | null), preis, einrichtung und hinweis (Abo-Text des Servers, aboMeldung in
|
||||
server/services/featureOrder.js, bei bestellbar true null). Das Abo betrifft nur die Bestellung: ohne laufendes Abo gibt es im
|
||||
Zustand Aus keinen Weg in die Ansicht; wer schon bestellt hat oder den Terminplaner nutzt, behaelt seinen. */
|
||||
const TERMINE_TEXT = 'Deine Kundschaft bucht Termine direkt über deine Website.'
|
||||
const termineOf = (project) => project.features?.termine || { state: 'off' }
|
||||
// Doppelt zu anfragenText in termine-view.js: funktionen.js darf dort nichts importieren (die Kachel testet test/funktionenTiles.test.js
|
||||
// mit einem umgebogenen Import). Aenderungen an beiden Stellen machen.
|
||||
const anfragenText = (n) => (n === 1 ? '1 Anfrage wartet' : `${n} Anfragen warten`)
|
||||
|
||||
// Abo-Hinweise der Kachel. Kopie von aboMeldung (server/services/featureOrder.js, einzige Quelle der Abo-Hinweistexte) fuer den
|
||||
// Terminplaner; test/funktionenTiles.test.js haelt beide gleich. kein_abo steht wie bei der Analyse im Wortlaut der Kachel.
|
||||
const TERMINE_ABO_TEXTE = {
|
||||
gekuendigt: 'Dein Wartungs-Abo ist gekündigt. Für den Terminplaner brauchst du ein laufendes Abo.',
|
||||
nicht_aktiv: 'Dein Wartungs-Abo ist gerade nicht aktiv (zum Beispiel wegen einer offenen Zahlung). Sobald es wieder aktiv ist, kannst du den Terminplaner bestellen.',
|
||||
unbekannt: 'Das Abo konnte gerade nicht geprüft werden.',
|
||||
}
|
||||
const KEIN_ABO_HINWEIS = 'Im Wartungs-Abo enthalten. <button type="button" class="kb-link" data-view="vertraege">Zu Verträge</button>'
|
||||
|
||||
function termineAboHinweis(angebot) {
|
||||
if (angebot.bestellbar !== false) return TERMINE_ABO_TEXTE.unbekannt // null (Lesefehler) oder Feld fehlt: nicht geprueft
|
||||
if (angebot.grund === 'kein_abo') return KEIN_ABO_HINWEIS
|
||||
return Object.hasOwn(TERMINE_ABO_TEXTE, angebot.grund) && angebot.grund !== 'unbekannt' ? TERMINE_ABO_TEXTE[angebot.grund] : TERMINE_ABO_TEXTE.unbekannt
|
||||
}
|
||||
|
||||
// Entwurf: Funktionsdokument im Zustand Aus mit siteKey (entsteht beim ersten Speichern des Fragebogens)
|
||||
const hatEntwurf = (project) => termineOf(project).state === 'off' && Boolean(termineOf(project).siteKey)
|
||||
|
||||
@@ -216,7 +205,10 @@ function termineTile(projects, angebot = {}) {
|
||||
const preis = typeof angebot.preis === 'string' && angebot.preis.trim() ? ` · ${esc(angebot.preis)}` : ''
|
||||
action = knopf(hatEntwurf(target) ? 'Fragebogen fortsetzen' : `Terminplaner einrichten${preis}`)
|
||||
} else {
|
||||
extra = `<p class="fn-count">${termineAboHinweis(angebot)}</p>`
|
||||
// Hinweis des Servers (maskiert), bei kein_abo dazu der Weg in die Verträge; ohne Text bleibt nur der Link oder nichts
|
||||
const hinweis = typeof angebot.hinweis === 'string' ? esc(angebot.hinweis) : ''
|
||||
const zeile = [hinweis, angebot.bestellbar === false && angebot.grund === 'kein_abo' ? ZU_VERTRAEGE_LINK : ''].filter(Boolean).join(' ')
|
||||
if (zeile) extra = `<p class="fn-count">${zeile}</p>`
|
||||
}
|
||||
const count = projects.length > 1 && active ? `<p class="fn-count">aktiv für ${active} von ${projects.length} Websites</p>` : ''
|
||||
return `
|
||||
@@ -695,7 +687,7 @@ export async function initAnalyse(root, { projectId } = {}) {
|
||||
if (a.state === 'active') renderAnalyseStats(stage, project, reload)
|
||||
else if (a.state === 'disabled') stage.innerHTML = '<div class="kb-panel"><h3>Analyse ist abgeschaltet</h3><p>Für diese Website ist die Analyse im Moment gesperrt. <button type="button" class="kb-link" data-view="chat">Schreib uns im Chat</button>, dann klären wir das.</p></div>'
|
||||
else if (a.state === 'unknown') stage.innerHTML = '<div class="kb-panel"><p>Die Daten konnten gerade nicht geladen werden.</p></div>'
|
||||
else if (!a.eligible) stage.innerHTML = `<div class="kb-panel"><h3>Analyse nicht verfügbar</h3><p>${esc(a.reasonText || 'Für diese Website gerade nicht verfügbar.')}${a.reason === 'kein_abo' ? ' <button type="button" class="kb-link" data-view="vertraege">Zu Verträge</button>' : ''}</p></div>`
|
||||
else if (!a.eligible) stage.innerHTML = `<div class="kb-panel"><h3>Analyse nicht verfügbar</h3><p>${esc(a.reasonText || 'Für diese Website gerade nicht verfügbar.')}${a.reason === 'kein_abo' ? ` ${ZU_VERTRAEGE_LINK}` : ''}</p></div>`
|
||||
else renderAnalyseActivation(stage, project, reload)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user