/* Abschnitt „Aufträge“ im Reiter Rechnungen des Kundenportals (geladen von app.js, loadCustomerOrders; request ist api aus app.js). Kundentext kommt nur über textContent in die Seite. Alle Texte stehen in auftrag-ansicht.js; das Portal spricht in der Du-Form. */ import { ANREDE_DU, agbPfad, darfBestaetigen, kartenMeta, sortiereAuftraege, statusAnzeige, texte, } from './auftrag-ansicht.js' import { h, renderBestaetigtBlock, renderBestaetigung, renderDokumente, renderZusammenfassung, } from './auftrag-dom.js' export async function initAuftraege({ section, body, invoicesTitle, request, viewAs = false } = {}) { if (!section || !body || typeof request !== 'function') return { sichtbar: false } const t = texte(ANREDE_DU) let eintraege = [] /** Bestätigen darf, wer der Server dafür freigibt; in der Kundenansicht zeigt die Oberfläche die offene AB mit gesperrtem Formular. */ const wirksam = (e) => darfBestaetigen(e) && (viewAs || e.kannBestaetigen === true) async function ladeListe() { const daten = await request('/api/auftraege') if (daten?.aktiv !== true || !Array.isArray(daten.auftraege)) return [] return daten.auftraege.filter((e) => e && typeof e.id === 'string' && e.id !== '') } function karte(auftrag, offeneId) { const kann = wirksam(auftrag) const status = statusAnzeige({ ...auftrag, kannBestaetigen: kann }) const pfad = `/api/auftraege/${encodeURIComponent(auftrag.id)}` async function senden(koerper) { try { const antwort = await request(`${pfad}/bestaetigen`, { method: 'POST', body: JSON.stringify(koerper) }) return antwort?.auftrag ? { ok: true, auftrag: antwort.auftrag } : { ok: false, status: 0, body: {} } } catch (err) { return { ok: false, status: Number(err?.status) || 0, body: { error: String(err?.message ?? '') } } } } function nachErfolg(neu) { eintraege = eintraege.map((alt) => (alt.id === auftrag.id ? { ...alt, ...neu, id: alt.id, kannBestaetigen: false } : alt)) zeichne(auftrag.id) body.querySelector(`[data-auftrag="${CSS.escape(auftrag.id)}"] [data-bestaetigt]`)?.focus() } async function nachEnde() { try { eintraege = await ladeListe() zeichne('') } catch { /* die Anzeige bleibt stehen */ } } return h('article', { class: 'ab-karte', 'data-auftrag': auftrag.id, 'data-status': auftrag.status || '' }, h('div', { class: 'ab-karte-kopf' }, h('div', null, h('p', { class: 'ab-karte-nummer' }, h('strong', null, auftrag.nummer || '')), auftrag.titel ? h('p', { class: 'ab-karte-titel' }, auftrag.titel) : null, h('p', { class: 'ab-karte-meta' }, kartenMeta(auftrag))), h('span', { class: `ab-pille ab-pille-${status.ton}` }, status.text)), h('div', { class: 'ab-karte-aktionen' }, h('a', { class: 'ab-link', 'data-link': 'pdf', href: `${pfad}/pdf`, target: '_blank', rel: 'noopener noreferrer' }, t.kartePdf)), h('details', { class: 'ab-details', open: kann || auftrag.id === offeneId }, h('summary', null, kann ? t.karteDetailsBestaetigen : t.karteDetails), renderZusammenfassung(auftrag, { ebene: 4 }), renderDokumente({ agbHref: agbPfad(auftrag.agbUrl) }), renderBestaetigtBlock(auftrag, { anrede: ANREDE_DU }), kann ? renderBestaetigung(auftrag, { senden, nachErfolg, nachEnde, gesperrt: viewAs ? t.ansichtsmodus : '', anrede: ANREDE_DU }) : null)) } function zeichne(offeneId) { body.replaceChildren(...sortiereAuftraege(eintraege.map((e) => ({ ...e, kannBestaetigen: wirksam(e) }))).map((e) => karte(eintraege.find((x) => x.id === e.id), offeneId))) } try { eintraege = await ladeListe() } catch { return { sichtbar: false } } if (!eintraege.length) return { sichtbar: false } zeichne('') section.classList.remove('hidden') invoicesTitle?.classList.remove('hidden') return { sichtbar: true } }