// Vanilla JS Migration of anmeld.js (jQuery removed) async function ladeAbsagegruende() { const res = await fetch('data/absagegruende.txt'); const text = await res.text(); return text .split('\n') .map(line => line.trim()) .filter(line => line.length > 0); } document.addEventListener('DOMContentLoaded', async () => { // URL-Parameter lesen const urlParams = new URLSearchParams(window.location.search); const query = { typ: urlParams.get('typ') || 'regular', storno: urlParams.get('storno') === 'true', double: urlParams.get('double') === 'true', name: urlParams.get('name') || 'Null', datum: urlParams.get('datum') === 'true' }; const absagegrundListe = await ladeAbsagegruende(); const fuehrung = query.typ === 'sonnen' ? 'Sonnenführung' : 'Sternführung'; let absagegrund = ""; const useDatum = query.datum const ajaxURL = "php/anmeldDB.php"; const ANZAHL_DATES = query.typ === 'sonnen' ? 25 : 50; bodytext = "" betreff = "" const TEXTE = { absagetext: "Absage an alle angemeldeten Besucher senden.", bittegrund: "Die Führung wird abgesagt wegen:", schonabgesagt: "Absage schon gesendet. Nochmal senden?", subject: (useDatum, date) => `Absage der ${useDatum ? `${fuehrung} am ${date}` : `heutigen ${fuehrung}`}`, bodytext: (useDatum, date) => `Sehr geehrte Dame, sehr geehrter Herr, Sie haben sich über unsere Webseite www.sternwarte-welzheim.de zur ${useDatum ? `${fuehrung} am ${date}`: `heutigen ${fuehrung}`} angemeldet. Aufgrund {absagegrund} können wir ${useDatum ? `am ${date}` : 'heute'} keine ${fuehrung} anbieten. Bitte melden Sie sich für einen anderen Termin neu an. Mit freundlichen Grüßen Beobachtergruppe Sternwarte Welzheim` , }; const liste = { emails: [], ids: [] }; let abgesagt = false; let actualdate; let isSmallScreen = false let DateTime = luxon.DateTime function $(selector) { return document.querySelector(selector); } function $all(selector) { return document.querySelectorAll(selector); } async function fetchFromDbase(body) { body.typ = query.typ; const response = await fetch(ajaxURL, { method: 'POST', headers: {'Content-Type': 'application/js'}, body: JSON.stringify(body) }); return await response.json(); } async function putToDbase(body) { body.typ = query.typ; const response = await fetch(ajaxURL, { method: 'POST', headers: {'Content-Type': 'application/js'}, body: JSON.stringify(body) }); return await response.json(); } function clearElement(el) { el.innerHTML = ''; } function appendHtml(el, html) { el.insertAdjacentHTML('beforeend', html); } function setVisibility(id, visible) { $(id).style.visibility = visible ? 'visible' : 'hidden'; } async function storeAbsage(ids) { const update = { cmd: 'UPDATE', field: 'abgesagt', ids: ids, values: [1] }; await putToDbase(update); abgesagt = true; } async function getDetailText(id) { const nbr = parseInt(id); const holit = await fetchFromDbase({cmd:'GET_TEILN_ID', id:nbr}); const entry = holit[0]; return `
${entry.name} ${entry.vorname}
${entry.email}
${entry.plz} ${entry.stadt}
${entry.strasse}
${entry.telefon}
${entry.remarks}
`; } // Teilnehmer aus 'anmeldungen' austragen und den count in 'fdatum1' anpassen const austragen = async (teilnehmer) => { let update = {cmd: 'DELETEONE', id: parseInt(teilnehmer.id)} const erg1 = await putToDbase(update) // update = {cmd: 'UPDATECOUNT',date: parseInt(teilnehmer.fdatum), anzahl: parseInt(teilnehmer.anzahl)} const erg2 = await putToDbase(update) console.log("Storno Ergebisse: ",erg1,erg2) showAktAnmeldungen(actualdate) } async function showAktAnmeldungen(date) { actualdate = date; liste.emails = []; liste.ids = []; abgesagt = true; let column = query.storno ? "col-2" : "col-3"; const anmeldungen = await fetchFromDbase({cmd:'GET_ANMELD', id:date}); let besucher = 0; clearElement($('tbody')); for (let e of anmeldungen) { besucher += parseInt(e.anzahl); liste.emails.push(e.email); liste.ids.push(e.id); if (e.abgesagt !== '1') { abgesagt = false; } // const selected = e.teilgenommen === "1" ? "checked" : ""; const row = document.createElement('tr'); row.classList.add('d-flex'); row.innerHTML = ` ${e.name} ${e.vorname} ${e.anzahl}` if (query.storno) { row.innerHTML += `` } row.querySelector('.tdname').addEventListener('click', async () => { const detail = await getDetailText(e.id); $('#detailtext').innerHTML = detail; $('#detaildialog').showModal(); }); if(query.storno) { row.querySelector('.tdstorno').addEventListener('click', function() { const tr = this.closest("tr") // Finds the closest row const index = tr.rowIndex-1 austragen(anmeldungen[index]) }); } $('#tabAnmeld tbody').appendChild(row); } if (abgesagt) { $('#absagen').innerHTML = 'Absage
wurde gesendet'; } else { $('#absagen').innerHTML = 'Absage senden'; } if (besucher !== 0) { const sumRow = document.createElement('tr'); sumRow.id = 'summe'; sumRow.classList.add('d-flex'); sumRow.innerHTML = ` Summe der Anmeldungen` if (query.storno) { sumRow.innerHTML += `${besucher}`; } else { sumRow.innerHTML += `${besucher}`; } $('#tabAnmeld tbody').appendChild(sumRow); } bodytext = TEXTE.bodytext(useDatum, DateTime.fromISO(date).setLocale("de").toFormat("cccc, 'den' d. LLLL yyyy")) betreff = TEXTE.subject(useDatum, DateTime.fromISO(date).setLocale("de").toFormat("cccc, 'den' d. LLLL yyyy")) console.log(betreff) } async function findName(name) { const update = { cmd: 'GET_TEILN_NAME', name: name }; let erg = await putToDbase(update); clearElement($('#tnames')); appendHtml($('#tnames'), ` Name Anzahl Datum Finden `); for (let x of erg) { appendHtml($('#tnames'), ` ${x.name} ${x.vorname} ${x.anzahl} ${DateTime.fromISO(x.fdatum).toFormat('yyyy-LL-dd')} `); } appendHtml($('#tnames'), ``); $('#names').style.display = 'block'; $all('.findit').forEach(btn => { btn.addEventListener('click', async () => { const id = btn.value; const detail = await getDetailText(id); $('#detailtext').innerHTML = detail; $('#detaildialog').showModal(); }); }); } $('#absagen').addEventListener('click', () => { $('#absagetext').innerHTML = abgesagt ? TEXTE.schonabgesagt : TEXTE.absagetext; $('#bittegrund').innerHTML = TEXTE.bittegrund $('#absagedialog').showModal(); const container = $('#absagegrund'); clearElement(container); absagegrundListe.forEach((g, i) => { const line = document.createElement('div'); line.className = 'absageline'; const radio = document.createElement('input'); radio.type = 'radio'; radio.name = 'grund'; radio.value = i; radio.id = `grund${i}`; radio.checked = i === 0; // Default to the first option const label = document.createElement('label'); label.setAttribute('for', `grund${i}`); const span = document.createElement('span'); span.textContent = g; span.style.marginLeft = "20px" line.appendChild(radio); line.appendChild(span); line.appendChild(document.createElement('br')); container.appendChild(line); }); }); $('#absagedialog-send').addEventListener('click', async () => { const grundIndex = Array.from($all('input[name=grund]')).find(el => el.checked)?.value || 0; absagegrund = absagegrundListe[grundIndex]; await storeAbsage(liste.ids); if (query.typ !== 'sonnen') { await fetch('https://laufschrift.rexfue.de/switch/switch_on') } bodyText = bodytext.replace("{absagegrund}", absagegrund); const mailRet = await fetchFromDbase({ cmd: 'SENDMYMAIL', to: ['rexfue@gmail.com'], betreff: betreff, body: bodyText, bcc: liste.emails }); if (mailRet.error) { $('#errortext').innerHTML = mailRet.errortext $('#errordialog-ok').addEventListener('click', () => $('#errordialog').close()) $('#errordialog').showModal(); } console.log("Mailret: ", mailRet, "Gesendet an: ", liste.emails) $('#absagen').innerHTML = 'Absage
wurde gesendet'; $('#absagedialog').close(); }); $('#absagedialog-cancel').addEventListener('click', () => { $('#absagedialog').close(); }); async function getDoubles(date) { const update = { cmd: 'GET_ANMELDNEW', date: date, special: "alllater" }; let { data } = await putToDbase(update); data.sort((a, b) => a.name.localeCompare(b.name)); data.push({name: '', vorname: '', email: ''}); let i; for(i = 0; i < data.length - 1; i++) { data[i].single = false; if(data[i].name !== data[i+1].name) { data[i].single = true; } else { while((i < data.length - 1) && (data[i].name === data[i+1].name)) { if (data[i].strasse.slice(0,6).toUpperCase() !== data[i+1].strasse.slice(0,6).toUpperCase() || data[i].plz !== data[i+1].plz) { data[i].single = true; break; } else { i++; } } } } data[i].single = true; return data; } async function showDoubles(date) { const erg = await getDoubles(date); const container = $('#tnames'); clearElement(container); appendHtml(container, ` Name Vorname Email Anz Datum Anmeldung `); for (let x of erg) { if (x.single) continue; appendHtml(container, ` ${x.name} ${x.vorname} ${x.email} ${x.anzahl} ${DateTime.fromISO(x.fdatum).toFormat('yyyy-LL-dd')} ${DateTime.fromISO(x.angemeldet).toFormat('yyyy-LL-dd')} `); } appendHtml(container, ``); $('#names').style.display = 'block'; } function switchText() { const thead = document.createElement('thead'); const row = document.createElement('tr'); let column = query.storno ? "col-2" : "col-3" row.className = 'd-flex'; row.innerHTML = ` Name ${isSmallScreen ? 'Anz' : 'Personen'}` if (query.storno) { row.innerHTML += `Storno`; } $('#versn').innerHTML = "Version: " + VERSION + ' vom ' + VDATE thead.appendChild(row); const table = $('#tabAnmeld'); clearElement(table); // Leert sowohl thead als auch tbody table.appendChild(thead); table.appendChild(document.createElement('tbody')); } // Aus dem rohen Führungsdatum von der Datenbank ein besser // leserliches Format erzeugen // Params: // w -> Wochentag // d -> Datum in DBase-Format // t -> Uhrzeit // Return // neu formatierter Datums-String const bauDate = (w,d,t) => { let dd = d.replace(/^(\d{4})(\d{2})(\d{2})$/, '$3.$2.$1',); let dt = w.substr(0,2) + ', ' + dd + ' ' + t.substr(0,2) + ':00'; return dt; } async function buildFuehrungsDates(dates, last) { let n = 0; let i = 0; let summ = 0; let select = `
Gesamtzahl der Anmeldungen (ab heute): ${summ}
`; $('#auswahl').innerHTML = select; $('#ftermin').addEventListener('change', async () => { const date = $('#ftermin').value; const index = $('#ftermin').selectedIndex; setVisibility('#absagen', index === 0 || useDatum); await showAktAnmeldungen(date); }); return n; } async function main(n) { let index = 0 const today = DateTime.now().minus({ days: 14 }).toFormat("yyyyLLdd"); const dates = await fetchFromDbase({cmd:'GET_DATES', anzahl:n, date: today}); const last = await fetchFromDbase({cmd:'GET_LASTANMELDUNG', date: today}); let mq = window.matchMedia('(max-width: 800px)'); isSmallScreen = mq.matches switchText(); mq.addEventListener('change', async (e) => { isSmallScreen = e.matches switchText(); await buildFuehrungsDates(dates, last); showAktAnmeldungen(actualdate); }); index = await buildFuehrungsDates(dates, last); await showAktAnmeldungen(dates[index].datum); if (query.name !== 'Null') { await findName(query.name); } if (query.double) { await showDoubles(DateTime.now().toFormat("yyyyLLdd")); } } main(ANZAHL_DATES).catch(console.error); });