First Commit
This commit is contained in:
471
html/sternwarte/javascript/anmeldung.js
Normal file
471
html/sternwarte/javascript/anmeldung.js
Normal file
@@ -0,0 +1,471 @@
|
||||
// anmeldung.js rxf 2020-10.12
|
||||
// Dynamik für die Anmelde-Seite
|
||||
//
|
||||
|
||||
$(document).ready(() => {
|
||||
|
||||
const ajaxURL="../DB4js.php";
|
||||
const maxPersonen = 10;
|
||||
|
||||
const dummyTln = {
|
||||
name:"Zuname{z}",
|
||||
vorname:"",
|
||||
email:"rxf{z}@gmx.de",
|
||||
telefon:"0711123456789",
|
||||
plz:"12345",
|
||||
stadt:"Ort{z}",
|
||||
strasse:"Straße {z}",
|
||||
fid: "",
|
||||
anzahl:1,
|
||||
teilgenommen: 0,
|
||||
remarks:"Bemerkung Nr {z}",
|
||||
abgesagt: 0,
|
||||
angemeldet: moment().format("YYYY-MM-DD")
|
||||
};
|
||||
|
||||
let aktualTln = {
|
||||
name:"",
|
||||
vorname:"",
|
||||
email:"",
|
||||
telefon:"",
|
||||
plz:"",
|
||||
stadt:"",
|
||||
strasse:"",
|
||||
fid: "",
|
||||
anzahl:1,
|
||||
teilgenommen: 0,
|
||||
remarks:"",
|
||||
abgesagt: 0,
|
||||
angemeldet: ""
|
||||
};
|
||||
|
||||
const mandatory = {
|
||||
name:true,
|
||||
vorname:false,
|
||||
email:true,
|
||||
telefon:false,
|
||||
plz:true,
|
||||
stadt:true,
|
||||
strasse:true,
|
||||
fid: false,
|
||||
anzahl:false,
|
||||
teilgenommen: false,
|
||||
remarks:false,
|
||||
abgesagt: false,
|
||||
angemeldet: true
|
||||
};
|
||||
|
||||
let allParticipants = [];
|
||||
let errtext = "";
|
||||
|
||||
|
||||
// Von der Datenbank Werte abholen
|
||||
// Param:
|
||||
// body: Object mit cmd und param
|
||||
// Return:
|
||||
// angeforderte Daten als JSON
|
||||
const fetchFromDbase = async (body) => {
|
||||
const response = await fetch(ajaxURL,{
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/js'},
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
|
||||
// In die Datenbank Werte eintragen
|
||||
// Param:
|
||||
// body: Object mit cmd und param
|
||||
// Return:
|
||||
// angeforderte Daten als JSON
|
||||
const putToDbase = async (body) => {
|
||||
const response = await fetch(ajaxURL,{
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/js'},
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
|
||||
// Beim Senden der Anmeldeseite die Nummer der Führung mit schicken
|
||||
$('form').submit((event) => {
|
||||
let nr = $('#ftermin').find(':selected');
|
||||
console.log('nr: ', nr[0].value);
|
||||
$('#fid').val(nr[0].value);
|
||||
});
|
||||
|
||||
|
||||
// zum Testen die Anmelde-Seite automatisch ausfüllen
|
||||
$('#autofillbutton').click(() => {
|
||||
let rand = Math.floor(Math.random() * 100);
|
||||
for (let f in dummyTln) {
|
||||
if (f=='fid') {
|
||||
continue;
|
||||
}
|
||||
let x = dummyTln[f].toString();
|
||||
aktualTln[f] = x.replace("{z}",rand);
|
||||
$('#'+f).val(x.replace("{z}",rand));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Aus dem rohen Führungsdatum von der Datenbank ein besser
|
||||
// leserliches Format erzeugen
|
||||
// Params:
|
||||
// w -> Wocjentag
|
||||
// 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',);
|
||||
return w.substr(0,2) + ', ' + dd + ' ' + t;
|
||||
}
|
||||
|
||||
|
||||
// Aus der Datenbank die nächsten 'n' Führungsdaten holen und
|
||||
// in den <option>-Tags anzeigen.
|
||||
// Zusätzlich für jeden Tag zählen, wieviel schon angemeldet sind.
|
||||
// Sind es >= 10, dass diese <option> als "disbaled" markieren.
|
||||
// Die Anzahl der noch freien Plätze mit anzeigen
|
||||
async function buildfuehrungdates(n) {
|
||||
const dates = await fetchFromDbase({cmd:'GET_DATES',anzahl:n, fid:0});
|
||||
|
||||
str = "";
|
||||
for (let d of dates) {
|
||||
const count = await fetchFromDbase({cmd: 'GET_COUNTS', fid: d.fid});
|
||||
str += `<option ${count >= maxPersonen ? "disabled" : ""} ` +
|
||||
`value=${d.fid}> ${bauDate(d.weekday, d.date, d.time)} Frei: ${maxPersonen - count}</>`;
|
||||
}
|
||||
$('#fid').append(str);
|
||||
}
|
||||
|
||||
|
||||
// Mit der fid das Führungsdatum aus der DB holen und in leserliche
|
||||
// Form umsetzen
|
||||
// Params:
|
||||
// fid -> ID des Eintrages in der DB
|
||||
// Return
|
||||
// String mit dem Führungsdatum
|
||||
const getfdateformatted = async (fid) => {
|
||||
const nxd = await fetchFromDbase({cmd: 'GET_DATES', anzahl: 1, fid: fid});
|
||||
let newdate = bauDate(nxd[0].weekday, nxd[0].date, nxd[0].time);
|
||||
return newdate.replace(/(\d+) Uhr/, "um $1 Uhr");
|
||||
}
|
||||
|
||||
// Infomail über die Anmeldung bzw. Stornierung an rexfue@gmail.com senden
|
||||
// Parameters:
|
||||
// storno -> true: Stornierung, fals: Anmeldung
|
||||
const sendInfoMail = async(storno) => {
|
||||
const fdatum = await getfdateformatted(aktualTln.fid);
|
||||
const subj = storno ? "Stornierung einer Stern-Führung" : "Neue Anmeldung zu einer Stern-Führung";
|
||||
const ret = await putToDbase({
|
||||
cmd: 'SEND_INFO_MAIL',
|
||||
to: 'rexfue@gmail.com',
|
||||
subject: subj,
|
||||
body: '<html>' +
|
||||
'<body><table>' +
|
||||
'<tr><td>Name, Vorname</td><td style="text-align: right;">' + aktualTln.name + ', ' + aktualTln.vorname + '</td></tr>' +
|
||||
'<tr><td>Strasse</td><td style="text-align: right;">' + aktualTln.strasse + '</td></tr>' +
|
||||
'<tr><td>Ort</td><td style="text-align: right;">' + aktualTln.plz + ', ' + aktualTln.stadt + '</td></tr>' +
|
||||
'<tr><td>Telefon</td><td style="text-align: right;">' + aktualTln.telefon + '</td></tr>' +
|
||||
'<tr><td>E-mail</td><td style="text-align: right;">' + aktualTln.email + '</td></tr>' +
|
||||
'<tr><td>Termin</td><td style="text-align: right;">' + fdatum + '</td></tr>' +
|
||||
'<tr><td>Personen</td><td style="text-align: right;">' + aktualTln.anzahl + '</td></tr>' +
|
||||
'<tr><td>Bemerkungen</td><td class="fr">' + aktualTln.remarks + '</td></tr>' +
|
||||
'</table></body></html>'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Bestätigungsmail an den Anmeldeneden senden
|
||||
// Params:
|
||||
// storno -> true: Stornierung, fals: Anmeldung
|
||||
const sendConfirmation = async (storno) => {
|
||||
const fdatum = await getfdateformatted(aktualTln.fid);
|
||||
let body = "Sehr geehrte Dame, sehr geehrter Herr, \r\n\r\nhiermit bestätigen wir Ihre "
|
||||
body += storno ? "Stornierung der " : "";
|
||||
body += "Anmeldung zu der Führung auf der Sternwarte Welzheim am\r\n\r\n" +
|
||||
`${fdatum} für ${aktualTln.name} ${aktualTln.vorname} mit ${aktualTln.anzahl} ${aktualTln.anzahl==1?"Person.":"Personen."}` +
|
||||
"\r\n\r\n";
|
||||
if (!storno) {
|
||||
body +=
|
||||
"Bitte bringen Sie diese Bestätigung als Ausdruck oder digital zur Führung mit. \r\n" +
|
||||
"Ohne diese Bestätigung erfolgt ausnahmslos k e i n Einlass.\r\n\r\n" +
|
||||
"Falls Sie den Führungstermin absagen wollen, verwenden Sie bitte folgenden Link \r\n";
|
||||
body += develop == "true" ?
|
||||
"http://localhost:8082/anmeldung.php?storno=" :
|
||||
"https://sternwarte-welzheim.de/anmeldung.php?storno=";
|
||||
body += md5(aktualTln.email + aktualTln.fid) + "\n\r";
|
||||
body += "Die Führung findet NUR bei sternklarem Himmel statt. Falls der Himmel bedeckt ist \r\n" +
|
||||
"und die Führung ausfällt, bitten wir Sie um eine neue Anmeldung.\r\n\r\n" +
|
||||
"Die Hygienevorschriften sind zu beachten: Die Teilnehmer/-innen müssen Gesichtsmasken \r\n" +
|
||||
"tragen und den vorgeschriebenen Abstand halten. " +
|
||||
"Nicht teilnehmen dürfen Personen, \r\ndie in den letzten vierzehn Tagen Kontakt " +
|
||||
"mit einem Coronavirus-Infizierten \r\nhatten oder Infektionssymptome zeigen.\r\n\r\n";
|
||||
}
|
||||
body += "Mit freundlichen Grüßen\r\n\r\n" +
|
||||
"Beobachterteam der Sternwarte Welzheim\r\n\r\n" +
|
||||
"www.sternwarte-welzheim.de"
|
||||
const ret = await putToDbase({
|
||||
cmd: 'SEND_MAIL',
|
||||
to: aktualTln.email,
|
||||
subject: storno ?
|
||||
"Stornierung Ihrer Anmeldung zu einer Führung auf der Sternwarte Welzheim" :
|
||||
"Anmeldung zu einer Führung auf der Sternwarte Welzheim",
|
||||
body: body,
|
||||
});
|
||||
console.log("hier wird die Email gesendet");
|
||||
sendInfoMail(storno);
|
||||
}
|
||||
|
||||
|
||||
// MD5-Hash ausrechnen
|
||||
const md5 = (value) => {
|
||||
return CryptoJS.MD5(value).toString();
|
||||
}
|
||||
|
||||
|
||||
// Den neuen Teilnehmer in die DB eintragen
|
||||
const insertEntry = async () => {
|
||||
let ret = await putToDbase({cmd: 'INSERT_TLN', data: aktualTln})
|
||||
sendConfirmation(false);
|
||||
}
|
||||
|
||||
|
||||
// Den Teilnehmer mit der ID id aus der DB löschen
|
||||
const deleteEntry = async (id) => {
|
||||
let ret = await putToDbase({cmd: 'DELETE_TLN', id:id});
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// Den Teilnehmer mit der ID id mit den neuen Daten versorgen
|
||||
const updateEntry = async (id) => {
|
||||
let ret = await putToDbase({cmd: 'UPDATE_TLN', data: aktualTln, id: id })
|
||||
sendConfirmation(false);
|
||||
}
|
||||
|
||||
|
||||
// Dialogbox für 'doppelt eingetragen'
|
||||
$("#dialogdoppelt").dialog({
|
||||
dialogClass: 'no-close',
|
||||
autoOpen: false,
|
||||
closeOnEscape: false,
|
||||
width: 700,
|
||||
modal: true,
|
||||
position: 'center',
|
||||
title: 'Doppelter Eintrag',
|
||||
open: () => {
|
||||
showdoppelText();
|
||||
},
|
||||
buttons: [
|
||||
{
|
||||
text: 'Auswahl übernehmen',
|
||||
click: async function() {
|
||||
let gewaehlt = [];
|
||||
$.each($("input[name='dopp']:checked"), function() {
|
||||
gewaehlt.push($(this).val());
|
||||
});
|
||||
let tln = $("#dialogdoppelt").data('fids').otln;
|
||||
if (gewaehlt.length === 1) {
|
||||
if (gewaehlt[0] == "new") {
|
||||
deleteEntry($("#dialogdoppelt").data('fids').otln.id);
|
||||
insertEntry();
|
||||
tln = $("#dialogdoppelt").data('fids').ntln;
|
||||
}
|
||||
} else {
|
||||
insertEntry();
|
||||
tln = $("#dialogdoppelt").data('fids').ntln;
|
||||
}
|
||||
$(this).dialog('close');
|
||||
let meld = await afterDialogtext(tln);
|
||||
$('#mainContent').html(meld);
|
||||
$('#mainContent').css('height','430px');
|
||||
}
|
||||
}
|
||||
]
|
||||
}).prev(".ui-dialog-titlebar").css("background","red");
|
||||
|
||||
|
||||
// Der Eintrag wird jetzt doppelt: dieses melden in einer
|
||||
// kleinen Dialog-Box
|
||||
function showDoppelt(oldone, newone) {
|
||||
$('#dialogdoppelt').data('fids', {otln: oldone, ntln: newone}).dialog('open');
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Text für doppelten Eintrag anzeigen
|
||||
async function showdoppelText() {
|
||||
const ofdate = await fetchFromDbase({
|
||||
cmd: 'GET_ONE_DATE',
|
||||
fid: $("#dialogdoppelt").data('fids').otln.fid
|
||||
});
|
||||
const nfdate = await fetchFromDbase({
|
||||
cmd: 'GET_ONE_DATE',
|
||||
fid: $("#dialogdoppelt").data('fids').ntln.fid
|
||||
});
|
||||
$('#dialogdoppelttext').html('Sie haben sich doppelt eingetragen.<br />' +
|
||||
'Wenn das so gewollt ist, dann kreuzen Sie bitte unten beide Führungen an,<br />' +
|
||||
'andernfalls nur diejenige, an der Sie wirklich teilnehmen wollen.<br /> <br />' +
|
||||
'<input type="checkbox" name="dopp" value="new" checked style="margin-right:10px;">' +
|
||||
bauDate(nfdate.wtag, nfdate.datum, nfdate.uhrzeit) + '<br />' +
|
||||
'<input type="checkbox" value="old" name="dopp" style="margin-right:10px;">' +
|
||||
bauDate(ofdate.wtag, ofdate.datum, ofdate.uhrzeit) + '<br />');
|
||||
}
|
||||
|
||||
const errnum = {'no':1, 'error':2, 'double':3};
|
||||
|
||||
|
||||
// Alle Einträge auf Plausibilität prüfen
|
||||
// Return:
|
||||
// Object mit:
|
||||
// error: 'true', 'false'
|
||||
// action: 'store', 'exit', 'none'
|
||||
async function checkPlausibilität() {
|
||||
let error = false;
|
||||
// Zuerst prüfen, ob auch alle notwendigen Felder ausgefüllt sind
|
||||
for (let feld in aktualTln) {
|
||||
aktualTln[feld] = $('#' + feld).val(); // Feld des actualTln auf dem Wert setzen
|
||||
if (!mandatory[feld]) {
|
||||
continue;
|
||||
}
|
||||
if (aktualTln[feld] == "") { // Falls das Feld leer ist, den Rahmen
|
||||
$('#' + feld).css('border-color', 'red'); // rot machen und das
|
||||
error = true; // errorfralg setzen
|
||||
}
|
||||
}
|
||||
if (error) { // wenn Error, dieses melden
|
||||
errtext = "Bitte korrigieren Sie die fehlenden Einträge in den rot umrandeten Feldern";
|
||||
return errnum.error; // und raus
|
||||
}
|
||||
// Als Nächstes die PLZ prüfen: Das müssen 5 Ziffern sein
|
||||
const plz = $('#plz').val();
|
||||
let re = RegExp(/^[0-9]{5}$/);
|
||||
if(!re.test(plz)) {
|
||||
$('#plz').css('border-color', 'red');
|
||||
errtext = "Bitte geben Sie bei der Postleitzahl mindestens fünf Ziffern und keine Buchstaben ein";
|
||||
return errnum.error; // und raus
|
||||
}
|
||||
// Die Email prüfen
|
||||
re = RegExp(/^[a-z0-9]+([-_\.]?[a-z0-9])+@[a-z0-9]+([-_\.]?[a-z0-9])+\.[a-z]{2,4}/);
|
||||
let mail = $('#email').val().toLowerCase();
|
||||
if(!re.test(mail)) {
|
||||
$('#email').css('border-color', 'red');
|
||||
errtext = "Bitte geben Sie eine gültige E-Mail-Adresse ein";
|
||||
return errnum.error; // und raus
|
||||
}
|
||||
// Nun noch doppelte Einträge checken
|
||||
// dazu prüfen, ob die email_Adresse in den Teilnehmern schon enthalten ist
|
||||
const aktMail = aktualTln.email;
|
||||
let allParticipants = await fetchAlleTln();
|
||||
const find = allParticipants.findIndex((f) => f.email === aktMail);
|
||||
if (find == -1) {
|
||||
insertEntry();
|
||||
return errnum.no;
|
||||
}
|
||||
let oldTln = allParticipants[find];
|
||||
// Email enthalten. Ist der Führungstag identisch? Wenn ja, dann einfach die neuen
|
||||
// Werte eintragen (also überschreiben)
|
||||
if (aktualTln.fid === oldTln.fid) {
|
||||
updateEntry(oldTln.id);
|
||||
return errnum.no;
|
||||
} else {
|
||||
// Hier nun 'Doppelt' melden
|
||||
showDoppelt(oldTln, aktualTln);
|
||||
return errnum.double;
|
||||
}
|
||||
return errnum.no;
|
||||
}
|
||||
|
||||
|
||||
// Text für den Dialog der Anmeldung
|
||||
const afterDialogtext = async(tln) => {
|
||||
let fdate = await getfdateformatted(tln.fid);
|
||||
return '<p>Vielen Dank für Ihre Anmeldung. <br /><br />' +
|
||||
'Wir freuen uns über Ihren Besuch auf der Sternwarte Welzheim am<br /> ' +
|
||||
'<div id="antwort_fdatum" style="text-align:center;">' +
|
||||
`${fdate} mit ${tln.anzahl} ${tln.anzahl == 1 ? "Person" : "Personen"}` +
|
||||
'</div> <br />' +
|
||||
'Wir haben Ihnen die Anmelde-Bestätigung per Email zugesandt.</p>' +
|
||||
'<p><a class="button" href="/index.php">Zurück</a></p>';
|
||||
}
|
||||
|
||||
|
||||
// Formular ist ausgefüllt - der Anmelde-Knopf wurde gerdückt.
|
||||
// Alle Eingaben in den aktuelTln eintragen und dann
|
||||
// eine Plausibilitäts-Prüfung durchführen und wenn Alles
|
||||
// OK ist, die Einträge in die Datenbank schreiben
|
||||
$('input[name="submit"]').click(async () => {
|
||||
$('#errordiv').css('visibility','hidden'); // erst mal die evtl. vorhandenen Fehlermeldung
|
||||
for ( let f in aktualTln) { // löschen und alle Rahmen
|
||||
$('#'+f).css('border-color','black'); // wieder schwarz machen
|
||||
}
|
||||
let nr = $('#fid').find(':selected');
|
||||
aktualTln.fid = nr[0].value; // selektiertes Führungsdatum merken
|
||||
const ret = await checkPlausibilität();
|
||||
if (ret === errnum.error) {
|
||||
$('#errordiv').html(errtext);
|
||||
$('#errordiv').css('visibility', 'visible');
|
||||
} else if (ret === errnum.no) {
|
||||
let meld = await afterDialogtext(aktualTln);
|
||||
$('#mainContent').html(meld);
|
||||
$('#mainContent').css('height','430px');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Storno
|
||||
// Der Link für die Stornierung wurde aufgerufen:
|
||||
// Zuerst die email-Adresse suchen (mit Hilfe des übergebenen md5-hash),
|
||||
// dann die Stornierung anzeigen und dann noch eine Bestätigung senden
|
||||
const doStorno = async(md5hash) => {
|
||||
let emails = await fetchFromDbase({cmd:'GET_ALL_EMAILS'});
|
||||
for (let em of emails) {
|
||||
if(md5((em.email+em.fid)) == md5hash) {
|
||||
// komplette Info dieses teilnehmers holen
|
||||
let teilnehmer = await fetchFromDbase({cmd: 'GET_TEILN', id: em.id, isid: true});
|
||||
aktualTln = Object.assign({}, teilnehmer[0]);
|
||||
// Löschen des Eintrages
|
||||
let ret = putToDbase({cmd:'DELETE_TLN', id: em.id});
|
||||
// Meldung anzeigen
|
||||
let fdate = await getfdateformatted(em.fid);
|
||||
let meld = '<p><h1 style="text-align:center">Stornierung</h1><br />' +
|
||||
'Ihre Anmeldung für die Führung auf der Sternwarte Welzheim am<br /><br />' +
|
||||
'<div id="antwort_fdatum" style="text-align:center;">' +
|
||||
`${fdate} mit ${aktualTln.anzahl} ${aktualTln.anzahl == 1 ? "Person" : "Personen"}` +
|
||||
'</div> <br />' +
|
||||
'wurde storniert.<br /><br /> Wir haben Ihnen die Stornierungs-Bestätigung per Email zugesandt.</p>' +
|
||||
'<p><a class="button" href="/index.php">Zurück</a></p>';
|
||||
$('#mainContent').html(meld);
|
||||
$('#mainContent').css('height','430px');
|
||||
sendConfirmation(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Alle eingetragenen Teilnehmer ab 'morgen' in das globale Array einlesen
|
||||
const fetchAlleTln = async () => {
|
||||
const nxtDate = await fetchFromDbase({cmd: 'GET_DATES', anzahl: 1, fid:0});
|
||||
return await fetchFromDbase({cmd: 'GET_ALLTEILN', fid: nxtDate[0].fid});
|
||||
}
|
||||
|
||||
|
||||
async function main() {
|
||||
// Falls Storno angefordert, dann anzeigen
|
||||
if(md5Hash != "") {
|
||||
await doStorno(md5Hash);
|
||||
return;
|
||||
}
|
||||
// Alle eingetragenen Teilnehmer ab 'morgen' in das globale Array einlesen
|
||||
// die nächste 30 Führungsdaten anzeigen
|
||||
buildfuehrungdates(30);
|
||||
}
|
||||
|
||||
main().catch(console.err);
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user