Buchungskalender: Rechnungen, Einstellungen und Funktionen-Kachel
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
10fe9a2ae0
commit
efeb99e214
8 files changed
+696
-11
No files matched your search
+52
-1
@@ -260,6 +260,51 @@ function shopTile(projects, features) {
|
||||
</article>`
|
||||
}
|
||||
|
||||
/* Buchungskalender (Schluessel unterkunft): Kachel nur, wenn der Server die Funktion freigibt (unterkunft.verfuegbar der Antwort, Schalter
|
||||
UNTERKUNFT_ENABLED); sonst gar keine Kachel. Die Ansicht #buchungen (buchungen.js) zeigt Anfrage und Stand; die Kachel kennt nur den Zustand
|
||||
des Funktionsdokuments (projects[].features.unterkunft: off | ordered | setup | active | disabled), Preis aus features.unterkunft.priceLabel,
|
||||
Rueckfall 199 €. */
|
||||
const UNTERKUNFT_PREIS = '199 €'
|
||||
const UNTERKUNFT_TEXT = 'Belegungskalender auf deiner Website, Anfragen freigeben, Rechnung und Online-Zahlung'
|
||||
const unterkunftOf = (project) => project.features?.unterkunft || { state: 'off' }
|
||||
|
||||
function pickUnterkunftProject(projects) {
|
||||
return projects.find((p) => unterkunftOf(p).state === 'active')
|
||||
|| projects.find((p) => isSetup(unterkunftOf(p).state))
|
||||
|| projects.find((p) => unterkunftOf(p).state === 'disabled')
|
||||
|| projects[0]
|
||||
}
|
||||
|
||||
function unterkunftTile(projects, features) {
|
||||
const preis = textOr(features?.unterkunft?.priceLabel, UNTERKUNFT_PREIS)
|
||||
const active = projects.filter((p) => unterkunftOf(p).state === 'active').length
|
||||
const target = pickUnterkunftProject(projects)
|
||||
const state = target ? unterkunftOf(target).state : 'off'
|
||||
const knopf = (text) => `<button type="button" class="kb-btn-primary fn-tile-cta" data-view="buchungen" data-project="${esc(target.projectId)}">${text}</button>`
|
||||
const ZUSTAENDE = {
|
||||
off: [['Aus', 'off'], 'Buchungskalender anfragen'],
|
||||
ordered: [['Zahlung offen', 'setup'], 'Zahlung offen'],
|
||||
setup: [['In Einrichtung', 'setup'], 'In Einrichtung'],
|
||||
active: [['Aktiv', 'on'], 'Buchungskalender öffnen'],
|
||||
disabled: [['Abgeschaltet', 'off'], 'Buchungskalender ansehen'],
|
||||
}
|
||||
const [pill, knopfText] = ZUSTAENDE[state] || ZUSTAENDE.off
|
||||
const action = target ? knopf(knopfText) : ''
|
||||
let extra = ''
|
||||
if (!target) extra = '<p class="fn-count">Sobald deine Website angelegt ist, kannst du den Buchungskalender anfragen.</p>'
|
||||
else if (state === 'disabled') extra = '<p>Der Buchungskalender ist für diese Website abgeschaltet. Deine Buchungen kannst du noch ansehen.</p>'
|
||||
const count = projects.length > 1 && active ? `<p class="fn-count">aktiv für ${active} von ${projects.length} Websites</p>` : ''
|
||||
return `
|
||||
<article class="fn-tile" data-fn-tile="unterkunft">
|
||||
<div class="fn-tile-head">${svg('calendar')}<span class="fn-pill fn-pill-${pill[1]}">${pill[0]}</span></div>
|
||||
<h3>Buchungskalender</h3>
|
||||
<p>${UNTERKUNFT_TEXT}. ${esc(preis)} einmalig.</p>
|
||||
${extra}
|
||||
${count}
|
||||
${action}
|
||||
</article>`
|
||||
}
|
||||
|
||||
/* Oeffnungszeiten live: Kachel nur, wenn der Schalter es erlaubt (zeiten.verfuegbar); sonst gibt es sie gar nicht (auch kein "Kommt bald").
|
||||
Wie bei den anderen Funktionen steht sie inline, die Ansicht #zeiten (zeiten.js) laedt app.js. Alles, was sie zeigt, kommt mit der Liste
|
||||
(GET /api/funktionen): zeiten (Angebot) mit inklusive (true: im laufenden, aktiven Wartungs-Abo enthalten, einschaltbar | false: sonst, dann
|
||||
@@ -386,12 +431,13 @@ const soonTile = (icon, title, text) => `
|
||||
|
||||
export async function initFunktionen(root) {
|
||||
if (!root) return
|
||||
const { projects = [], termine, features, shop, zeiten } = await request('/api/funktionen')
|
||||
const { projects = [], termine, features, shop, zeiten, unterkunft } = await request('/api/funktionen')
|
||||
root.innerHTML = `
|
||||
<div class="fn-tiles">
|
||||
${newsTile(projects, newsOffer(features).price)}
|
||||
${termine?.verfuegbar ? termineTile(projects, termine) : soonTile('calendar', 'Terminplaner', TERMINE_TEXT)}
|
||||
${shop?.verfuegbar ? shopTile(projects, features) : ''}
|
||||
${unterkunft?.verfuegbar === true ? unterkunftTile(projects, features) : ''}
|
||||
${zeiten?.verfuegbar === true ? zeitenTile(projects, zeiten) : ''}
|
||||
${analyseTile(projects)}
|
||||
</div>`
|
||||
@@ -407,6 +453,11 @@ export async function initFunktionen(root) {
|
||||
const body = document.getElementById('webshop-body')
|
||||
if (body) body.dataset.wunschProjekt = ev.currentTarget.dataset.project
|
||||
})
|
||||
// Die Buchungskalender-Ansicht liest das gewaehlte Projekt aus ihrem Behaelter (buchungen.js, initBuchungen)
|
||||
root.querySelector('[data-fn-tile="unterkunft"] .fn-tile-cta[data-project]')?.addEventListener('click', (ev) => {
|
||||
const body = document.getElementById('buchungen-body')
|
||||
if (body) body.dataset.wunschProjekt = ev.currentTarget.dataset.project
|
||||
})
|
||||
// Die Zeiten-Ansicht liest Projekt und Weg (Behalten) aus ihrem Behaelter (zeiten.js, initZeiten); der Klick steigt danach zum Navigationshandler auf
|
||||
root.querySelector('[data-fn-tile="zeiten"]')?.addEventListener('click', (ev) => {
|
||||
const knopf = ev.target?.closest?.('button[data-view="zeiten"]')
|
||||
|
||||
Reference in new issue
Block a user