Kundenansicht neu E-Fix F1: Kerninfo und Knopf der Bestellseiten passen in den nutzbaren Bereich (390x844, 375x667)

Die Messung im Werkzeug nahm innerHeight; nutzbar ist am Handy nur der Bereich zwischen Kopf und fester Leiste (735 px bei 844, 558 px bei 667).
Gemessen vor der Korrektur (Blockanfang bis Knopfunterkante, 375x667): Abo bestellen privat 799 px, Wechsel privat 888 px, Zusatzspeicher 567 px.

- Block knapp: Leistung als eine Zeile mit Link "Leistungen ansehen" auf die Leistungsbeschreibung, Preis, Fällig, Beginn, Laufzeit und Zahlung in je ein bis zwei Zeilen.
- Die ausführlichen Sätze stehen unter dem Knopf und der Kundenart-Zeile (baueEinzelheiten), ohne Klappe.
- Handy: Beschriftung läuft in der Zeile mit, kleinere Überschrift, knappere Abstände.
- Die Wortlaute des Blocks sind gekürzt und gehören in die Rechtsrunde.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-16 21:25:48 +00:00
1 parent 779320c080
commit d4050f870a
8 files changed
+148 -41

No files matched your search

+20 -11
View File
@@ -1,6 +1,8 @@
/* Kundenansicht neu (P7): Bestellseite je Abo (#bestellen-hosting, #bestellen-wartung) im schlanken Muster der Spec 5.6, Fassung 6.
Reihenfolge ohne Klappe und ohne Scrollbereich: Block „Was du bestellst“, eine Linkzeile, bei Privatkunden ein Häkchen, der Knopf
„Zahlungspflichtig bestellen“ (§ 312j BGB: Kerninfo und Knopf auf demselben Bildschirm), darunter die Kundenart-Zeile.
Der Block ist knapp gehalten (Leistung als eine Zeile mit Link auf die Leistungsbeschreibung), damit er mit dem Knopf in den nutzbaren Bereich
zwischen Kopf und Leiste passt (375 x 667); die ausführlichen Sätze stehen unter dem Knopf (baueEinzelheiten), ohne Klappe.
Die Sätze (Linkzeile, Häkchen, Kundenart-Zeile) kommen vom Server (GET /api/abo → bestelltexte). Der Server entscheidet die Kundenart selbst:
der Client sendet nie kundenart oder startChoice, bei Privatkunden nur earlyStart (das Häkchen) und den gezeigten Leistungsbeginn.
Der Titel kommt von der Hülle (meldeTitel); die Seite hat keine eigene h1. */
@@ -8,7 +10,7 @@
import { api } from './api.js'
import { h, leeren } from './dom.js'
import { K, ladeAbo, sichereAdresse, meldeTitel, fmtEuro, fmtDatum, ABO_NICHT_GELADEN } from './ansicht-hilfen.js'
import { baueBlock, baueKundenartZeile, baueLinkzeile, hatWortlaut, kundenartVon } from './bestell-bausteine.js'
import { baueBlock, baueEinzelheiten, baueKundenartZeile, baueLinkzeile, hatWortlaut, kundenartVon, leistungLink } from './bestell-bausteine.js'
const laeufe = new WeakMap() // Wurzel → Nummer des jüngsten Aufrufs
const TEXT_SPERRE = 'Im Ansichtsmodus nicht möglich.'
@@ -35,10 +37,10 @@ function preise(product, offer) {
const mitZahlen = Boolean(offer) && Number.isFinite(offerMonthly) && offer.monthlyPriceCents != null && offerMonths > 0
const preis = fmtEuro(product.amountCents / 100)
const preisZeile = !offer
? `${preis} pro Monat (Gesamtpreis, ${UST}), keine weiteren Kosten`
? `${preis} pro Monat (Gesamtpreis, ${UST})`
: mitZahlen
? `${fmtEuro(offerMonthly / 100)} pro Monat für die ersten ${offerMonths} Monate, danach ${fmtEuro(offerRegular / 100)} pro Monat (individuelles Angebot: ${offer.text}; Gesamtpreis, ${UST}), keine weiteren Kosten`
: `${preis} pro Monat (individuelles Angebot: ${offer.text}; Gesamtpreis, ${UST}), keine weiteren Kosten`
? `${fmtEuro(offerMonthly / 100)} pro Monat für die ersten ${offerMonths} Monate, danach ${fmtEuro(offerRegular / 100)} pro Monat (individuelles Angebot: ${offer.text}; Gesamtpreis, ${UST})`
: `${preis} pro Monat (individuelles Angebot: ${offer.text}; Gesamtpreis, ${UST})`
return { preisZeile, erste: fmtEuro((mitZahlen ? offerMonthly : product.amountCents) / 100) }
}
@@ -46,13 +48,13 @@ function preise(product, offer) {
function faelligBeginn({ lage, erste, frist }) {
if (lage === 'frist') {
return {
faellig: `Erste Abbuchung am ${frist || 'Ende der 14-tägigen Widerrufsfrist'}: ${erste} (${UST}); heute wird nichts abgebucht`,
beginn: `nach Ablauf der 14-tägigen Widerrufsfrist${frist ? ` (am ${frist})` : ''}; bis dahin keine Leistung und keine Abbuchung`,
faellig: `erst am ${frist || 'Ende der Widerrufsfrist'}: ${erste}`,
beginn: `nach Ablauf der 14-tägigen Widerrufsfrist${frist ? ` (am ${frist})` : ''}`,
}
}
return {
faellig: `Heute fällig: ${erste} (${UST})`,
beginn: lage === 'wunsch' ? 'sofort, auf deinen ausdrücklichen Wunsch vor Ablauf der Widerrufsfrist' : 'sofort',
faellig: `heute ${erste}`,
beginn: lage === 'wunsch' ? 'sofort, auf deinen ausdrücklichen Wunsch' : 'sofort',
}
}
@@ -82,13 +84,19 @@ function bestellung(daten, productKey, { viewAs, kundenart }) {
const start = faelligBeginn({ lage: privat ? 'frist' : 'sofort', erste, frist })
const block = baueBlock([
{ label: 'Leistung', text: `${product.name}: ${(product.features || []).map(([t]) => t).join(', ')}` },
{ label: 'Leistung', text: labelVon(daten, productKey), link: { text: 'Leistungen ansehen', href: leistungLink(T.abo.linkzeile, productKey) } },
{ label: 'Preis', text: preisZeile },
{ id: 'abo-due-summary', label: 'Fällig', text: start.faellig },
{ id: 'abo-start-summary', label: 'Beginn', text: start.beginn },
{ label: 'Laufzeit', text: `Mindestlaufzeit ${product.minTermMonths} Monate, kündbar bis 1 Monat vor Ende; danach monatlich` },
{ label: 'Zahlung', text: 'Karte oder SEPA über Stripe' },
], { id: 'abo-block' })
// Die ausführlichen Sätze stehen unter dem Knopf
const einzelheiten = baueEinzelheiten([
{ label: 'Laufzeit', text: `Mindestlaufzeit ${product.minTermMonths} Monate ab Leistungsbeginn, kündbar zum Ende der Mindestlaufzeit bis einen Monat vorher; danach jederzeit zum Ende des Abrechnungsmonats kündbar` },
{ label: 'Zahlung', text: 'Kreditkarte oder SEPA-Lastschrift über Stripe; die Zahlungsart hinterlegst du im nächsten Schritt, bis zum Abschluss dort kannst du abbrechen' },
], { id: 'abo-block' })
{ label: 'Kosten', text: 'keine weiteren Kosten' },
], { id: 'abo-einzelheiten' })
const haken = privat ? h('input', { type: 'checkbox', id: 'abo-beginn', disabled: viewAs }) : null
const fehler = h('p', { class: K.fehler, id: 'abo-error', hidden: true })
@@ -103,7 +111,8 @@ function bestellung(daten, productKey, { viewAs, kundenart }) {
haken ? h('label', { class: K.check }, haken, h('span', { id: 'abo-beginn-text' }, T.abo.haken)) : null,
fehler,
h('div', { class: 'kn-aktionen' }, kaufen, viewAs ? h('span', { class: K.meldung }, TEXT_SPERRE) : null),
baueKundenartZeile(kundenart, T.kundenart, { id: 'abo-kundenart' }))
baueKundenartZeile(kundenart, T.kundenart, { id: 'abo-kundenart' }),
einzelheiten)
// Das Häkchen schaltet die Zeilen „Fällig“ und „Beginn“ um
haken?.addEventListener('change', () => {