Kundenansicht neu P1: Widerrufsstreifen mit GET /api/fristen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e144a9611d
commit
3241aedc3c
3 files changed
+114
No files matched your search
@@ -0,0 +1,52 @@
|
||||
/* Kundenansicht neu: Widerrufsstreifen. Läuft eine Widerrufsfrist, steht über der Leiste ein schmaler Streifen
|
||||
„Widerrufsfrist bis TT.MM. · Widerrufen“. Er ist nicht wegtippbar. Die Daten kommen von GET /api/fristen; jeder Fehler
|
||||
(404 auf einem Server ohne P5, 500, Netz weg) und anzeigen !== true ergeben keinen Streifen. Daten in Europe/Berlin. */
|
||||
|
||||
import { h, leeren } from './dom.js'
|
||||
|
||||
/** Fristen vom Server holen; bei Fehlern jeder Art oder anzeigen !== true null. */
|
||||
export async function ladeFristen(api) {
|
||||
try {
|
||||
const daten = await api('/api/fristen')
|
||||
return daten?.anzeigen === true ? daten : null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const datumBerlin = new Intl.DateTimeFormat('de-DE', { timeZone: 'Europe/Berlin', day: '2-digit', month: '2-digit' })
|
||||
|
||||
/** 'Widerrufsfrist bis TT.MM.' in der Zeit von Berlin; ohne gültiges Datum 'Widerrufsfrist läuft'. */
|
||||
export function streifenText(iso) {
|
||||
const zeit = new Date(iso)
|
||||
if (!iso || Number.isNaN(zeit.getTime())) return 'Widerrufsfrist läuft'
|
||||
const teile = Object.fromEntries(datumBerlin.formatToParts(zeit).map((t) => [t.type, t.value]))
|
||||
return `Widerrufsfrist bis ${teile.day}.${teile.month}.`
|
||||
}
|
||||
|
||||
/** Frühestes Ende als ISO-Text: fruehestesEnde, sonst das kleinste bis, sonst ''. */
|
||||
export function fruehesteFrist(daten) {
|
||||
if (daten?.fruehestesEnde) return daten.fruehestesEnde
|
||||
const zeiten = (daten?.fristen ?? []).map((f) => f?.bis).filter((b) => b && !Number.isNaN(Date.parse(b)))
|
||||
return zeiten.sort((a, b) => Date.parse(a) - Date.parse(b))[0] ?? ''
|
||||
}
|
||||
|
||||
/** Streifen in `wurzel` füllen: setze(daten) zeigt ihn, setze(null) versteckt ihn. Am Körper steht `kn-hat-streifen`, solange er sichtbar ist. */
|
||||
export function baueStreifen(wurzel, { koerper = document.body } = {}) {
|
||||
wurzel.classList.add('kn-streifen')
|
||||
wurzel.setAttribute('role', 'region')
|
||||
wurzel.setAttribute('aria-label', 'Widerrufsfrist')
|
||||
return {
|
||||
setze(daten) {
|
||||
leeren(wurzel)
|
||||
if (!daten) {
|
||||
wurzel.hidden = true
|
||||
koerper.classList.remove('kn-hat-streifen')
|
||||
return
|
||||
}
|
||||
wurzel.append(streifenText(fruehesteFrist(daten)), ' · ', h('a', { class: 'kn-streifen-link', href: '/widerrufen.html' }, 'Widerrufen'))
|
||||
wurzel.hidden = false
|
||||
koerper.classList.add('kn-hat-streifen')
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -30,3 +30,16 @@
|
||||
.kn-haupt[inert] { display: block; } /* am Handy bleibt die Hauptseite unter dem Blatt stehen */
|
||||
.kn-brot { display: none; }
|
||||
}
|
||||
|
||||
/* ---------- Streifen (Widerrufsfrist) ---------- */
|
||||
|
||||
.kn-streifen { display: flex; align-items: center; min-height: 44px; padding: 0 48px; background: var(--kn-orange-bg); color: var(--kn-orange-fg); font-size: 14px; line-height: 20px; font-weight: 600; }
|
||||
.kn-streifen-link { margin-left: 6px; color: inherit; text-decoration: underline; text-underline-offset: 3px; }
|
||||
.kn-tastatur .kn-streifen { display: none; }
|
||||
|
||||
@media (max-width: 880px), (pointer: coarse) and (max-height: 500px) {
|
||||
.kn-streifen { position: fixed; left: 0; right: 0; bottom: calc(var(--kn-zeile-h) + env(safe-area-inset-bottom)); z-index: 30; padding: 0 16px; }
|
||||
.kn-streifen-link { min-height: 44px; display: inline-flex; align-items: center; }
|
||||
.kn-hat-streifen { --kn-unten: calc(var(--kn-zeile-h) + env(safe-area-inset-bottom) + 44px); }
|
||||
.kn-hat-streifen .kn-haupt { padding-bottom: calc(var(--kn-zeile-h) + env(safe-area-inset-bottom) + 28px + 44px); }
|
||||
}
|
||||
Reference in new issue
Block a user