108 lines
4.5 KiB
JavaScript
108 lines
4.5 KiB
JavaScript
/*! WEBklar Aufträge: öffentliche Bestätigungsseite (auftrag.html#t=<Token>, Rückfall ?t=). Link aus der Mail K31.
|
|
* Der Token steht nur in der Adresse, in Links und im Speicher der Seite, nie in Text, Ansage, Fehlermeldung oder Protokoll.
|
|
* Keine Cookies (credentials: 'omit'), kein Browserspeicher, keine Drittanfragen. Alle Texte stehen in auftrag-ansicht.js (Sie-Form)
|
|
* und kommen nur über textContent in die Seite. */
|
|
import {
|
|
KONTAKT, agbPfad, darfBestaetigen, pdfPfad, statusAnzeige, texte, tokenAusAdresse, zustandAusAntwort,
|
|
} from './auftrag-ansicht.js'
|
|
import { h, renderBestaetigtBlock, renderBestaetigung, renderDokumente, renderZusammenfassung } from './auftrag-dom.js'
|
|
|
|
/** Einzige Anfrage der Seite: { status, body }; jeder Fehler des Netzes ist Status 0 (nie die Meldung des Browsers weiterreichen). */
|
|
async function anfrage(token, aktion, { method = 'GET', body } = {}) {
|
|
try {
|
|
const antwort = await fetch(`/api/auftrag/${encodeURIComponent(token)}${aktion ? `/${aktion}` : ''}`, {
|
|
method,
|
|
credentials: 'omit',
|
|
headers: body ? { 'Content-Type': 'application/json' } : {},
|
|
body: body ? JSON.stringify(body) : undefined,
|
|
})
|
|
const daten = await antwort.json().catch(() => ({}))
|
|
return { status: antwort.status, body: daten !== null && typeof daten === 'object' ? daten : {} }
|
|
} catch {
|
|
return { status: 0, body: {} }
|
|
}
|
|
}
|
|
|
|
export async function initAuftragsseite({ root, ansage, suche = '', hash = '' }) {
|
|
const t = texte()
|
|
const token = tokenAusAdresse(suche, hash)
|
|
|
|
const sage = (text) => { ansage.textContent = text }
|
|
const zeige = (zustand, ...kinder) => {
|
|
root.dataset.zustand = zustand
|
|
root.setAttribute('aria-busy', zustand === 'laedt' ? 'true' : 'false')
|
|
root.replaceChildren(...kinder.filter(Boolean))
|
|
}
|
|
const kontakt = () => h('p', { class: 'ab-kontakt' },
|
|
t.kontaktVor, ' ',
|
|
h('a', { href: `mailto:${KONTAKT.email}` }, KONTAKT.email), ' oder ',
|
|
h('a', { href: `tel:${KONTAKT.telefon.replace(/\D/g, '')}` }, KONTAKT.telefon), '.')
|
|
|
|
function zeigeZustand({ zustand, titel, text }) {
|
|
zeige(zustand,
|
|
h('h1', { class: 'ab-h1', 'data-titel': true, tabindex: '-1' }, titel),
|
|
h('p', { class: 'ab-text' }, text),
|
|
zustand === 'limit' ? null : kontakt(),
|
|
zustand === 'limit' || zustand === 'fehler' ? h('button', { type: 'button', class: 'ab-knopf', 'data-aktion': 'erneut', onclick: () => lade() }, t.erneut) : null)
|
|
sage(titel)
|
|
}
|
|
|
|
async function senden(koerper) {
|
|
const { status, body } = await anfrage(token, 'bestaetigen', { method: 'POST', body: koerper })
|
|
if (status === 200 && body.auftrag) return { ok: true, auftrag: body.auftrag }
|
|
return { ok: false, status: status === 200 ? 0 : status, body }
|
|
}
|
|
|
|
function zeigeAuftrag(auftrag) {
|
|
const bestaetigt = Boolean(auftrag.bestaetigtAm)
|
|
const offen = darfBestaetigen(auftrag)
|
|
const status = statusAnzeige({ ...auftrag, kannBestaetigen: offen })
|
|
zeige(bestaetigt ? 'bestaetigt' : 'offen',
|
|
h('p', { class: `ab-pille ab-pille-${status.ton}` }, status.text),
|
|
h('h1', { class: 'ab-h1', 'data-titel': true, tabindex: '-1' }, bestaetigt ? t.titelBestaetigt : `${t.titelOffen} ${auftrag.nummer || ''}`.trim()),
|
|
bestaetigt ? null : h('p', { class: 'ab-intro' }, t.intro),
|
|
renderBestaetigtBlock(auftrag),
|
|
renderZusammenfassung(auftrag),
|
|
h('section', { class: 'ab-abschnitt' },
|
|
h('h2', { class: 'ab-h2' }, t.unterlagen),
|
|
renderDokumente({ pdfHref: pdfPfad(token), agbHref: agbPfad(auftrag.agbUrl) })),
|
|
offen
|
|
? renderBestaetigung(auftrag, {
|
|
senden,
|
|
nachErfolg: (neu) => {
|
|
zeigeAuftrag(neu)
|
|
sage(t.titelBestaetigt)
|
|
root.querySelector('[data-bestaetigt]')?.focus()
|
|
},
|
|
nachEnde: (code, antwortBody) => zeigeZustand(zustandAusAntwort(code, antwortBody)),
|
|
})
|
|
: null)
|
|
}
|
|
|
|
async function lade() {
|
|
if (!token) {
|
|
zeigeZustand(zustandAusAntwort(404, {}))
|
|
return
|
|
}
|
|
zeige('laedt', h('p', { class: 'ab-laden' }, t.laedt))
|
|
const { status, body } = await anfrage(token, '')
|
|
if (status === 200 && body.auftrag) {
|
|
zeigeAuftrag(body.auftrag)
|
|
sage(t.geladen)
|
|
} else {
|
|
zeigeZustand(zustandAusAntwort(status === 200 ? 0 : status, body))
|
|
}
|
|
}
|
|
|
|
await lade()
|
|
}
|
|
|
|
if (typeof document !== 'undefined' && document.getElementById('ab-wurzel')) {
|
|
initAuftragsseite({
|
|
root: document.getElementById('ab-wurzel'),
|
|
ansage: document.getElementById('ab-ansage'),
|
|
suche: window.location.search,
|
|
hash: window.location.hash,
|
|
})
|
|
}
|