Funktionen neu: Einschalten senden, 409-Folgen, Wechsel mit gemerkter Funktion, zeigeEinschalten für die Module
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
906c9ec1f0
commit
57112cc51f
2 files changed
+327
-7
No files matched your search
@@ -23,6 +23,7 @@ export const TEXTE = Object.freeze({
|
||||
nurBetrieb: (name) => `${name} gibt es für Betriebe. Stimmt das nicht? Schreib uns im Chat.`,
|
||||
registerFehlt: 'Einschalten ist gerade nicht möglich. Schreib uns im Chat.',
|
||||
kundenansicht: 'In der Kundenansicht kann nichts eingeschaltet werden.',
|
||||
laden: 'Die Angaben konnten gerade nicht geladen werden. Bitte versuch es gleich noch einmal.',
|
||||
})
|
||||
|
||||
/** Die Erklärung der Funktion aus dem Katalog der Antwort (einzige Stelle für das Register); fehlt sie, null. */
|
||||
@@ -213,16 +214,29 @@ export function fehlerAktion(fehler, { eintrag }) {
|
||||
* @returns {HTMLElement} section.kn-fn-einschalten
|
||||
*/
|
||||
export function renderEinschalten(behaelter, o) {
|
||||
const { key, projectId, viewAs = false, imModul = false, jetzt = () => new Date(), bei = {} } = o
|
||||
const { key, projectId, viewAs = false, imModul = false, jetzt = () => new Date() } = o
|
||||
let daten = o.daten
|
||||
const api = o.api ?? apiStandard
|
||||
const geheZu = o.geheZu ?? geheZuStandard
|
||||
const kundenart = () => (o.kundenartWirksam === undefined ? daten?.kundenart : o.kundenartWirksam)
|
||||
const z = { haken: false, serverAb: '', sperreAb: '', sendet: false, meldung: '' }
|
||||
const z = { haken: false, serverAb: '', sperreAb: '', erzwingeHaken: false, sendet: false, meldung: '' }
|
||||
// Standards der Rückmeldungen (Task 4): Erfolg merkt die Meldung und geht zu Meine, Abbrechen zu Entdecken
|
||||
const bei = {
|
||||
fertig: (antwort) => { merkeMeldung(erfolgText(String(eintragVon()?.name ?? key), antwort)); geheZu('#funktionen', { ersetzen: true }) },
|
||||
weiter: (weg) => navigiere(weg, { key, projectId }, { geheZu, speicher: o.speicher }),
|
||||
abbrechen: () => geheZu('#entdecken', { ersetzen: true }),
|
||||
neuLaden: () => api('/api/funktionen'),
|
||||
...o.bei,
|
||||
}
|
||||
const abschnitt = h('section', { class: 'kn-fn-einschalten', 'data-key': key, 'data-projekt': projectId })
|
||||
let knopf = null
|
||||
let meldungEl = null
|
||||
|
||||
const eintragVon = () => (Array.isArray(daten?.katalog) ? daten.katalog.find((e) => e?.key === key) ?? null : null)
|
||||
const lageJetzt = () => beginnLage({ kundenart: kundenart(), abo: daten?.abo, jetzt: jetzt(), serverAb: z.serverAb })
|
||||
const lageJetzt = () => {
|
||||
const lage = beginnLage({ kundenart: kundenart(), abo: daten?.abo, jetzt: jetzt(), serverAb: z.serverAb })
|
||||
return z.erzwingeHaken && !lage.noetig ? { noetig: true, ab: '' } : lage // beginn_noetig ohne lesbares Datum: Häkchen trotzdem zeigen
|
||||
}
|
||||
|
||||
function aktualisiereKnopf() {
|
||||
if (!knopf) return
|
||||
@@ -278,18 +292,147 @@ export function renderEinschalten(behaelter, o) {
|
||||
viewAs ? h('p', { class: 'kn-fn-info' }, TEXTE.kundenansicht) : null,
|
||||
meldungEl,
|
||||
h('div', { class: 'kn-fn-aktionen' },
|
||||
knopf ?? h('button', { type: 'button', class: 'kn-fn-knopf', 'data-aktion': 'chat', on: { click: () => (o.geheZu ?? geheZuStandard)('#chat') } }, 'Im Chat schreiben'),
|
||||
imModul ? null : h('button', { type: 'button', class: 'kn-fn-knopf kn-fn-knopf--zweit', 'data-aktion': 'abbrechen', on: { click: () => bei.abbrechen?.() } }, 'Abbrechen')),
|
||||
knopf ?? h('button', { type: 'button', class: 'kn-fn-knopf', 'data-aktion': 'chat', on: { click: () => geheZu('#chat') } }, 'Im Chat schreiben'),
|
||||
imModul ? null : h('button', { type: 'button', class: 'kn-fn-knopf kn-fn-knopf--zweit', 'data-aktion': 'abbrechen', on: { click: () => bei.abbrechen() } }, 'Abbrechen')),
|
||||
]
|
||||
abschnitt.replaceChildren(...kinder.flat(Infinity).filter(Boolean))
|
||||
aktualisiereKnopf()
|
||||
}
|
||||
|
||||
async function senden() {
|
||||
// folgt in Task 4
|
||||
if (z.sendet || viewAs || z.sperreAb) return
|
||||
const eintrag = eintragVon()
|
||||
const consent = consentVon(daten, key)
|
||||
const lage = lageJetzt()
|
||||
if (!eintrag || !consent || (lage.noetig && !z.haken)) return
|
||||
z.sendet = true
|
||||
setzeMeldung('')
|
||||
aktualisiereKnopf()
|
||||
let antwort
|
||||
try {
|
||||
antwort = await api(`/api/funktionen/${encodeURIComponent(key)}/einschalten`, {
|
||||
method: 'POST',
|
||||
body: einschaltKoerper({ projectId, consent, beginnGesetzt: lage.noetig && z.haken }),
|
||||
})
|
||||
} catch (fehler) {
|
||||
z.sendet = false
|
||||
await behandleFehler(fehler, eintrag)
|
||||
return
|
||||
}
|
||||
bei.fertig(antwort) // der Knopf bleibt gesperrt: nach Erfolg gibt es nichts mehr zu senden
|
||||
}
|
||||
|
||||
async function behandleFehler(fehler, eintrag) {
|
||||
const aktion = fehlerAktion(fehler, { eintrag })
|
||||
switch (aktion.art) {
|
||||
case 'wechsel':
|
||||
case 'bestellen':
|
||||
aktualisiereKnopf()
|
||||
bei.weiter(aktion)
|
||||
break
|
||||
case 'etage': // im Modul steht der Servertext (die Etage ist schon offen), sonst führt die Seite hin
|
||||
if (imModul) { setzeMeldung(fehler?.message || TEXTE.allgemein); aktualisiereKnopf() } else { aktualisiereKnopf(); bei.weiter(aktion) }
|
||||
break
|
||||
case 'schon':
|
||||
bei.fertig(null)
|
||||
break
|
||||
case 'beginn': // Häkchen zeigen, Knopf bis dahin gesperrt mit Datum
|
||||
z.serverAb = typeof aktion.ab === 'string' ? aktion.ab : ''
|
||||
z.erzwingeHaken = true
|
||||
z.haken = false
|
||||
fuelle()
|
||||
abschnitt.querySelector('input[data-haken="beginn"]')?.focus?.()
|
||||
break
|
||||
case 'spaeter': // das Abo beginnt später: Text und gesperrter Knopf mit Datum, kein Häkchen
|
||||
z.sperreAb = berlinTag(aktion.ab)
|
||||
setzeMeldung(aktion.text)
|
||||
aktualisiereKnopf()
|
||||
break
|
||||
case 'neu-laden':
|
||||
try {
|
||||
daten = await bei.neuLaden()
|
||||
z.haken = false
|
||||
z.serverAb = ''
|
||||
z.erzwingeHaken = false
|
||||
setzeMeldung(aktion.text)
|
||||
fuelle()
|
||||
} catch {
|
||||
setzeMeldung(TEXTE.allgemein)
|
||||
aktualisiereKnopf()
|
||||
}
|
||||
break
|
||||
default:
|
||||
setzeMeldung(aktion.text)
|
||||
aktualisiereKnopf()
|
||||
}
|
||||
}
|
||||
|
||||
leeren(behaelter).append(abschnitt)
|
||||
fuelle()
|
||||
return abschnitt
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------ Navigation und Meldungen --- */
|
||||
|
||||
/**
|
||||
* Wohin nach einem Weg von einschaltWeg oder fehlerAktion? ziel = { key, projectId }; 'seite' behandelt die Ansicht selbst.
|
||||
* etage → #<etage>?projekt=<id>, bestellen → #bestellen-<produkt>, wechsel → die gewünschte Funktion merken (V11), dann #wechsel.
|
||||
* Der Wechsel geht auch, wenn sessionStorage fehlt oder voll ist.
|
||||
*/
|
||||
export async function navigiere(weg, ziel, { geheZu = geheZuStandard, speicher } = {}) {
|
||||
switch (weg?.art) {
|
||||
case 'etage':
|
||||
geheZu(`#${weg.etage}?projekt=${encodeURIComponent(ziel.projectId)}`)
|
||||
break
|
||||
case 'bestellen':
|
||||
geheZu(`#bestellen-${weg.produkt}`)
|
||||
break
|
||||
case 'wechsel':
|
||||
try {
|
||||
const ablage = speicher ?? globalThis.sessionStorage
|
||||
ablage.setItem('kn-wechsel-funktion', JSON.stringify({ key: ziel.key, projectId: ziel.projectId }))
|
||||
} catch { /* ohne Speicher geht der Wechsel trotzdem; nur die Rückkehr zur Funktion entfällt */ }
|
||||
geheZu('#wechsel')
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
/** Text nach dem Einschalten; antwort null heißt: war schon eingeschaltet. */
|
||||
export function erfolgText(name, antwort) {
|
||||
if (!antwort) return `${name} ist schon eingeschaltet.`
|
||||
const ticket = antwort.ticketWoid ? ` Ticket #${antwort.ticketWoid}.` : ''
|
||||
return `${name} ist eingeschaltet. Die Einrichtung läuft jetzt.${ticket}`
|
||||
}
|
||||
|
||||
let gemerkteMeldung = ''
|
||||
/** Merkt genau eine Meldung für den nächsten Aufbau von Meine oder Entdecken. */
|
||||
export function merkeMeldung(text) { gemerkteMeldung = String(text ?? '') }
|
||||
/** Gibt die gemerkte Meldung zurück und vergisst sie. */
|
||||
export function nimmMeldung() {
|
||||
const text = gemerkteMeldung
|
||||
gemerkteMeldung = ''
|
||||
return text
|
||||
}
|
||||
|
||||
/**
|
||||
* Vertrag mit den Funktionsmodulen (P4, VF1): die Bestätigungsseite in `platz`, ohne „Abbrechen“. Lädt GET /api/funktionen, wenn
|
||||
* `daten` fehlt. onFertig({ feature, ticketWoid }) nach 200, onFertig({ feature: null, ticketWoid: null }) nach 409 bereits_eingeschaltet;
|
||||
* alle anderen Fehler zeigt die Seite selbst. Liefert die gezeichnete Seite (oder die Fehlerzeile beim Laden).
|
||||
*/
|
||||
export async function zeigeEinschalten(platz, { key, projectId, onFertig, daten, kundenartWirksam, viewAs = false, api = apiStandard, geheZu, speicher, jetzt } = {}) {
|
||||
let liste = daten
|
||||
if (!liste) {
|
||||
leeren(platz).append(h('p', { class: 'kn-leer' }, 'Wird geladen …'))
|
||||
try {
|
||||
liste = await api('/api/funktionen')
|
||||
} catch {
|
||||
return leeren(platz).appendChild(h('p', { class: 'kn-fn-info', role: 'alert' }, TEXTE.laden,
|
||||
h('button', { type: 'button', class: 'kn-fn-knopf kn-fn-knopf--zweit', 'data-aktion': 'nochmal', on: { click: () => zeigeEinschalten(platz, { key, projectId, onFertig, kundenartWirksam, viewAs, api, geheZu, speicher, jetzt }) } }, 'Nochmal versuchen')))
|
||||
}
|
||||
}
|
||||
return renderEinschalten(platz, {
|
||||
key, projectId, daten: liste, kundenartWirksam, viewAs, imModul: true, api, geheZu, speicher, jetzt,
|
||||
bei: { fertig: (antwort) => onFertig?.(antwort ?? { feature: null, ticketWoid: null }) },
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user