/* Kundenansicht neu (P2): Reiter Stunden in Verträge. Stundenkonto des Wartungs-Abos mit Verlauf; ein Vorschuss für die Einrichtung (ab P6 in ledger.vorschussMinutes) wird nie als Mehraufwand gezeigt. */ import { h, leeren } from './dom.js' import { K, ersetze, fmtStd, fmtDatum, ladeAbo, ABO_NICHT_GELADEN } from './ansicht-hilfen.js' import { aboWarnungen } from './vertraege-abo.js' const laeufe = new WeakMap() // Reiter-Inhalt → Nummer des jüngsten Aufrufs const stat = (wert, beschriftung) => h('div', { class: 'kn-stat' }, h('strong', { class: 'kn-num' }, wert), h('span', null, beschriftung)) /** Zeile zum Vorschuss für die Einrichtung; bei 0 oder weniger leer. gekuendigt: der Rest verfällt. */ export function vorschussZeile(minuten, gekuendigt) { if (!(Number(minuten) > 0)) return '' return `Vorschuss für Einrichtung: ${fmtStd(minuten)}, ${gekuendigt ? 'verfällt, wird nicht berechnet' : 'wird mit den nächsten Monaten verrechnet'}` } function verlaufZeile(u) { const vorschuss = Number(u.vorschussMinutes) || 0 const mehr = Number(u.overageMinutes) || 0 const pille = vorschuss > 0 ? h('span', { class: K.pille.violett }, `Vorschuss ${fmtStd(vorschuss)}`) : mehr > 0 ? h('span', { class: K.pille.orange, title: 'Über das Kontingent hinaus' }, `+${fmtStd(mehr)} extra`) : null return h('tr', null, h('td', { 'data-label': 'Datum' }, fmtDatum(u.date)), h('td', { 'data-label': 'Vorgang' }, u.topic || u.details || 'Arbeitszeit', u.woid ? h('span', { class: 'kn-zeile-sub' }, ` #${u.woid}`) : null), h('td', { 'data-label': 'Zeit', class: 'kn-num' }, `−${fmtStd(u.minutes)}`, u.supportMinutes ? h('span', { class: 'kn-zeile-sub' }, ` inkl. ${fmtStd(u.supportMinutes)} Unterstützung`) : null, pille ? ' ' : null, pille)) } function gutschriftZeile(c) { return h('tr', null, h('td', { 'data-label': 'Datum' }, fmtDatum(c.grantedAt)), h('td', { 'data-label': 'Vorgang' }, 'Monatskontingent'), h('td', { 'data-label': 'Zeit', class: 'kn-num' }, `+${fmtStd(c.minutes)}`, h('span', { class: 'kn-zeile-sub' }, ` ${c.expired ? 'abgelaufen' : `nutzbar bis ${fmtDatum(c.expiresAt)}`}`))) } /** Reiter-Inhalt Stunden. daten (GET /api/abo) ist optional; ohne sie lädt die Funktion selbst. */ export async function zeigeStunden(wurzel, { route, me, nav, daten } = {}) { const nr = (laeufe.get(wurzel) ?? 0) + 1 laeufe.set(wurzel, nr) const aktuell = () => laeufe.get(wurzel) === nr leeren(wurzel).append(h('p', { class: K.leer }, 'Wird geladen …')) const abo = daten ?? await ladeAbo() if (!aktuell()) return if (!abo) { leeren(wurzel).append(h('p', { class: K.fehler }, ABO_NICHT_GELADEN)); return } const sub = abo.subscription const l = abo.ledger if (!sub?.active || sub.productKey !== 'wartung' || !l) { leeren(wurzel).append(h('p', { class: K.leer }, 'Ein Stundenkonto gibt es im Wartungs-Abo.')) return } const gekuendigt = Boolean(sub.cancelAtPeriodEnd || sub.cancelAt) const vorschuss = vorschussZeile(l.vorschussMinutes, gekuendigt) const zeilen = [...(l.usage || []).map(verlaufZeile), ...(l.credits || []).slice().reverse().map(gutschriftZeile)] ersetze(wurzel, ...aboWarnungen(sub), h('div', { class: 'kn-statistik' }, stat(fmtStd(l.balanceMinutes), 'verfügbare Zeit'), stat(fmtStd(l.usedMinutes), 'bisher genutzt'), l.nextExpiry ? stat(fmtStd(l.nextExpiry.minutes), `verfallen am ${fmtDatum(l.nextExpiry.at)}`) : null), vorschuss ? h('p', { class: 'kn-hinweis kn-vorschuss' }, vorschuss) : null, h('p', { class: 'kn-hinweis' }, '1 Stunde pro bezahltem Monat. Angerechnet wird in 15-Minuten-Schritten, die ältesten Stunden zuerst.'), h('p', { class: 'kn-links' }, h('a', { href: sub.termsUrl || '/abo-bedingungen.html', target: '_blank', rel: 'noopener noreferrer' }, 'Leistungen & Bedingungen')), h('section', { class: 'kn-sektion' }, h('h2', { class: K.abschnitt }, 'Verlauf'), zeilen.length ? h('div', { class: 'kn-tabelle' }, h('table', null, h('thead', null, h('tr', null, h('th', null, 'Datum'), h('th', null, 'Vorgang'), h('th', null, 'Zeit'))), h('tbody', null, zeilen))) : h('p', { class: 'kn-hinweis' }, 'Noch keine Buchungen.'))) }