92 lines
4.4 KiB
JavaScript
92 lines
4.4 KiB
JavaScript
/* Kundenansicht neu (P7): gemeinsame Bausteine der vier Bestellseiten (Abo bestellen, Wechsel, Zusatzspeicher, Gutschrift-Antrag).
|
|
Die Sätze kommen vom Server (GET /api/abo → bestelltexte); hier werden sie nur gezeichnet. Link-Texte stehen in der Vorlage in
|
|
eckigen Klammern, ihre Adressen daneben in urls. Jede Adresse läuft durch sicherLink; Kundentext wird nie als HTML gelesen.
|
|
Keine h1: den Titel meldet die Ansicht mit meldeTitel. */
|
|
|
|
import { h } from './dom.js'
|
|
import { K } from './ansicht-hilfen.js'
|
|
|
|
/** 'unternehmen' | 'privat': nur exakt 'unternehmen' (me.customer.kundenartWirksam, sonst daten.kundenart) ist Betrieb; alles andere privat (E4). */
|
|
export function kundenartVon(me, daten = null) {
|
|
return me?.customer?.kundenartWirksam === 'unternehmen' || daten?.kundenart === 'unternehmen' ? 'unternehmen' : 'privat'
|
|
}
|
|
|
|
/** Adresse nur, wenn sie ein Pfad auf derselben Herkunft ('/…', nicht '//…'), ein Anker ('#name…') oder http(s) ohne Zugangsdaten ist; sonst ''. */
|
|
export function sicherLink(url) {
|
|
if (typeof url !== 'string' || url === '') return ''
|
|
if (/[\s\u0000-\u001f\u007f\\]/.test(url)) return ''
|
|
if (/^\/(?![/\\])/.test(url)) return url
|
|
if (/^#[a-z][\w-]*(\?[\w=&.%-]*)?$/i.test(url)) return url
|
|
if (/^https?:\/\/[^/?#]+/i.test(url)) {
|
|
try {
|
|
const u = new URL(url)
|
|
return u.hostname !== '' && u.username === '' && u.password === '' ? url : ''
|
|
} catch {
|
|
return ''
|
|
}
|
|
}
|
|
return ''
|
|
}
|
|
|
|
/**
|
|
* 'Es gilt [A] und [B].' mit ['/a', '/b'] → Teile [{ text }, { text, href? }]. Die Markierungen bekommen der Reihe nach ihre Adresse;
|
|
* eine unsichere oder fehlende Adresse macht den Teil zu einem Teil ohne href. Eine offene Klammer bleibt Text.
|
|
*/
|
|
export function linkTeile(text, urls) {
|
|
const basis = typeof text === 'string' ? text : ''
|
|
const adressen = Array.isArray(urls) ? urls : []
|
|
const teile = []
|
|
let ab = 0
|
|
let nr = 0
|
|
const muster = /\[([^\]]*)\]/g
|
|
for (let m = muster.exec(basis); m; m = muster.exec(basis)) {
|
|
if (m.index > ab) teile.push({ text: basis.slice(ab, m.index) })
|
|
const href = sicherLink(adressen[nr])
|
|
nr += 1
|
|
teile.push(href ? { text: m[1], href } : { text: m[1] })
|
|
ab = m.index + m[0].length
|
|
}
|
|
if (ab < basis.length) teile.push({ text: basis.slice(ab) })
|
|
return teile
|
|
}
|
|
|
|
const ausserhalb = (href) => !href.startsWith('#')
|
|
|
|
/** <p id> mit den Links der Vorlage; '/…' und http(s) öffnen in neuem Tab (target _blank, rel noopener), '#…' bleibt im Fenster. */
|
|
export function baueLinkzeile({ text, urls } = {}, { id } = {}) {
|
|
const kinder = linkTeile(text, urls).map((t) =>
|
|
t.href ? h('a', { href: t.href, ...(ausserhalb(t.href) ? { target: '_blank', rel: 'noopener' } : {}) }, t.text) : t.text)
|
|
return h('p', { id, class: 'kn-linkzeile' }, kinder)
|
|
}
|
|
|
|
/** <p id>: „Du bestellst als Betrieb“ | „Du bestellst privat“, ' · ', dann der Hinweis zur Korrektur mit seinem Link. */
|
|
export function baueKundenartZeile(kundenart, texte, { id } = {}) {
|
|
const lage = kundenart === 'unternehmen' ? texte?.unternehmen : texte?.privat
|
|
const korrektur = linkTeile(texte?.korrektur?.text, texte?.korrektur?.urls).map((t) =>
|
|
t.href ? h('a', { href: t.href, ...(ausserhalb(t.href) ? { target: '_blank', rel: 'noopener' } : {}) }, t.text) : t.text)
|
|
return h('p', { id, class: 'kn-kundenart-zeile' }, lage, ' · ', korrektur)
|
|
}
|
|
|
|
/** Block „Was du bestellst“: zeilen [{ id?, label, text }] als Beschriftungsliste. Der Text ist immer Text. */
|
|
export function baueBlock(zeilen, { id } = {}) {
|
|
return h('dl', { id, class: 'kn-block' }, (zeilen || []).map((z) => h('div', { class: 'kn-block-zeile' }, h('dt', null, z.label), h('dd', { id: z.id }, z.text))))
|
|
}
|
|
|
|
const nichtLeer = (x) => typeof x === 'string' && x !== ''
|
|
|
|
/**
|
|
* true, wenn die Antwort den Wortlaut trägt: status, knopf und die Sätze der Seite (art 'abo' | 'wechsel' | 'speicher' | 'gutschrift').
|
|
* Ohne ihn zeigt keine Seite einen Bestellknopf.
|
|
*/
|
|
export function hatWortlaut(daten, art = 'abo') {
|
|
const t = daten?.bestelltexte
|
|
if (!t || typeof t !== 'object' || !nichtLeer(t.status) || !nichtLeer(t.knopf)) return false
|
|
if (art === 'gutschrift') return nichtLeer(t.gutschrift?.satz?.text) && nichtLeer(t.gutschrift?.knopf)
|
|
if (!nichtLeer(t[art]?.linkzeile?.text)) return false
|
|
if (art === 'wechsel') return nichtLeer(t.wechsel.haken) && nichtLeer(t.wechsel.gesperrt)
|
|
if (art === 'abo') return nichtLeer(t.abo.haken)
|
|
return true
|
|
}
|
|
|
|
export { K }
|