Funktionen neu: Bestätigung als Overlay der Zurück-Geste, Erfolgsmeldung, Rückkehr nach dem Wechsel

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-16 18:11:36 +00:00
1 parent f30e72ebbb
commit 36890c6734
2 files changed
+150 -17

No files matched your search

+56 -17
View File
@@ -127,11 +127,13 @@ export function zeilenWeg(zeile) {
const laeufe = new WeakMap() // Wurzel → Nummer des jüngsten Aufrufs: eine ältere Antwort zeichnet nichts mehr
let reiterGewaehlt = false // Tipp auf „Meine“: der nächste Aufruf zeigt den Leerzustand statt zu Entdecken zu springen
let vorgabe = null // nach einer eigenen Navigation (Reiter, Sprung zu Entdecken) nimmt der nächste Aufruf die geladenen Antworten
const wechselErledigt = new Set() // 'key:projectId' der Funktionen, in die die Rückkehr vom Wechsel schon geführt hat (je Seitenaufruf einmal)
/** Setzt die Merker des Moduls zurück (nur für Tests). */
export function vergissMerker() {
reiterGewaehlt = false
vorgabe = null
wechselErledigt.clear()
}
const BILD = /^\/neu\/bilder\/[a-z0-9-]+\.webp$/
@@ -160,6 +162,7 @@ export async function zeigeFunktionen(wurzel, { route, me, nav } = {}, abh = {})
let daten
let offen
const frisch = !mitgebracht
if (mitgebracht) {
({ daten, offen } = mitgebracht)
} else {
@@ -183,18 +186,17 @@ export async function zeigeFunktionen(wurzel, { route, me, nav } = {}, abh = {})
const kundenart = me?.customer?.kundenartWirksam ?? daten.kundenart
const viewAs = me?.viewAs === true
const zeilen = meineZeilen(daten)
if (reiterWahl === 'meine' && zeilen.length === 0 && !ausdruecklich) {
vorgabe = { wurzel, daten, offen, bis: Date.now() + 5000 }
A.geheZu('#entdecken', { ersetzen: true })
return
}
const projektVon = (projectId) => daten.projects.find((p) => p?.projectId === projectId)
const weiter = (weg, ziel) => navigiere(weg, ziel, { geheZu: A.geheZu, speicher: A.speicher })
let gezeigteMeldung = ''
/** Die Bestätigungsseite für diese Funktion und Website. */
/** Die Bestätigungsseite für diese Funktion und Website als Overlay: die Zurück-Geste und „Abbrechen“ bringen die Liste ohne neuen Abruf zurück. */
function oeffneSeite(key, projectId) {
renderEinschalten(wurzel, { key, projectId, daten, kundenartWirksam: kundenart, viewAs, jetzt: A.jetzt, api: A.api, geheZu: A.geheZu, speicher: A.speicher })
A.oeffneOverlay({ schliesse: () => { if (aktuell()) zeichneListe() } })
renderEinschalten(wurzel, {
key, projectId, daten, kundenartWirksam: kundenart, viewAs, jetzt: A.jetzt, api: A.api, geheZu: A.geheZu, speicher: A.speicher,
bei: { abbrechen: () => A.beendeOverlay() },
})
}
/** „Einschalten“ für eine Website: die Vorprüfung wählt den Ort; eine Meldung steht im Eintrag. */
@@ -206,6 +208,38 @@ export async function zeigeFunktionen(wurzel, { route, me, nav } = {}, abh = {})
else weiter(weg, { key: eintrag.key, projectId: kandidat.projectId })
}
/**
* Rückkehr vom Wechsel ins Wartungs-Abo (V11): hat der Kunde den Wechsel für eine Funktion begonnen und hat die Website sie noch nicht,
* öffnet die Ansicht ihren Ablauf, je Seitenaufruf einmal. Jeder Fehler und jede ungültige Angabe wird ignoriert.
* @returns {Promise<boolean>} true, wenn ein Ablauf geöffnet wurde
*/
async function wechselRueckkehr() {
if (daten.abo?.produkt !== 'wartung' || daten.abo.laeuft !== true) return false
let abo
try { abo = await A.api('/api/abo') } catch { return false }
if (!aktuell()) return false
const f = abo?.subscription?.wechselFunktion
if (!f || typeof f.key !== 'string' || typeof f.projectId !== 'string') return false
const merker = `${f.key}:${f.projectId}`
const eintrag = verfuegbare(daten).find((e) => e.key === f.key)
const projekt = projektVon(f.projectId)
if (!eintrag || !projekt || wechselErledigt.has(merker) || istInMeine(eintrag, projekt)) return false
const weg = einschaltWeg({ eintrag, projekt, abo: daten.abo, kundenart })
if (weg.art !== 'seite' && weg.art !== 'etage') return false
wechselErledigt.add(merker)
if (weg.art === 'seite') oeffneSeite(f.key, f.projectId)
else weiter(weg, { key: f.key, projectId: f.projectId })
return true
}
if (frisch && await wechselRueckkehr()) return
if (!aktuell()) return
if (reiterWahl === 'meine' && zeilen.length === 0 && !ausdruecklich) {
vorgabe = { wurzel, daten, offen, bis: Date.now() + 5000 }
A.geheZu('#entdecken', { ersetzen: true })
return
}
function meineListe() {
if (zeilen.length === 0) {
return [
@@ -277,13 +311,18 @@ export async function zeigeFunktionen(wurzel, { route, me, nav } = {}, abh = {})
A.geheZu(key === 'meine' ? '#funktionen' : '#entdecken', { ersetzen: true })
}
const meldung = nimmMeldung()
const reiter = baueReiter({ eintraege: [{ key: 'meine', label: 'Meine' }, { key: 'entdecken', label: 'Entdecken' }], aktiv: reiterWahl, art: 'unterstrich', ariaLabel: 'Funktionen', bei: wechsleReiter })
leeren(wurzel).append(
...[
meldung ? h('p', { class: 'kn-meldung kn-meldung-ok', role: 'status' }, meldung) : null,
rechnungOffenZeile(offen),
reiter,
h('div', { class: 'kn-reiter-inhalt' }, reiterWahl === 'meine' ? meineListe() : entdeckenListe()),
].filter(Boolean))
/** Reiter, Rechnungszeile und Liste aus den geladenen Antworten zeichnen (auch nach dem Schließen der Bestätigung, ohne Abruf). */
function zeichneListe() {
const reiter = baueReiter({ eintraege: [{ key: 'meine', label: 'Meine' }, { key: 'entdecken', label: 'Entdecken' }], aktiv: reiterWahl, art: 'unterstrich', ariaLabel: 'Funktionen', bei: wechsleReiter })
leeren(wurzel).append(
...[
gezeigteMeldung ? h('p', { class: 'kn-meldung kn-meldung-ok', role: 'status' }, gezeigteMeldung) : null,
rechnungOffenZeile(offen),
reiter,
h('div', { class: 'kn-reiter-inhalt' }, reiterWahl === 'meine' ? meineListe() : entdeckenListe()),
].filter(Boolean))
}
gezeigteMeldung = nimmMeldung() // genau einmal; nach dem Schließen der Bestätigung bleibt sie stehen
zeichneListe()
}