First Commit

This commit is contained in:
2025-11-02 22:52:08 +01:00
commit 73fbbf1be2
5821 changed files with 977526 additions and 0 deletions

View File

@@ -0,0 +1,477 @@
// 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 `
<div class="det">${entry.name} ${entry.vorname}<br /></div>
<div class="det">${entry.email}<br /></div>
<div class="det">${entry.plz} ${entry.stadt}<br /></div>
<div class="det">${entry.strasse}<br /></div>
<div class="det">${entry.telefon}<br /></div>
<div class="det">${entry.remarks}<br /></div>`;
}
// 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 = `
<td class="tdname col-6">${e.name} ${e.vorname}</td>
<td class=${column}>${e.anzahl}</td>`
if (query.storno) {
row.innerHTML += `<td class="col-2 tdstorno"><input type="checkbox" value="${e.id}" </td>`
}
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 <tr>
const index = tr.rowIndex-1
austragen(anmeldungen[index])
});
}
$('#tabAnmeld tbody').appendChild(row);
}
if (abgesagt) {
$('#absagen').innerHTML = 'Absage<br />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 = `
<td class="col-6">Summe der Anmeldungen</td>`
if (query.storno) {
sumRow.innerHTML += `<td style="text-align: center;" class="col-4">${besucher}</td>`;
} else {
sumRow.innerHTML += `<td class="col-3">${besucher}</td>`;
}
$('#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'), `
<thead><tr>
<th class="col-6">Name</th>
<th class="col-2">Anzahl</th>
<th class="col-2">Datum</th>
<th class="col-2">Finden</th>
</tr></thead><tbody>`);
for (let x of erg) {
appendHtml($('#tnames'), `
<tr>
<td class="tdname col-6">${x.name} ${x.vorname}</td>
<td class="col-2">${x.anzahl}</td>
<td class="col-2">${DateTime.fromISO(x.fdatum).toFormat('yyyy-LL-dd')}</td>
<td class="tdfind col-2"><button type="button" class="findit" value="${x.id}">🔍</button></td>
</tr>`);
}
appendHtml($('#tnames'), `</tbody>`);
$('#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<br />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, `
<thead><tr>
<th class="col-2">Name</th>
<th class="col-2">Vorname</th>
<th class="col-3">Email</th>
<th class="col-1">Anz</th>
<th class="col-2">Datum</th>
<th class="col-2">Anmeldung</th>
</tr></thead><tbody>`);
for (let x of erg) {
if (x.single) continue;
appendHtml(container, `
<tr>
<td class="tdname col-2">${x.name}</td>
<td class="tdname col-2">${x.vorname}</td>
<td class="tdname col-3">${x.email}</td>
<td class="col-1">${x.anzahl}</td>
<td class="col-2">${DateTime.fromISO(x.fdatum).toFormat('yyyy-LL-dd')}</td>
<td class="col-2">${DateTime.fromISO(x.angemeldet).toFormat('yyyy-LL-dd')}</td>
</tr>`);
}
appendHtml(container, `</tbody>`);
$('#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 = `
<th class="col-6">Name</th>
<th class=${column}>${isSmallScreen ? 'Anz' : 'Personen'}</th>`
if (query.storno) {
row.innerHTML += `<th class="col-2">Storno</th>`;
}
$('#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 = `<select name='ftermin' id='ftermin'>`;
let selectedNext = false;
const today = DateTime.now().startOf('day');
for (let d of dates) {
let isselected = "";
const fday = DateTime.fromISO(d.datum);
if (!selectedNext && (isSameorAfter = fday >= today)) {
selectedNext = true;
isselected = "selected";
n = i;
}
const count = await fetchFromDbase({cmd: 'GET_COUNTS', fdate: d.datum});
const isFuehrung = (count && count > 0) ? '' : 'disabled';
let datstr
let grpstr
if (query.typ == 'regular') {
datstr = bauDate(d.wtag, d.datum, d.uhrzeit)
grpstr = `(${d.grp})`
} else {
datstr = bauDate('So', d.datum, '11')
grpstr = "&nbsp;"
}
if (isSmallScreen) {
select += `
<option value="${d.datum}" ${isselected} ${isFuehrung}> ${datstr} ${count || 0}B</option>`;
} else {
select += `
<option value="${d.datum}" ${isselected} ${isFuehrung}> ${datstr} ${grpstr} ${count || 0} Besucher</option>`;
}
i++;
summ += count ? parseInt(count) : 0;
if (d.datum >= last) break;
}
select += `</select>
<div id="gesamtsumme">Gesamtzahl der Anmeldungen (ab heute): ${summ}</div>`;
$('#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);
});

View File

@@ -0,0 +1,462 @@
// 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'
};
const absagegrundListe = await ladeAbsagegruende();
const fuehrung = query.typ === 'sonnen' ? 'Sonnenführung' : 'Sternführung';
let absagegrund = "";
const ajaxURL = "php/anmeldDB.php";
const ANZAHL_DATES = query.typ === 'sonnen' ? 25 : 50;
const TEXTE = {
absagetext: "Absage an alle angemeldeten Besucher senden.",
bittegrund: "Die Führung wird abgesagt wegen:",
schonabgesagt: "Absage schon gesendet. Nochmal senden?",
subject: `Absage der heutigen ${fuehrung}`,
bodytext: `Sehr geehrte Dame, sehr geehrter Herr,
Sie haben sich über unsere Webseite www.sternwarte-welzheim.de zur heutigen ${fuehrung} angemeldet.
Aufgrund {absagegrund} können wir heute keine Sternführung 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 `
<div class="det">${entry.name} ${entry.vorname}<br /></div>
<div class="det">${entry.email}<br /></div>
<div class="det">${entry.plz} ${entry.stadt}<br /></div>
<div class="det">${entry.strasse}<br /></div>
<div class="det">${entry.telefon}<br /></div>
<div class="det">${entry.remarks}<br /></div>`;
}
// 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 = `
<td class="tdname col-6">${e.name} ${e.vorname}</td>
<td class=${column}>${e.anzahl}</td>`
if (query.storno) {
row.innerHTML += `<td class="col-2 tdstorno"><input type="checkbox" value="${e.id}" </td>`
}
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 <tr>
const index = tr.rowIndex-1
austragen(anmeldungen[index])
});
}
$('#tabAnmeld tbody').appendChild(row);
}
if (abgesagt) {
$('#absagen').innerHTML = 'Absage<br />wurde gesendet';
}
if (besucher !== 0) {
const sumRow = document.createElement('tr');
sumRow.id = 'summe';
sumRow.classList.add('d-flex');
sumRow.innerHTML = `
<td class="col-6">Summe der Anmeldungen</td>`
if (query.storno) {
sumRow.innerHTML += `<td style="text-align: center;" class="col-4">${besucher}</td>`;
} else {
sumRow.innerHTML += `<td class="col-3">${besucher}</td>`;
}
$('#tabAnmeld tbody').appendChild(sumRow);
}
}
async function findName(name) {
const update = { cmd: 'GET_TEILN_NAME', name: name };
let erg = await putToDbase(update);
clearElement($('#tnames'));
appendHtml($('#tnames'), `
<thead><tr>
<th class="col-6">Name</th>
<th class="col-2">Anzahl</th>
<th class="col-2">Datum</th>
<th class="col-2">Finden</th>
</tr></thead><tbody>`);
for (let x of erg) {
appendHtml($('#tnames'), `
<tr>
<td class="tdname col-6">${x.name} ${x.vorname}</td>
<td class="col-2">${x.anzahl}</td>
<td class="col-2">${DateTime.fromISO(x.fdatum).toFormat('yyyy-LL-dd')}</td>
<td class="tdfind col-2"><button type="button" class="findit" value="${x.id}">🔍</button></td>
</tr>`);
}
appendHtml($('#tnames'), `</tbody>`);
$('#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')
}
const bodyText = TEXTE.bodytext.replace("{absagegrund}", absagegrund);
await fetchFromDbase({
cmd: 'SENDMYMAIL',
to: ['rexfue@gmail.com'],
betreff: TEXTE.subject,
body: bodyText,
bcc: liste.emails
});
console.log("Gesendet an: ", liste.emails)
$('#absagen').innerHTML = 'Absage<br />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, `
<thead><tr>
<th class="col-2">Name</th>
<th class="col-2">Vorname</th>
<th class="col-3">Email</th>
<th class="col-1">Anz</th>
<th class="col-2">Datum</th>
<th class="col-2">Anmeldung</th>
</tr></thead><tbody>`);
for (let x of erg) {
if (x.single) continue;
appendHtml(container, `
<tr>
<td class="tdname col-2">${x.name}</td>
<td class="tdname col-2">${x.vorname}</td>
<td class="tdname col-3">${x.email}</td>
<td class="col-1">${x.anzahl}</td>
<td class="col-2">${DateTime.fromISO(x.fdatum).toFormat('yyyy-LL-dd')}</td>
<td class="col-2">${DateTime.fromISO(x.angemeldet).toFormat('yyyy-LL-dd')}</td>
</tr>`);
}
appendHtml(container, `</tbody>`);
$('#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 = `
<th class="col-6">Name</th>
<th class=${column}>${isSmallScreen ? 'Anz' : 'Personen'}</th>`
if (query.storno) {
row.innerHTML += `<th class="col-2">Storno</th>`;
}
$('#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 = `<select name='ftermin' id='ftermin'>`;
let selectedNext = false;
const today = DateTime.now().startOf('day');
for (let d of dates) {
let isselected = "";
const fday = DateTime.fromISO(d.datum);
if (!selectedNext && (isSameorAfter = fday >= today)) {
selectedNext = true;
isselected = "selected";
n = i;
}
const count = await fetchFromDbase({cmd: 'GET_COUNTS', fdate: d.datum});
const isFuehrung = (count && count > 0) ? '' : 'disabled';
let datstr
let grpstr
if (query.typ == 'regular') {
datstr = bauDate(d.wtag, d.datum, d.uhrzeit)
grpstr = `(${d.grp})`
} else {
datstr = bauDate('So', d.datum, '11')
grpstr = "&nbsp;"
}
if (isSmallScreen) {
select += `
<option value="${d.datum}" ${isselected} ${isFuehrung}> ${datstr} ${count || 0}B</option>`;
} else {
select += `
<option value="${d.datum}" ${isselected} ${isFuehrung}> ${datstr} ${grpstr} ${count || 0} Besucher</option>`;
}
i++;
summ += count ? parseInt(count) : 0;
if (d.datum >= last) break;
}
select += `</select>
<div id="gesamtsumme">Gesamtzahl der Anmeldungen (ab heute): ${summ}</div>`;
$('#auswahl').innerHTML = select;
$('#ftermin').addEventListener('change', async () => {
const date = $('#ftermin').value;
const index = $('#ftermin').selectedIndex;
setVisibility('#absagen', index === 0);
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);
});

View File

@@ -0,0 +1,98 @@
// VersiosNummern und -Geschichte
const VERSION="1.8.1";
const VDATE="2025-10-20";
/* History
Rev. Datum Entwickler
1.8.1 2025-10-19 rxf
- Errormeldung, wenn bei 'anmeld.js' die Abmeldung nicht rausgeht
1.8.0 2025-10-17 rxf
- intern Anmeldung kann nun mit Datum versehen werden (in der URL: &dateum=true), dass wird die
Abmeldungn mit dem Datum versehen und es kann auch schon füher abgemeldet werden.
- zusätzlicher Abmeldetext
- der Mailer arbeitet nun mit der Adresse: sternwarte.welzheim@gmx.de (!)
1.7.3 2025-09-07 rxf
- 'Laufschrift einschalten' wieder reingebaut, aber nicht bei Sonnenführung
1.7.2 2025-07-27 rxf
- Selectzeile einfacher bei kleinem Display
- statt moment nun luxor verwendet
1.7.1 2025-07-21 rxf
- sonnef komplett entfernt - das ist nun komplett in anmeld.js mit drin
- anmled.php umbenannt in index.php
- Aufruf auf der internen Seite angepasst:
- ../intern/anmeld/index.php - Anmeldungen zu regulären Führungen
- ../intern/anmeld/index.php?typ=sonnen - Anmeldungen zu den Sonnenführungen
1.7.0 2025-07-07 rxf
- umgestellt, so dass kein jquery und kein bootstrap mehr nötig ist (mit Hilfe von ChatGPT)
- Absagegrund kann angewählt werden
- Absagegrund liegt in der textDatei data/absagegruende.txt
1.63 2024-02-20 rxf
- Erkennung von Dubletten verbessert
1.62 2024-02-04 rxf
- Laufschrift einschalten, wenn Absage gesendet wird
1.61 2023-10-04 rxf
- Anzeiger der Teilnehmer-Datails funktioniert wieder
1.60 2022-10-15 rxf
- Probleme mit der Besucheranzahl gelöst (Anzahl IMMER aus der DB holen)
1.59 2022-05-29 rxf
- bei sofianmeld.js 14 Tage vorher mit auswählen lassen
1.58 2021-12-01 rxf
- Astroseminar Protokolle im internen bereich
1.57 2021-11-28 rxf
- 'storniert' bei Anmeldungen eingeführt
1.56 2021-11-25 rxf
- Senden von Mails nun via phpmailer (SMTP)
1.55 2021-09-21 rxf
- Aufruf weiter schneller
1.54 2021-08-19 rxf
- Aufbau der DB angepasst, damit schnellerer Aufruf
- Anzeige der Gesamzanzahl der zukünftigen Anmeldungen
- Daten ohne Führung hellgrau anzeigen
1.53 2021-08-08 rxf
- Absage-Mail per PHP-Call
1.52 2021-08-03 rxf
- Anzeige von 30 Führungstagen
1.5 2021-07-29 rxf
- Name der führenden Gruppe dazu
1.4 2021-07-25 rxf
- Anzahl der angemeldeten Besucher mit anzeigen
1.3 2020-10-11 rxf
- Anzeige-Dialog bei teilgenonnen Speicher nun OK
1.3 2020-10-11 rxf
- 'teilgenommen' wird nun richtig angezeigt
1.2 2020-10-07 rxf
- Wenn die Absage-Mail schon raus ist, dann dieses melden
1.1 2020-10-05 rxf
- Möglichkeit, an Alle eine Absage-Mail zu senden, eingebaut
1.0 2020-10-09 rxf
- Erste fertige Version. Geht so zum Testen an rexfue.de
0.00 2020-09-20 rxf
- Los gehts
*/

View File

@@ -0,0 +1,89 @@
// VersiosNummern und -Geschichte
const VERSION="1.7.3";
const VDATE="2025-09-07";
/* History
Rev. Datum Entwickler
1.7.3 2025-09-07 rxf
- 'Laufschrift einschalten' wieder reingebaut, aber nicht bei Sonnenführung
1.7.2 2025-07-27 rxf
- Selectzeile einfacher bei kleinem Display
- statt moment nun luxor verwendet
1.7.1 2025-07-21 rxf
- sonnef komplett entfernt - das ist nun komplett in anmeld.js mit drin
- anmled.php umbenannt in index.php
- Aufruf auf der internen Seite angepasst:
- ../intern/anmeld/index.php - Anmeldungen zu regulären Führungen
- ../intern/anmeld/index.php?typ=sonnen - Anmeldungen zu den Sonnenführungen
1.7.0 2025-07-07 rxf
- umgestellt, so dass kein jquery und kein bootstrap mehr nötig ist (mit Hilfe von ChatGPT)
- Absagegrund kann angewählt werden
- Absagegrund liegt in der textDatei data/absagegruende.txt
1.63 2024-02-20 rxf
- Erkennung von Dubletten verbessert
1.62 2024-02-04 rxf
- Laufschrift einschalten, wenn Absage gesendet wird
1.61 2023-10-04 rxf
- Anzeiger der Teilnehmer-Datails funktioniert wieder
1.60 2022-10-15 rxf
- Probleme mit der Besucheranzahl gelöst (Anzahl IMMER aus der DB holen)
1.59 2022-05-29 rxf
- bei sofianmeld.js 14 Tage vorher mit auswählen lassen
1.58 2021-12-01 rxf
- Astroseminar Protokolle im internen bereich
1.57 2021-11-28 rxf
- 'storniert' bei Anmeldungen eingeführt
1.56 2021-11-25 rxf
- Senden von Mails nun via phpmailer (SMTP)
1.55 2021-09-21 rxf
- Aufruf weiter schneller
1.54 2021-08-19 rxf
- Aufbau der DB angepasst, damit schnellerer Aufruf
- Anzeige der Gesamzanzahl der zukünftigen Anmeldungen
- Daten ohne Führung hellgrau anzeigen
1.53 2021-08-08 rxf
- Absage-Mail per PHP-Call
1.52 2021-08-03 rxf
- Anzeige von 30 Führungstagen
1.5 2021-07-29 rxf
- Name der führenden Gruppe dazu
1.4 2021-07-25 rxf
- Anzahl der angemeldeten Besucher mit anzeigen
1.3 2020-10-11 rxf
- Anzeige-Dialog bei teilgenonnen Speicher nun OK
1.3 2020-10-11 rxf
- 'teilgenommen' wird nun richtig angezeigt
1.2 2020-10-07 rxf
- Wenn die Absage-Mail schon raus ist, dann dieses melden
1.1 2020-10-05 rxf
- Möglichkeit, an Alle eine Absage-Mail zu senden, eingebaut
1.0 2020-10-09 rxf
- Erste fertige Version. Geht so zum Testen an rexfue.de
0.00 2020-09-20 rxf
- Los gehts
*/