Terminplaner TP2: Ansicht nach Zustand und Rueckkehr von Stripe

Die Ansicht #termine folgt dem Zustand aus GET /api/termine/einstellungen:
off mit laufendem Abo zeigt den Fragebogen samt Bestellseite, ohne Abo den
Hinweis des Servers (termine.hinweis, R111) und bei kein_abo den Link zu
Vertraege aus einer gemeinsamen Quelle (vertraege-link.js); ordered und setup
zeigen die Statuskarte und die Reiter Leistungen, Team & Plaetze und
Einstellungen nur zum Lesen (ohne Reiter Termine); active und disabled
bleiben wie bisher. Rueckkehr von Stripe: #termine?bestellt=1&projekt=<id>
und #termine?projekt=<id> waehlen das Projekt, "Danke!" nur mit bestellt=1,
die Adresse wird einmal gelesen und bereinigt.

R110: GET /einstellungen liefert bestellung und offen auch in ordered (ohne
Abo-Punkt, abo bleibt null); scheitert "Zahlung fortsetzen", zeichnet die
Huelle Liste und Daten neu (bei 409 zustimmung_fehlt mit dem
Bestellformular, sonst nach dem neuen Zustand, die Meldung bleibt am Knopf,
solange die Bestellung offen ist).

Dazu: "null" als Text im lesbaren Reiter Leistungen entfernt, Export und
Status der Einstellungen erst ab der Freischaltung.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-04 23:10:54 +00:00
1 parent 52456dac76
commit 87d267e51a
13 files changed
+1077 -71

No files matched your search

+15 -8
View File
@@ -259,10 +259,14 @@ function baueSeite(root, { ctx, daten, zumSchritt }, uebernahme) {
* Karte für eine Bestellung im Zustand ordered („Zahlung offen“) oder setup („In Einrichtung“).
* projekt = Eintrag des Projekts aus GET /api/funktionen (projectId), bestellung = projekt.features.termine (state, orderedAt, ticketWoid,
* invoiceUrl), einrichtung = Text der Zeiteinschätzung (Register: setupEstimate), danke = Rückkehr von Stripe, kundenansicht = Sitzung in der
* Kundenansicht. weiter() wird gerufen, wenn „Zahlung fortsetzen“ mit 409 zustimmung_fehlt antwortet (keine offene Sitzung mit Nachweis): es
* lädt die Seite neu und zeigt wieder das Bestellformular. Fehlt weiter, steht die Meldung des Servers am Knopf.
* Kundenansicht, meldung = Text, der am Knopf „Zahlung fortsetzen“ steht (z. B. der Fehler eines Versuchs vor dem Neuzeichnen).
* weiter(fall) wird gerufen, wenn „Zahlung fortsetzen“ scheitert (Ruling R110): fall = { bestellen, meldung }, bestellen ist wahr bei 409
* zustimmung_fehlt (keine offene Sitzung mit Nachweis: die Ansicht zeigt wieder das Bestellformular), meldung der Fehlertext der Antwort.
* weiter() lädt neu und zeichnet die Ansicht nach dem Zustand von neuem, damit keine veraltete Karte stehen bleibt (z. B. wenn die Bestellung
* inzwischen bezahlt ist und der Server 400 antwortet); wirft es, bleibt die Karte stehen und der Fehler steht am Knopf. Fehlt weiter,
* steht die Meldung des Servers am Knopf.
*/
export function statusKarte({ projekt, bestellung, einrichtung, danke, kundenansicht } = {}, { weiter } = {}) {
export function statusKarte({ projekt, bestellung, einrichtung, danke, kundenansicht, meldung } = {}, { weiter } = {}) {
const bestellt = bestellung?.state === 'ordered'
const datum = datumTag(bestellung?.orderedAt)
const ticket = bestellung?.ticketWoid
@@ -275,7 +279,7 @@ export function statusKarte({ projekt, bestellung, einrichtung, danke, kundenans
!bestellt && text(einrichtung) ? zeile('Zeiteinschätzung', einrichtung) : null,
].filter(Boolean)
const meldungEl = h('p', { class: 'tm-fehler', role: 'alert', 'data-meldung': 'fortsetzen' })
const meldungEl = h('p', { class: 'tm-fehler', role: 'alert', 'data-meldung': 'fortsetzen' }, text(meldung) || null)
const fortsetzenKnopf = bestellt
? h('button', { type: 'button', class: 'kb-btn-primary', 'data-aktion': 'fortsetzen', disabled: kundenansicht === true, onclick: () => fortsetzen() }, 'Zahlung fortsetzen')
: null
@@ -289,15 +293,18 @@ export function statusKarte({ projekt, bestellung, einrichtung, danke, kundenans
if (geheZu(antwort?.url)) return // die Seite wird verlassen
meldungEl.textContent = ZAHLUNGSSEITE
} catch (err) {
if (err?.status === 409 && err.code === 'zustimmung_fehlt' && typeof weiter === 'function') {
const nachricht = err?.message || ZAHLUNGSSEITE
const zustimmungFehlt = err?.status === 409 && err.code === 'zustimmung_fehlt'
if (typeof weiter === 'function') {
try {
await weiter()
await weiter({ bestellen: zustimmungFehlt, meldung: nachricht })
return // die Ansicht zeichnet sich neu
} catch (fehler) {
meldungEl.textContent = fehler?.message || ZAHLUNGSSEITE
// Neuladen gescheitert: bei fehlender Zustimmung ist das der Grund, der den Kunden betrifft, sonst bleibt der Fehler des Versuchs
meldungEl.textContent = zustimmungFehlt ? fehler?.message || ZAHLUNGSSEITE : nachricht
}
} else {
meldungEl.textContent = err?.message || ZAHLUNGSSEITE
meldungEl.textContent = nachricht
}
}
fortsetzenKnopf.disabled = false