Buchungskalender: Abschluss – Buchungsseite zeigt 409-Codes, nur https-Zahlung, Feldfehler barrierefrei
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a071e57fb7
commit
392b85c1f0
3 files changed
+102
-13
No files matched your search
@@ -14,6 +14,8 @@ body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;b
|
||||
.uk-feld input{width:100%;padding:10px 12px;border:1px solid #cbd5e1;border-radius:8px;font:inherit;background:#fff}
|
||||
.uk-feld input:focus-visible,.uk-knopf:focus-visible,.uk-zahlart input:focus-visible,.uk-link:focus-visible{outline:3px solid var(--uk-akzent);outline-offset:2px}
|
||||
.uk-zeile2{display:grid;grid-template-columns:1fr 2fr;gap:12px}
|
||||
.uk-zahlart-gruppe{border:0;margin:0 0 12px;padding:0;min-width:0}.uk-zahlart-gruppe legend{font-size:1.1rem;font-weight:700;padding:0;margin:0 0 8px}
|
||||
.uk-feld input[aria-invalid="true"]{border-color:#b91c1c;border-width:2px}
|
||||
.uk-zahlart{display:flex;gap:10px;align-items:flex-start;margin:0 0 8px}
|
||||
.uk-zahlart input{margin-top:5px}
|
||||
.uk-pflicht{margin:20px 0 16px;padding:14px 16px;border:1px solid #e5e7eb;border-radius:8px;background:#f9fafb;font-size:.92rem}
|
||||
|
||||
@@ -26,12 +26,16 @@
|
||||
ungueltig: 'Dieser Link ist ungültig.',
|
||||
abgelaufen: 'Die Reservierung ist abgelaufen. Bitte fragen Sie erneut an.',
|
||||
abbruch: 'Zahlung abgebrochen – Sie können jetzt oder vor Ort bezahlen.',
|
||||
widerruf: 'Ein Widerrufsrecht besteht nicht (§ 312g Abs. 2 Nr. 9 BGB).',
|
||||
widerruf: 'Ein Widerrufsrecht besteht nicht (§ 312g Abs. 2 Satz 1 Nr. 9 BGB).',
|
||||
kleinunternehmer: 'Gemäß § 19 UStG wird keine Umsatzsteuer berechnet.',
|
||||
laden: 'Die Buchung konnte nicht geladen werden. Bitte versuchen Sie es später erneut.',
|
||||
senden: 'Die Buchung konnte nicht abgeschlossen werden. Bitte versuchen Sie es erneut.',
|
||||
belegt: 'Der Zeitraum ist leider inzwischen belegt. Bitte fragen Sie einen anderen Zeitraum an.',
|
||||
knopf: 'Zahlungspflichtig buchen',
|
||||
onlineAus: 'Online-Zahlung ist gerade nicht möglich – bitte wählen Sie „Vor Ort bezahlen“.',
|
||||
nichtMoeglich: 'Die Buchung ist gerade nicht möglich. Bitte wenden Sie sich direkt an den Anbieter.',
|
||||
standGeaendert: 'Der Stand Ihrer Buchung hat sich geändert.',
|
||||
zahlungStart: 'Die Zahlung konnte nicht gestartet werden. Bitte versuchen Sie es erneut.',
|
||||
}
|
||||
|
||||
function h(tag, attrs, kinder) {
|
||||
@@ -69,9 +73,13 @@
|
||||
})
|
||||
}
|
||||
|
||||
function httpsUrl(u) { return typeof u === 'string' && /^https:\/\//i.test(u) ? u : '' }
|
||||
var meldungNachLaden = ''
|
||||
function zeige(karte, hinweis) {
|
||||
app.textContent = ''
|
||||
if (hinweis) app.appendChild(p(hinweis, 'uk-hinweis'))
|
||||
var text = [hinweis, meldungNachLaden].filter(Boolean).join(' ')
|
||||
meldungNachLaden = ''
|
||||
if (text) app.appendChild(h('p', { text: text, class: 'uk-hinweis', role: 'status' }))
|
||||
app.appendChild(karte)
|
||||
}
|
||||
function nurText(titel, text) {
|
||||
@@ -140,7 +148,7 @@
|
||||
var input = h('input', { type: 'text', name: name, autocomplete: (extra && extra.ac) || 'off', maxlength: 120 })
|
||||
input.value = wert || ''
|
||||
felder[name] = input
|
||||
var fehler = h('span', { class: 'uk-feldfehler', 'data-fehler': name, hidden: true })
|
||||
var fehler = h('span', { class: 'uk-feldfehler', 'data-fehler': name, id: 'uk-fehler-' + name, hidden: true })
|
||||
return { wurzel: h('label', { class: 'uk-feld' }, [h('span', { class: 'uk-bez', text: bez }), input, fehler]), fehler: fehler }
|
||||
}
|
||||
var fName = feld('name', 'Name', ra.name || g.name, { ac: 'name' })
|
||||
@@ -165,8 +173,7 @@
|
||||
fName.wurzel, fFirma.wurzel, fStrasse.wurzel,
|
||||
h('div', { class: 'uk-zeile2' }, [fPlz.wurzel, fOrt.wurzel]),
|
||||
fLand.wurzel,
|
||||
h('h2', { text: 'Zahlart' }),
|
||||
h('div', { 'data-tag': 'zahlart' }, radios),
|
||||
h('fieldset', { class: 'uk-zahlart-gruppe', 'data-tag': 'zahlart' }, [h('legend', { text: 'Zahlart' })].concat(radios)),
|
||||
pflichtangaben(d, gewaehlt),
|
||||
knopf,
|
||||
meldung,
|
||||
@@ -180,10 +187,20 @@
|
||||
function waehl() { var r = radios.map(function (l) { return l.querySelector('input') }).find(function (i) { return i.checked }); return r ? r.value : gewaehlt }
|
||||
var sendet = false
|
||||
function fehlerAnzeigen(felderFehler, text) {
|
||||
Object.keys(alle).forEach(function (k) { alle[k].fehler.hidden = true; alle[k].fehler.textContent = '' })
|
||||
Object.keys(felderFehler || {}).forEach(function (k) { if (alle[k]) { alle[k].fehler.textContent = String(felderFehler[k]); alle[k].fehler.hidden = false } })
|
||||
Object.keys(alle).forEach(function (k) { markiere(k, '') })
|
||||
var erstes = null
|
||||
Object.keys(alle).forEach(function (k) {
|
||||
if (felderFehler && Object.prototype.hasOwnProperty.call(felderFehler, k)) { markiere(k, String(felderFehler[k])); if (!erstes) erstes = felder[k] }
|
||||
})
|
||||
meldung.textContent = text || ''
|
||||
meldung.hidden = !text
|
||||
if (erstes && erstes.focus) erstes.focus()
|
||||
}
|
||||
function markiere(k, text) {
|
||||
alle[k].fehler.textContent = text
|
||||
alle[k].fehler.hidden = !text
|
||||
if (text) { felder[k].setAttribute('aria-invalid', 'true'); felder[k].setAttribute('aria-describedby', 'uk-fehler-' + k) }
|
||||
else { felder[k].removeAttribute('aria-invalid'); felder[k].removeAttribute('aria-describedby') }
|
||||
}
|
||||
form.addEventListener('submit', function (ev) {
|
||||
ev.preventDefault()
|
||||
@@ -204,14 +221,24 @@
|
||||
var zahlart = waehl()
|
||||
api('', 'POST', { rechnungsadresse: val, zahlart: zahlart }).then(function (r) {
|
||||
if (r.ok && r.body.status === 'gebucht') {
|
||||
if (zahlart === 'online' && r.body.zahlungUrl) { window.location.assign(r.body.zahlungUrl); return }
|
||||
if (zahlart === 'online' && httpsUrl(r.body.zahlungUrl)) { window.location.assign(r.body.zahlungUrl); return }
|
||||
bestaetigt(Object.assign({}, d, { status: 'gebucht', zahlart: zahlart, bezahlt: false, rechnungNummer: r.body.rechnungNummer }))
|
||||
return
|
||||
}
|
||||
if (r.status === 404) return nurText('Buchung', TXT.ungueltig)
|
||||
if (r.status === 410 || r.body.fehler === 'frist_abgelaufen' || r.body.fehler === 'abgelaufen') return nurText('Buchung', TXT.abgelaufen)
|
||||
if (r.body.fehler === 'zeitraum_belegt') return nurText('Buchung', TXT.belegt)
|
||||
if (r.status === 409 || r.ok) { laden(); return }
|
||||
var code = r.body.fehler
|
||||
if (r.status === 409 && (code === 'online_aus' || code === 'einstellungen_unvollstaendig' || code === 'zustimmung_fehlt')) {
|
||||
sendet = false
|
||||
knopf.removeAttribute('disabled')
|
||||
if (code === 'online_aus') {
|
||||
var vor = radios.map(function (l) { return l.querySelector('input') }).find(function (i) { return i.value === 'vorort' })
|
||||
if (vor) vor.checked = true
|
||||
}
|
||||
return fehlerAnzeigen({}, code === 'online_aus' ? TXT.onlineAus : TXT.nichtMoeglich)
|
||||
}
|
||||
if (r.status === 409 || r.ok) { meldungNachLaden = TXT.standGeaendert; laden(); return }
|
||||
sendet = false
|
||||
knopf.removeAttribute('disabled')
|
||||
fehlerAnzeigen(r.body.felder, r.status === 400 && r.body.felder ? 'Bitte prüfen Sie Ihre Angaben.' : TXT.senden)
|
||||
@@ -224,7 +251,7 @@
|
||||
// Fehler verschwinden, sobald der Gast das Feld aendert; die allgemeine Meldung, wenn kein Feldfehler mehr steht
|
||||
Object.keys(alle).forEach(function (k) {
|
||||
felder[k].addEventListener('input', function () {
|
||||
alle[k].fehler.hidden = true; alle[k].fehler.textContent = ''
|
||||
markiere(k, '')
|
||||
if (!Object.keys(alle).some(function (n) { return !alle[n].fehler.hidden })) { meldung.textContent = ''; meldung.hidden = true }
|
||||
})
|
||||
})
|
||||
@@ -245,9 +272,11 @@
|
||||
knopf.addEventListener('click', function () {
|
||||
knopf.setAttribute('disabled', '')
|
||||
api('/zahlung', 'POST', {}).then(function (r) {
|
||||
if (r.ok && r.body.url) { window.location.assign(r.body.url); return }
|
||||
if (r.ok && httpsUrl(r.body.url)) { window.location.assign(r.body.url); return }
|
||||
if (r.status === 409 && r.body.fehler === 'status_ungueltig') { meldungNachLaden = TXT.standGeaendert; laden(); return }
|
||||
knopf.removeAttribute('disabled')
|
||||
meldung.textContent = 'Die Zahlung konnte nicht gestartet werden. Bitte versuchen Sie es erneut.'; meldung.hidden = false
|
||||
meldung.textContent = r.status === 409 && r.body.fehler === 'online_aus' ? TXT.onlineAus : r.status === 409 && (r.body.fehler === 'einstellungen_unvollstaendig' || r.body.fehler === 'zustimmung_fehlt') ? TXT.nichtMoeglich : TXT.zahlungStart
|
||||
meldung.hidden = false
|
||||
}, function () {
|
||||
knopf.removeAttribute('disabled')
|
||||
meldung.textContent = 'Die Zahlung konnte nicht gestartet werden. Bitte versuchen Sie es erneut.'; meldung.hidden = false
|
||||
|
||||
Reference in new issue
Block a user