Compare commits

...

13 Commits

Author SHA1 Message Date
rxf
75a6988248 Führungsdaten bei den Anmeldunge bis 14.11. blockiert
dosendmail mit gmx und logdatei
Sondermeldung in rot
2025-10-22 15:08:49 +02:00
rxf
e42d9c9b32 anmeld.js: Fehlermeldung, wenn mail nich gesendet wurde 2025-10-20 11:10:36 +02:00
rxf
53decbc96b php_sendmail jetzt vie GMX
amnled.js mit Datum
2025-10-17 15:36:12 +02:00
rxf
45b76cf1b2 GO mit Führungsterminen angepasst 2025-10-01 15:25:14 +02:00
rxf
4214f48e34 Laufschrift nur bei regulärer Führung einschalten 2025-09-07 09:07:59 +02:00
rxf
2d5595a245 V 1.7.3 Laufschrift wieder dazu 2025-09-06 22:09:58 +02:00
rxf
53f9929c30 version angepasst 2025-07-27 17:01:41 +02:00
rxf
d5251ada3a console ausgabe beim Senden der Mail 2025-07-27 17:00:12 +02:00
rxf
d51aa4a6c8 statt Moment nun luxon verwendet 2025-07-27 13:46:34 +02:00
rxf
7300a46cb2 Tabelle auf 10% von links, Besucherzahl auch bei schmalen Display dazu 2025-07-27 12:53:35 +02:00
rxf
7ad7b34aa9 IsSMallScreen als globale Variable 2025-07-27 12:06:56 +02:00
rxf
61fd8e7a62 sonnenf entfert, anmeld.php -> index.php, Aufruf auf der internen Seite angepasst 2025-07-21 15:06:08 +02:00
rxf
b7a65765ea Funktion sendmymail in anmeldDB.php entfernt 2025-07-21 11:04:29 +02:00
27 changed files with 500 additions and 1203 deletions

22
GO/fuehrungstermine/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,22 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch file",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${file}"
},
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}"
}
]
}

View File

@@ -0,0 +1,8 @@
module rexfue.de/fuehrungstermine
go 1.16
require (
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/wlbr/feiertage v1.10.0 // indirect
)

View File

@@ -0,0 +1,4 @@
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/wlbr/feiertage v1.10.0 h1:Nx+KPuj8bNNJOzgRKb0GD4K8tkdxxej4BhkzRiXrbEA=
github.com/wlbr/feiertage v1.10.0/go.mod h1:wJOHvMa6sI5L1FkrTOX/GSoO0hpK3S2YqGLPi8Q84I0=

167
GO/fuehrungstermine/main.go Normal file
View File

@@ -0,0 +1,167 @@
package main
import (
"database/sql"
"flag"
"fmt"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/wlbr/feiertage"
)
var samstag = []string{"Sa A", "Sa B", "Sa C"}
var montag = []string{"Mo I", "Mo II"}
var mittwoch = []string{"Mi I", "Mi II"}
var sams int
var mont int
var mitt int
func bumpgroup(wd int) string {
grp := ""
switch wd {
case 6:
grp = samstag[sams]
sams = sams + 1
if sams == 3 {
sams = 0;
}
case 1:
grp = montag[mont]
mont = mont + 1
if mont == 2 {
mont = 0;
}
case 3:
grp = mittwoch[mitt]
mitt = mitt + 1
if mitt == 2 {
mitt = 0
}
}
return grp
}
func printDate (d time.Time, db *sql.DB, ft []feiertage.Feiertag, grp string, store bool) {
zeiten := [13]int{0,20,20,20,21,22,22,22,22,21,20,20,20}
wdays := [7]string{"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"}
year, month, day := d.Date()
wd := int(d.Weekday())
zt := zeiten[month]
// fmt.Printf("%v-%02d-%02d %9v %v Uhr\n", year, int(month), day, wdays[int(wd)], zt)
if Contains(ft, d) || d.Equal(time.Date(year, 12, 31, 0, 0, 0, 0, time.Local)) || d.Equal(time.Date(year, 12, 24, 0, 0, 0, 0, time.Local)) {
fmt.Println("********* Feiertag")
return
}
query := fmt.Sprintf("INSERT INTO fdatum1 (wtag, datum, uhrzeit, grp, count) VALUES ('%v', %v%02d%02d, '%v Uhr', '%v', 0)",
wdays[int(wd)], year, int(month), day, zt, grp)
fmt.Println(query)
if store {
insert, err := db.Query(query)
if err != nil {
panic(err.Error())
}
insert.Close()
}
}
func createDates(year int, db *sql.DB, ft []feiertage.Feiertag, doStore bool) {
d := time.Date(year, 1, 1, 0, 0, 0, 0, time.Local)
for i := 1; i< 366; i++ {
wd := int(d.Weekday())
grp := bumpgroup(wd)
if d.Month() <= 4 || d.Month() >=9 {
if wd == 1 || wd == 3 {
printDate(d, db, ft, grp, doStore);
}
}
if wd == 6 {
printDate(d, db, ft, grp, doStore)
}
d = d.AddDate(0,0,1)
if d.Year() > year {
break;
}
}
}
// Contains tells whether a contains x.
func Contains(a []feiertage.Feiertag, x time.Time) bool {
for _, n := range a {
if x.Equal(n.Time) {
return true
}
}
return false
}
func sendAllOff() {
var storeit bool
yearPtr := flag.Int("year", 2026, "Für das Jahr 'year' berechnen")
samPtr := flag.String("sams", "Sa A", "Start für Samstag (möglich: Sa A, Sa B, Sa C)")
monPtr := flag.String("mont", "Mo I", "Start für Montag (möglich: Mo I, Mo II)")
mitPtr := flag.String("mitt", "Mi I", "Start für Mittwoch (möglich: Mi I, Mi II)")
flag.BoolVar(&storeit, "store", false, "in der DB speichern?")
flag.Parse()
fmt.Println("year:", *yearPtr)
fmt.Println("samstag:", *samPtr)
fmt.Println("montag:", *monPtr)
fmt.Println("mittwoch:", *mitPtr)
fmt.Println("store:", storeit)
switch *samPtr {
case "Sa A":
sams = 0
case "Sa B":
sams = 1
default:
sams = 2
}
if *monPtr == "Mo I" {
mont = 0
} else {
mont = 1
}
if *mitPtr == "Mi I" {
mitt = 0
} else {
mitt = 1
}
feiertage.SetDefaultTimeZone(time.Local)
ft := feiertage.BadenWürttemberg(*yearPtr)
fmt.Println(ft)
db, err := sql.Open("mysql", "root:SFluorit@tcp(127.0.0.1:3306)/sternwarte")
if err != nil {
panic(err.Error())
}
db.SetConnMaxLifetime(time.Minute * 3)
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(10)
defer db.Close()
createDates(*yearPtr, db, ft.Feiertage, storeit)
}
func main() {
sendAllOff()
}

View File

@@ -0,0 +1 @@
package fdates

View File

@@ -0,0 +1,5 @@
module rexfue.de/fdates
go 1.16
require github.com/go-sql-driver/mysql v1.6.0

View File

@@ -0,0 +1,2 @@
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=

View File

@@ -0,0 +1,77 @@
package sendAllOff
import (
"database/sql"
"fmt"
"strconv"
"strings"
"time"
_ "github.com/go-sql-driver/mysql"
)
/*
* Tag... - a very simple struct
*/
type Tag struct {
datetime string `json:"datetime"`
}
func sendAllOff() {
fmt.Println("Go MySQL Tutorial")
// Open up our database connection.
// I've set up a database on my local machine using phpmyadmin.
// The database is called testDb
db, err := sql.Open("mysql", "root:SFluorit@tcp(127.0.0.1:3306)/sternwarte")
// if there is an error opening the connection, handle it
if err != nil {
panic(err.Error())
}
db.SetConnMaxLifetime(time.Minute * 3)
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(10)
// defer the close till after the sendAllOff function has finished
// executing
defer db.Close()
// Execute the query
results, err := db.Query("SELECT datetime FROM fdates")
if err != nil {
panic(err.Error()) // proper error handling instead of panic in your app
}
for results.Next() {
var tag Tag
// for each row, scan the result into our tag composite object
err = results.Scan(&tag.datetime)
if err != nil {
panic(err.Error()) // proper error handling instead of panic in your app
}
// datetime in das datum von fdatum umwandeln
str := strings.Replace(tag.datetime[0:10], "-", "", -1)
fmt.Println(str)
// einen int draus machen
i, err := strconv.Atoi(str)
if err != nil {
// handle error
fmt.Println(err)
}
// Update-query erzeugen
query := fmt.Sprintf("UPDATE fdates SET datum='%d' WHERE datetime='%s'", i, tag.datetime)
// update ausführen
update, err := db.Query(query)
// if there is an error inserting, handle it
if err != nil {
panic(err.Error())
}
// be careful deferring Queries if you are using transactions
update.Close()
}
}

View File

@@ -93,6 +93,7 @@
$enddatum = new DateTime('now');
$enddatum->modify($monthstoadd);
$enddatum = $enddatum->format('Ymd');
$datum_heute = 20251114; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$sql_sel = "SELECT * FROM fdatum1 where datum >='$datum_heute' && datum <= '$enddatum' order by datum ASC";
$result = mysqli_query($db, $sql_sel) or die(mysqli_error($db));
while ($row = mysqli_fetch_assoc($result)) {
@@ -381,12 +382,17 @@
erhalten Sie eine Anmeldebestätigung per e-mail. Diese bitte unbedingt zur Führung
ausgedruckt oder in digitaler Form mitbringen!
<div style="text-align:center;"><strong>Ohne die mitgebrachte Anmeldebestätigung erfolgt
<!-- <div style="text-align:center;"><strong>Ohne die mitgebrachte Anmeldebestätigung erfolgt
k e i n Einlass.</strong></div>
-->
</p>
<p>
<?PHP echo $stern_error_msg ?>
</p>
<p class="sondermeldung">
Unsere Sternwarte bleibt bis voraussichtlich 14. November 2025 wegen neuer technischer Einrichtung
geschlossen. <br />Bis dahin können keine Führungen durchgeführt werden.
</p>
<strong>Anmeldung:</strong>
<span class="textklein">(Alle Felder mit '*' müssen ausgefüllt werden)</span><br />
<br />
@@ -478,7 +484,7 @@
<p>
Hinweis zum Datenschutz: <a href="" id="dschu">Datenschutzerklärung</a>
</p>
<p class="lastchange">Letzte Änderungen: 2024-05-22 rxf</p>
<p class="lastchange">Letzte Änderungen: 2025-10-22 rxf</p>
</form>
</div>

View File

@@ -465,4 +465,12 @@ textarea {
#maxpro {
margin-left: 20px;
}
.sondermeldung {
font-weight: bold;
border: 2px rgb(229, 162, 61) solid;
color: red;
padding: 5px;
width: 90%;
}

View File

@@ -10,7 +10,7 @@ body {
#container, #names {
max-width: 800px;
width: 95%;
width: 90%;
margin: 20px auto;
padding: 16px;
border: 2px solid #333;
@@ -33,7 +33,7 @@ h5 {
font-size: 1rem;
border: 1px solid #aaa;
border-radius: 4px;
width: 60%;
width: 65%;
max-width: 100%;
box-sizing: border-box;
background-color: #fff;
@@ -66,6 +66,10 @@ h5 {
margin-top: 1em;
}
#tabAnmeld {
margin-left: 10%;
}
#tabAnmeld, #tnames {
width: 100%;
border-collapse: collapse;

View File

@@ -1,6 +1,7 @@
der aktuellen Wetterlage
technischer Probleme
einer hereinziehenden Wolkenfront
Erkrankung des Führungspersonals
Verhinderung durch Verkehrsprobleme
anderer unvorhersehbarer Ereignisse
der Erkrankung des Führungspersonals
einer Verhinderung durch Verkehrsprobleme
unvorhersehbarer Ereignisse
der Erneuerung unserer Technik

View File

@@ -63,6 +63,14 @@ if ($typ == 'regular') {
</div>
</dialog>
<!-- Error Dialog -->
<dialog id="errordialog">
<p id="errortext"></p>
<div id="errorbutton">
<button id="errordialog-ok">OK</button>
</div>
</dialog>
<!-- Info unter Tabelle -->
<div id="author">
<div>
@@ -74,7 +82,7 @@ if ($typ == 'regular') {
</div>
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.4/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luxon@3.7.1/build/global/luxon.min.js"></script>
<script src="js/version.js" defer></script>
<script src="js/anmeld.js" defer></script>

View File

@@ -17,29 +17,32 @@ document.addEventListener('DOMContentLoaded', async () => {
typ: urlParams.get('typ') || 'regular',
storno: urlParams.get('storno') === 'true',
double: urlParams.get('double') === 'true',
name: urlParams.get('name') || 'Null'
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: `Absage der heutigen ${fuehrung}`,
bodytext: `Sehr geehrte Dame, sehr geehrter Herr,
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 heutigen ${fuehrung} angemeldet.
Aufgrund {absagegrund} können wir heute keine Sternführung anbieten.
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`,
Beobachtergruppe Sternwarte Welzheim`
,
};
const liste = {
@@ -49,6 +52,9 @@ Beobachtergruppe Sternwarte Welzheim`,
let abgesagt = false;
let actualdate;
let isSmallScreen = false
let DateTime = luxon.DateTime
function $(selector) {
return document.querySelector(selector);
@@ -121,6 +127,7 @@ Beobachtergruppe Sternwarte Welzheim`,
}
async function showAktAnmeldungen(date) {
actualdate = date;
liste.emails = [];
@@ -169,6 +176,8 @@ Beobachtergruppe Sternwarte Welzheim`,
}
if (abgesagt) {
$('#absagen').innerHTML = 'Absage<br />wurde gesendet';
} else {
$('#absagen').innerHTML = 'Absage senden';
}
if (besucher !== 0) {
@@ -184,6 +193,9 @@ Beobachtergruppe Sternwarte Welzheim`,
}
$('#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) {
@@ -204,7 +216,7 @@ Beobachtergruppe Sternwarte Welzheim`,
<tr>
<td class="tdname col-6">${x.name} ${x.vorname}</td>
<td class="col-2">${x.anzahl}</td>
<td class="col-2">${moment(x.fdatum).format('YYYY-MM-DD')}</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>`);
}
@@ -257,15 +269,25 @@ Beobachtergruppe Sternwarte Welzheim`,
await storeAbsage(liste.ids);
const bodyText = TEXTE.bodytext.replace("{absagegrund}", absagegrund);
await fetchFromDbase({
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: TEXTE.subject,
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();
});
@@ -312,7 +334,7 @@ Beobachtergruppe Sternwarte Welzheim`,
<th class="col-2">Name</th>
<th class="col-2">Vorname</th>
<th class="col-3">Email</th>
<th class="col-1">Anzahl</th>
<th class="col-1">Anz</th>
<th class="col-2">Datum</th>
<th class="col-2">Anmeldung</th>
</tr></thead><tbody>`);
@@ -325,8 +347,8 @@ Beobachtergruppe Sternwarte Welzheim`,
<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">${moment(x.fdatum).format('YYYY-MM-DD')}</td>
<td class="col-2">${moment(x.angemeldet).format('YYYY-MM-DD')}</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>`);
}
@@ -334,7 +356,7 @@ Beobachtergruppe Sternwarte Welzheim`,
$('#names').style.display = 'block';
}
function switchText(isSmallScreen) {
function switchText() {
const thead = document.createElement('thead');
const row = document.createElement('tr');
let column = query.storno ? "col-2" : "col-3"
@@ -377,12 +399,12 @@ Beobachtergruppe Sternwarte Welzheim`,
let summ = 0;
let select = `<select name='ftermin' id='ftermin'>`;
let selectedNext = false;
const today = moment().startOf('day');
const today = DateTime.now().startOf('day');
for (let d of dates) {
let isselected = "";
const fday = moment(d.datum);
if (!selectedNext && fday.isSameOrAfter(today)) {
const fday = DateTime.fromISO(d.datum);
if (!selectedNext && (isSameorAfter = fday >= today)) {
selectedNext = true;
isselected = "selected";
n = i;
@@ -393,13 +415,18 @@ Beobachtergruppe Sternwarte Welzheim`,
let grpstr
if (query.typ == 'regular') {
datstr = bauDate(d.wtag, d.datum, d.uhrzeit)
grpstr = `(${d.grp})`
grpstr = `(${d.grp})`
} else {
datstr = bauDate('So', d.datum, '11')
grpstr = "&nbsp;"
}
select += `
<option value="${d.datum}" ${isselected} ${isFuehrung}> ${datstr} ${grpstr} ${count || 0} Besucher</option>`;
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;
@@ -412,7 +439,7 @@ Beobachtergruppe Sternwarte Welzheim`,
$('#ftermin').addEventListener('change', async () => {
const date = $('#ftermin').value;
const index = $('#ftermin').selectedIndex;
setVisibility('#absagen', index === 0);
setVisibility('#absagen', index === 0 || useDatum);
await showAktAnmeldungen(date);
});
@@ -420,25 +447,29 @@ Beobachtergruppe Sternwarte Welzheim`,
}
async function main(n) {
const today = moment().subtract(14, 'days').format("YYYYMMDD");
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});
const index = await buildFuehrungsDates(dates, last);
let mq = window.matchMedia('(max-width: 800px)');
switchText(mq.matches);
mq.addEventListener('change', (e) => {
switchText(e.matches);
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(today);
await showDoubles(DateTime.now().toFormat("yyyyLLdd"));
}
}

View File

@@ -1,16 +1,39 @@
// VersiosNummern und -Geschichte
const VERSION="1.7.0";
const VDATE="2025-07-07";
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 textDate data/absagegruende.txt
- Absagegrund liegt in der textDatei data/absagegruende.txt
1.63 2024-02-20 rxf
- Erkennung von Dubletten verbessert
@@ -19,7 +42,7 @@ Rev. Datum Entwickler
- Laufschrift einschalten, wenn Absage gesendet wird
1.61 2023-10-04 rxf
- Anzeiger der teilnehmer-Datails funktioniert wieder
- Anzeiger der Teilnehmer-Datails funktioniert wieder
1.60 2022-10-15 rxf
- Probleme mit der Besucheranzahl gelöst (Anzahl IMMER aus der DB holen)

View File

@@ -249,41 +249,6 @@ function deleteOne($id) {
return $result;
}
function findDoubles($dat) {
global $db, $table;
$sql_stmt = "SELECT * FROM $table INNER JOIN (SELECT vorname,name FROM $table " .
"GROUP BY vorname,name HAVING COUNT(id) > 1 ) dup ON $table.name = dup.name && $table.vorname = dup.vorname";
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
while ($row = mysqli_fetch_assoc($result)) {
foreach ($row as $key => $value) {
$entry[$key] = $value;
}
$erg[] = $entry;
}
return $erg;
}
function sendmymail($to, $betreff, $body, $bcc)
{
$absender = "noreply@sternwarte-welzheim.de";
$lst = "";
foreach($bcc as $b) {
$lst = $lst . trim($b) . ',';
}
$lst = substr($lst,0,-1);
$headers = array();
$headers[] = "MIME-Version: 1.0";
$headers[] = "Content-type: text/plain; charset=utf-8";
$headers[] = "From: {$absender}";
$headers[] = "X-Mailer: PHP/" . phpversion();
$headers[] = "Reply-To: {$absender}";
$headers[] = "Bcc: {$lst}" . ",rxf@fuerst-stuttgart.de";
mail($to, $betreff, $body, implode("\r\n", $headers), "-f noreply@sternwarte-welzheim.de");
return "OK";
}
$_POST = json_decode(file_get_contents('php://input'), true);
@@ -358,11 +323,7 @@ switch ($cmd) {
$erg = deleteOne($_POST['id']);
break;
case 'DOUBLE':
$erg = findDoubles($_POST['date']);
break;
case 'SENDMYMAIL':
case 'SENDMYMAIL':
$erg = sendmail($_POST['betreff'], $defaultabsender, $_POST['body'], [], $_POST['bcc'], $_POST['to']);
break;
}

View File

@@ -50,8 +50,8 @@
<p><a href="sofue/sofue.php">Sonderf&uuml;hrungen &Uuml;bersicht</a></p>
<p><a href="statistik">Statistik</a></p>
<p><a href="laufschrift.html">Laufschrift</a></p>
<p><a href="anmeld/anmeld.php">Liste der angemeldeten Besucher</a></p>
<p><a href="sonnenf/sonnenf.php">Liste der Anmeldungen für die Sonnenführungen</a></p>
<p><a href="anmeld/index.php">Liste der angemeldeten Besucher</a></p>
<p><a href="anmeld/index.php?typ=sonnen">Liste der Anmeldungen für die Sonnenführungen</a></p>
<p><strong>Download</strong></p>
<blockquote>
<p><a href="ausgabebeoprotokolle.php">Archiv Beoprotokolle</a></p>

File diff suppressed because one or more lines are too long

View File

@@ -1,93 +0,0 @@
@CHARSET "UTF-8";
body {
font-family: Arial, Verdana, Helevetica, sans-serif;
font-size: 80%;
position:relative;
margin: 3px 0 3px 0;
padding: 0;
background-color: #FFFFDD;
}
#container, #names {
max-width: 800px;
width: 95%;
height: 100%;
margin: 5px auto;
border: solid 2px black;
background: #EEEEEE;
}
h3 {
margin-top: 10px;
}
h5 {
font-weight: bold;
}
#auswahl {
margin-top: 15px;
}
#gesamtsumme {
margin-top: 5px;
font-size: 85%;
}
#author {
font-size:90%;
margin: auto;
padding-bottom: 8px;
margin-top: 8px;
}
#tabAnmeld, #tnames {
margin: auto;
border-collapse: collapse;
}
#tnames {
margin-top: 10px;
margin-bottom: 10px;
}
#names {
display: none;
}
#absagedialog {
text-align: center;
}
#absagen, #uebernehmen {
width: 100%;
}
.det {
border: 1px solid black;
padding-left: 10px;
width: 100%;
}
.ui-dialog {
max-width: 800px !important;
width: 80% !important;
}
.findit {
box-shadow: none;
height: 20px;
width: 20px;
border-radius: 10px;
margin-right: 5px;
}
#anmeldung {
font-weight: bold;
}
#nixda {
color: red;
padding-bottom: 15px;
}

View File

@@ -1,512 +0,0 @@
// sofianmeld.js rxf 2020-09-21
// Anmeldungen anzeigen und abhaken lassen
//
function getAuthorisation(was) {
let x = was.split(',')
return { storno: x[0], name: x[1] , double: x[2]}
}
$(document).ready(() => {
// Globale Konstanten und Variable
const ajaxURL="php/sonnenfDB.php";
const ANZAHL_DATES = 12;
const TEXTE = {
absagetext: "Absage an alle angemeldeten Besucher senden?",
schonabgesagt: "Absage schon gesendet. Nochmal senden?",
eingetragen: 'Besucher erfolgreich eingetragen.',
subject: 'Absage der heutigen Sonnenführung',
bodytext: `Sehr geehrte Dame, sehr geehrter Herr,
Sie haben sich über unsere Webseite www.sternwarte-welzheim.de zur heutigen Sonnenführung angemeldet.
Aufgrund der aktuellen Wetterlage können wir heute keine Sonnenfü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;
// 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();
}
// Aktuelle Anmeldungen anzeigen:
// Für den ausgewählten Führungstag (date) die Anmeldungen aus der
// Datenbank holen und in die Tabelle einbauen
// Außerdem die globale Variable 'emails' mit den emails der Teilnehmer füllen
const showAktAnmeldungen = async (date) => {
actualdate = date;
let auth = params.storno == 'true'
let column = auth ? "col-2" : "col-6"
liste.emails = [];
liste.ids = [];
abgesagt = false;
console.log('date: ', date);
let anmeldungen = await fetchFromDbase({cmd:'GET_ANMELD',id:date});
let besucher = 0;
$('tbody').empty();
for (let e of anmeldungen) {
besucher += parseInt(e.anzahl);
liste.emails.push(e.email);
liste.ids.push(e.id);
if (e.abgesagt == '1') {
abgesagt = true;
$('#absagen').html('Absage<br />wurde gesendet');
}
// const selected = e.teilgenommen == "1" ? "checked" : "";
let str = `<tr class="d-flex">
<td class="tdname col-6">${e.name} ${e.vorname}</td>
<td class=${column}>${e.anzahl}</td>`
// <td class=${column}><input type="checkbox" value="${e.id}" ${selected}></td>`
if (auth) {
str += `<td class="tdstorno col-2"><input type="checkbox" value="${e.id}"></td>`
}
str += '</tr>'
$('#tabAnmeld > tbody:last-child').append(str);
}
if(besucher != 0) {
let str = `<tr id="summe" class="d-flex">
<td class="col-6">Summe der Anmeldungen</td>
<td class="col-6">${besucher}</td>`
$('#tabAnmeld > tbody:last-child').append(str);
}
// Klick auf den Namen: Detail-Dialog öffnen
$('.tdname').click( function() {
const row = $(this).closest("tr") // Finds the closest row <tr>
const index = (row[0].rowIndex)-1
$('#detail').data('id',anmeldungen[index].id).dialog('open');
})
// Klick auf 'storno' : den Eintrag stornieren
$('.tdstorno').click( function() {
const row = $(this).closest("tr") // Finds the closest row <tr>
const index = (row[0].rowIndex)-1
austragen(anmeldungen[index]) // Teilnehmer austragen
})
}
// 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;
}
// Führungsdaten in einer Select-Auswahl anzeigen
// Zusätzlich den Eventhandler für die Auswahl registrieren.
// Params:
// dates -> Array mit den geholten Führungsdaten
const buildFuehrungsDates = async (dates, last) => {
let n = 0;
let i = 0;
let summ = 0;
let select =
// <label for='ftermin' class='col-8 col-form-label'>
// <strong>Führung am</strong></label>
`<select name='ftermin' id='ftermin' >`;
let selectedNext = false;
const today = moment().startOf('day');
for (let d of dates) {
let isselected = "";
const fday = moment(d.datum);
if (!selectedNext) {
if (fday.isSameOrAfter(today)) {
selectedNext = true;
isselected = "selected";
n = i;
}
}
const count = await fetchFromDbase({cmd: 'GET_COUNTS', fdate: d.datum})
const isFuehrung = ((count > 0) && (count != null)) ? ' ' : 'disabled';
select += `
<option value=${d.datum} ${isselected} ${isFuehrung}> ${bauDate('So', d.datum, '11')} &nbsp;&nbsp; ${count} Besucher</option>`;
i++;
summ += (count != null) ? parseInt(count) : 0;
if (d.datum >= last) {
break;
}
}
select += `</select>
<div id = "gesamtsumme">Gesamtzahl der Anmeldungen (ab heute): ${summ}</div>`;
$('#auswahl').append(select);
// Eventhandler für Auswahl eines Datums über die SelectBox:
// Anzeigen der Anmeldungen dazu
$('#ftermin').change( async () => {
let x = $('#ftermin').find(':selected');
let date = x[0].value;
console.log('date: ', date);
let index = $('#ftermin').prop('selectedIndex');
if (index == 0) {
$('#absagen').css('visibility', 'visible');
$('#uebernehmen').css('visibility', 'visible');
} else {
$('#absagen').css('visibility', 'hidden');
$('#uebernehmen').css('visibility', 'hidden');
}
await showAktAnmeldungen(date);
});
return n;
}
// Text für die Tabelle abh. von der Schirmbreite umstellen
// Params
// x -> true/false für > oder < 700px
function switchText(x) {
let auth = params.storno == 'true'
console.log("auth: ",auth)
let column = auth ? "col-2" : "col-6"
let thead = `
<thead>
<tr class="d-flex">
<th class="col-6">Name</th>
<th class=${column}>${x ? "Anz" : "Person"}</th>`
// <th class=${column}>${x ? "tlg" : "teilgenommen"}</th>`
if(auth) {
thead += `<th class="col-2">${x ? "sto" : "stornieren"}</thclass>`
}
thead += '</tr></thead><tbody></tbody>'
$('#tabAnmeld').empty()
$('#tabAnmeld').append(thead)
if (x) {
$('#versn').html("V " + VERSION + ' ' + VDATE);
} else {
$('#versn').html("Version: " + VERSION + ' vom ' + VDATE);
}
}
const getEintragetext = () => {
let sel1 = $('input[type=checkbox]:checked').map(function (_, el) {
return $(el).val();
}).get();
return `${sel1.length} ${TEXTE.eingetragen}`;
}
// Für die übergebenen IDs das #abgesagt'-Flag in der DB setzen
const storeAbsage = async (ids) => {
let update = {cmd:'UPDATE', field: 'abgesagt', ids : ids, values: [1]};
let erg1 = await putToDbase(update);
abgesagt = true;
}
// die Daten des angewählten Teilnehmers anzeigen
const getDetailText = async (id) => {
// const nbr = parseInt(id.substr(-3));
const nbr = parseInt(id);
const holit = await fetchFromDbase({cmd:'GET_TEILN_ID',id:nbr});
const entry = holit[0];
const tafel = `
<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>`
return tafel;
}
// 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 Ergenisse: ",erg1)
showAktAnmeldungen(actualdate)
}
// ******************
// Event-Handler
// ******************
// Übernahme der angeklickten 'teilgenommen' Boxen
//
// Jeder Teilnehmer, der hier abgehakt ist, wird in der Datenbank
// als 'teilgenommen' eingetragen, jeder, der NICHT abgehakt ist, wird
// als 'nicht teilgenommen' markiert.
$('#uebernehmen').click(async function() {
let sel1 = $('input[type=checkbox]:checked').map(function(_, el) {
return $(el).val();
}).get();
let sel0 = $('input[type=checkbox]:not(:checked)').map(function(_, el) {
return $(el).val();
}).get();
let update = {cmd:'UPDATE', field: 'teilgenommen', ids : sel1, values: [1]};
let erg1 = await putToDbase(update);
update = {cmd:'UPDATE', field: 'teilgenommen', ids : sel0, values: [0]};
let erg0 = await putToDbase(update);
if (erg0 && erg1) {
$('#eintragedialog').dialog('open');
}
});
// Dialogbox zu Absage aufrufen
$('#absagen').click(()=> {
$('#absagedialog').dialog('open');
})
// ******************
// Dialogboxen
// ******************
// Dialogbox zur Absage
$("#absagedialog").dialog({
autoOpen: false,
modal: true,
position: 'center',
title: 'Absage-Mail',
open: function() {
if (abgesagt) {
$('#absagetext').text(TEXTE.schonabgesagt)
} else {
$('#absagetext').text(TEXTE.absagetext)
}
},
buttons: [
{
text: "Senden",
click : async function() {
await storeAbsage(liste.ids);
await fetch('https://laufschrift.rexfue.de/switch/switch_on')
let erg = await fetchFromDbase({
cmd: 'SENDMYMAIL',
to: ['rexfue@gmail.com'],
betreff: TEXTE.subject,
body: TEXTE.bodytext,
bcc: liste.emails
});
console.log("Mail gesendet");
$('#absagen').html('Absage<br />wurde gesendet');
$(this).dialog("close");
},
},
{
text: "Abbrechen",
click : function() {
$(this).dialog("close");
},
}
],
});
// Dialogbox für das 'eingetragen'
$("#eintragedialog").dialog({
autoOpen: false,
modal: true,
position: 'center',
title: 'Teilnehmer',
open: () => {
$('#eintragetext').text(getEintragetext());
}
});
// Dialogbox mit den genauen Daten des Teilnehmers
$("#detail").dialog({
autoOpen: false,
modal: true,
position: 'top',
title: 'Teilnehmer-Details',
open: () => {
const id = $('#detail').data('id');
getDetailText(id)
.then((txt) => {
$('#detailtext').html(txt);
});
}
});
const filterDoubles = (data) => {
let erg = {}
return erg
}
async function getDoubles(date) {
const update = { cmd: 'DOUBLE', date: date}
let erg = await putToDbase(update)
for (let i = erg.length-1; i>=0; i--) {
if(erg[i].name == 'Donner') {
console.log(erg)
}
if(
((erg[i].name == '-') && (erg[i].vorname == '-'))
|| (erg[i].abgesagt == "1")
|| (erg[i].fdatum <= parseInt(moment().format('YYYYMMDD')))
) {
erg.splice(i, 1)
}
}
erg.sort(function (a,b) {
let na = a.name.toUpperCase()
let nb = b.name.toUpperCase()
if (na < nb) {
return -1
}
if(na > nb) {
return 1
}
return 0
})
console.log(erg)
// alle die, die nur noch 1x drin sind, rausschmeißen
let i
for(i = 0; i < erg.length-1; i++) {
console.log(`${i} Name[${i}]: ${erg[i].name} Name[${i+1}]: ${erg[i+1].name}`)
if(erg[i].name != erg[i+1].name) {
erg[i].single = true
} else {
i++
}
}
erg[i].single = true
return erg
}
const showDoubles = async (date) => {
let erg = await getDoubles(date)
console.log(erg)
$('#tnames').append(
'<thead><tr>' +
' <th class="col-3">Name</th>' +
' <th class="col-3">Email</th>' +
' <th class="col-1">Anzahl</th>' +
' <th class="col-2">Datum</th>' +
' <th class="col-2">Anmeldung</th>' +
' <th class="col-1">Finden</th>' +
'</tr></thead><tbody>')
for(let x of erg) {
if((x.single != undefined) && (x.single == true)) {
continue
}
$('#tnames').append(`<tr>
<td class="tdname col-3">${x.name} ${x.vorname}</td>
<td class="tdname col-3">${x.email}</td>
<td class="col-1">${x.anzahl}</td>
<td class="col-2">${moment(x.fdatum).format('YYYY-MM-DD')}</td>
<td class="col-2" style="color:lightgray;">${moment(x.angemeldet).format('YYYY-MM-DD')}</td>
<td class="tdfind col-1"><input type="checkbox" value="${x.id}"></td>\`
</tr>
`)
}
$('#tnames').append('</tbody')
$('#names').show();
}
async function findName(name) {
const update = { cmd: 'GET_TEILN_NAME', name: name}
let erg = await putToDbase(update)
console.log('Name: ',erg);
$('#tnames').append(
'<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) {
$('#tnames').append(`<tr>
<td class="tdname col-6">${x.name} ${x.vorname}</td>
<td class="col-2">${x.anzahl}</td>
<td class="col-2">${moment(x.fdatum).format('YYYY-MM-DD')}</td>
<td class="tdfind col-2"><button type="button" class="findit btn btn-primary" id="b1" value="${x.id}"></td>\`
</tr>
`)
}
$('#tnames').append('</tbody')
$('#names').show();
// Event für 'find'
$('.findit').click(() => {
let id = $('.findit').val()
$('#detail').data('id',id).dialog('open');
})
}
// *****************************************
// main
// *****************************************
// Hier gehts los:
// Von der Datenbank die nächsten 'n' Führungsdaten holen
// und anzeigen
// Params:
// n -> Anzahl der zu holnden Daten
async function main(n){
// Media Query einbauen:
let x = window.matchMedia("(max-width: 800px)");
switchText(x.matches);
x.addEventListener("change", async (e) => {
switchText(e.matches);
await showAktAnmeldungen(actualdate);
});
let curtime = moment().subtract(2,'months').format("YYYYMMDD");
// let curtime = moment().format("YYYYMMDD");
console.log(curtime)
const y = await fetchFromDbase({cmd:'GET_DATES', anzahl:n, date: curtime});
const last = await fetchFromDbase({cmd:'GET_LASTANMELDUNG', date: curtime});
const sel = await buildFuehrungsDates(y, last);
await showAktAnmeldungen(y[sel].datum);
console.log(y);
if(params.name != 'Null') {
await findName(params.name)
}
if(params.double == 'true') {
await showDoubles(curtime);
}
}
main(ANZAHL_DATES).catch(console.error);
});

View File

@@ -1,12 +0,0 @@
// VersiosNummern und -Geschichte
const VERSION="1.1";
const VDATE="2024-02-11";
/* History
Rev. Datum Entwickler
1.0 2020-10-09 rxf
- Erste Version. Baut auf auf 'inrern/anmeld'
*/

View File

@@ -1,2 +0,0 @@
cmd=GET_DATES
anzahl=10

View File

@@ -1,364 +0,0 @@
<?php
# Hier werden die Anfragen vom Javascript verarbeitet und die
# Datenbank bedient
include '../../../config_stern.php';
include '../../../phpmailer/dosendmail.php';
// Holen der Einträge in der sonne-Datenbank für den selektierten Tag
// Parameter
// $special -> was muss geholt werden
// $date -> Datum, für das geholt wird
//
// Return:
// Array mit den Einträgen
function getAnmeldungenNew($special, $date)
{
global $db;
$retur = [];
$retur['error'] = false;
$retur['errortext'] = '';
$erg = array();
if ($special == 'total') {
$sql_stmt = "SELECT * FROM sonneanmeld";
} else if ($special == 'all') {
$sql_stmt = "SELECT * FROM sonneanmeld WHERE name != '-'";
} else if ($special == 'abgesagt') {
$sql_stmt = "SELECT * FROM sonneanmeld WHERE abgesagt=1 AND name != '-'";
} else if ($special == 'nichtda') {
$sql_stmt = "SELECT * FROM sonneanmeld WHERE DATE_ADD(DATE(sonnedatum),INTERVAL 1 DAY)<=DATE(NOW()) AND teilgenommen = 0 AND name != '-'";
} else if ($special == 'zualt') {
$sql_stmt = "SELECT * FROM sonneanmeld WHERE DATE_ADD(DATE(sonnedatum),INTERVAL $date DAY)<=DATE(NOW()) AND name != '-'";
} else if ($special == 'alllater'){
$sql_stmt = "SELECT * FROM sonneanmeld WHERE sonnedatum > '$date' AND name != '-' ORDER BY sonnedatum";
} else if ($special == 'normal'){
$sql_stmt = "SELECT * FROM sonneanmeld WHERE sonnedatum = '$date'";
} else {
$retur['error'] = 'false';
$retur['errortext'] = 'Falsches SELECT Statement!';
$retur['data'] = [];
return $retur;
}
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
while ($row = mysqli_fetch_assoc($result)) {
foreach($row as $key => $value) {
$entry[$key] = $value;
}
$erg[] = $entry;
}
$retur['data'] = $erg;
return $retur;
}
// Holen der Einträge in der anmelde-Datenbank für den selektierten Tag
// Parameter
// $special -> was muss geholt werden
// $date -> Datum, für das geholt wird
//
// Return:
// Array mit den Einträgen
function getSonderNew($special, $date)
{
global $db;
$retur = [];
$retur['error'] = false;
$retur['errortext'] = '';
$erg = array();
/* if ($special == 'total') {
$sql_stmt = "SELECT * FROM sonneanmeld";
} else if ($special == 'all') {
$sql_stmt = "SELECT * FROM sonneanmeld WHERE name != '-'";
} else if ($special == 'abgesagt') {
$sql_stmt = "SELECT * FROM sonneanmeld WHERE abgesagt=1 AND name != '-'";
} else if ($special == 'nichtda') {
$sql_stmt = "SELECT * FROM sonneanmeld WHERE DATE_ADD(DATE(sonnedatum),INTERVAL 1 DAY)<=DATE(NOW()) AND teilgenommen = 0 AND name != '-'";
} else if ($special == 'zualt') {
$sql_stmt = "SELECT * FROM sonneanmeld WHERE DATE_ADD(DATE(sonnedatum),INTERVAL $date DAY)<=DATE(NOW()) AND name != '-'";
} else
*/ if ($special == 'alllater'){
$sql_stmt = "SELECT * FROM SoFue2 WHERE wtermin > '$date' ORDER BY wtermin";
// } else if ($special == 'normal'){
// $sql_stmt = "SELECT * FROM sonneanmeld WHERE sonnedatum = '$date'";
} else {
$retur['error'] = 'false';
$retur['errortext'] = 'Falsches SELECT Statement!';
$retur['data'] = [];
return $retur;
}
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
while ($row = mysqli_fetch_assoc($result)) {
foreach($row as $key => $value) {
$entry[$key] = $value;
}
$erg[] = $entry;
}
$retur['data'] = $erg;
return $retur;
}
// Holen der Einträge in der anmelde-Datenbank für den selektierten Tag
// Parameter
// $date -> so für dieses Datum die Einträge holen
// Retunrn:
// Array mit den Einträgen
function getAnmeldungen($date)
{
global $db;
$erg = array();
$sql_stmt = "SELECT * FROM sonneanmeld WHERE fdatum = '$date'";
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
while ($row = mysqli_fetch_assoc($result)) {
foreach($row as $key => $value) {
$entry[$key] = $value;
}
$erg[] = $entry;
}
return $erg;
}
// Daten eines Teilnehmers abholen
// Parameter:
// $id: Teilnehmer - ID
// Return:
// Dict mit allen Daten des Teilnehmers
function getTeilnehmer($id)
{
global $db;
$erg = array();
$sql_stmt = "SELECT * FROM sonneanmeld WHERE id='$id'";
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
while ($row = mysqli_fetch_assoc($result)) {
foreach ($row as $key => $value) {
$entry[$key] = $value;
}
$erg[] = $entry;
}
return $erg;
}
// Daten eines Teilnehmers abholen
// Parameter:
// $name: Name oder Vorname des Teilnehmers
// Return:
// Dict mit allen Daten des Teilnehmers
function getTeilnehmerByName($name)
{
global $db;
$erg = array();
$sql_stmt = "SELECT * FROM sonneanmeld WHERE name ='$name' || vorname = '$name'";
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
while ($row = mysqli_fetch_assoc($result)) {
foreach ($row as $key => $value) {
$entry[$key] = $value;
}
$erg[] = $entry;
}
return $erg;
}
// Die Daten der nächsten $soviel Führungen ab dem Datum $ab in ein Array holen
// Parameter
// $soviel -> so viele Einträge ab jetzt holen
// $ab -> Startdatum
// Retunrn:
// Array mit allen Werte aus der Table
function getNextFuehrungen($soviel, $ab) {
global $db;
$erg = array();
// $datum_heute = date("Ymd",strtotime("-1 days"));
$sql_sel = "SELECT * FROM sonnedatum where datum >='$ab' order by datum ASC LIMIT $soviel";
$result = mysqli_query($db, $sql_sel) or die(mysqli_error($db));
while ($row = mysqli_fetch_assoc($result)) {
foreach ($row as $key => $value) {
$entry[$key] = $value;
}
$erg[] = $entry;
}
return $erg;
}
// Das Datum der letzen Anmeldung suchen und übergeben
// Parameter
// $date -> Startdatum
// Retunrn:
// Datum der letzten Anmeldung
function getLastAnmeldung($date) {
global $db;
$erg = array();
// $datum_heute = date("Ymd",strtotime("-1 days"));
$sql_sel = "SELECT MAX(fdatum) AS lastdate FROM sonneanmeld WHERE fdatum >= '$date' and anzahl != 0";
$result = mysqli_query($db, $sql_sel) or die(mysqli_error($db));
$row = mysqli_fetch_row($result);
return $row[0];
}
// Bezeichnung der Gruppe für das übergeben Datum holen
// Parameter:
// $date -> Datum/Zeit (YYY-MM-DD HH:mm:ss), für das die Gruppe geholt werden soll
// Return: Bezeichnung der Gruppe
function getGroup($date) {
global $db;
global $db;
$sql_stmt = "SELECT grp FROM fdates WHERE dateTime = '$date'";
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
$data = mysqli_fetch_assoc($result);
return $data['grp'] ;
}
// Zählen, wieviele Personen zu einem Führungstermin angemeldet sind
// Parameter:
// $fid -> id des Führungsdatum
// Return: Anzahl der Personen
function getCountsPerDate($fdate) {
global $db;
$sql_stmt = "SELECT SUM(anzahl) AS count FROM sonneanmeld WHERE fdatum='$fdate'";
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
$data = mysqli_fetch_assoc($result);
return $data['count'] ;
}
function updateentries($nr,$val,$field)
{
global $db;
$result = false;
for ($i = 0; $i < count($nr); $i++) {
$sql_stmt = "UPDATE sonneanmeld SET $field=$val[0] where id=$nr[$i]";
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
}
return $result;
}
function updateCount($date, $anzahl) {
global $db;
$sql_stmt = "UPDATE sonnedatum SET count=count-$anzahl WHERE datum=$date AND count >0";
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
return $result;
}
function deleteOne($id) {
global $db;
$sql_stmt = "DELETE FROM sonneanmeld WHERE id=$id";
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
return $result;
}
function findDoubles($dat) {
global $db;
$sql_stmt = "SELECT * FROM sonneanmeld INNER JOIN (SELECT vorname,name FROM sonneanmeld " .
"GROUP BY vorname,name HAVING COUNT(id) > 1 ) dup ON sonneanmeld.name = dup.name && sonneanmeld.vorname = dup.vorname";
$result = mysqli_query($db, $sql_stmt) or die(mysqli_error($db));
while ($row = mysqli_fetch_assoc($result)) {
foreach ($row as $key => $value) {
$entry[$key] = $value;
}
$erg[] = $entry;
}
return $erg;
}
function sendmymail($to, $betreff, $body, $bcc)
{
$absender = "noreply@sternwarte-welzheim.de";
$lst = "";
foreach($bcc as $b) {
$lst = $lst . trim($b) . ',';
}
$lst = substr($lst,0,-1);
$headers = array();
$headers[] = "MIME-Version: 1.0";
$headers[] = "Content-type: text/plain; charset=utf-8";
$headers[] = "From: {$absender}";
$headers[] = "X-Mailer: PHP/" . phpversion();
$headers[] = "Reply-To: {$absender}";
$headers[] = "Bcc: {$lst}" . ",rxf@fuerst-stuttgart.de";
mail($to, $betreff, $body, implode("\r\n", $headers), "-f noreply@sternwarte-welzheim.de");
return "OK";
}
$_POST = json_decode(file_get_contents('php://input'), true);
$erg = "";
$cmd = $_POST["cmd"];
/*
$x = "#-->";
foreach ($_POST as $key => $value) {
$x = $x . $key . " <> " . $value . "\n";
}
$x = $x . '# ';
echo $x;
var_dump($_POST);
*/
switch ($cmd) {
case 'GET_ANMELD':
$erg = getAnmeldungen($_POST['id']);
break;
case 'GET_ANMELDNEW':
$erg = getAnmeldungenNew($_POST['special'], $_POST['date']);
break;
case 'GET_SONDERNEW':
$erg = getSonderNew($_POST['special'], $_POST['date']);
break;
case 'GET_TEILN_ID':
$erg = getTeilnehmer($_POST['id']);
break;
case 'GET_TEILN_NAME':
$erg = getTeilnehmerByName($_POST['name']);
break;
case 'GET_GROUP':
$erg = getGroup($_POST['date']);
break;
case 'GET_DATES':
$erg = getNextFuehrungen($_POST['anzahl'], $_POST['date']);
break;
case 'GET_COUNTS':
$erg = getCountsPerDate($_POST['fdate']);
break;
case 'GET_LASTANMELDUNG':
$erg = getLastAnmeldung($_POST['date']);
break;
case 'UPDATE':
$erg = "Nix gut";
if ((count($_POST['ids']) != 0) and (count($_POST['values']) != 0)) {
$rows = $_POST['ids'];
$values = $_POST['values'];
$erg = updateEntries($rows, $values, $_POST['field']);
}
break;
case 'UPDATECOUNT':
$erg = updateCount($_POST['date'], $_POST['anzahl']);
break;
case 'DELETEONE':
$erg = deleteOne($_POST['id']);
break;
case 'DOUBLE':
$erg = findDoubles($_POST['date']);
break;
case 'SENDMYMAIL':
$erg = sendmail($_POST['betreff'], $defaultabsender, $_POST['body'], [], $_POST['bcc'], $_POST['to']);
break;
}
header("Content-type: text/json;charset=utf-8");
echo json_encode($erg);

View File

@@ -1,88 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Sonnenführungen</title>
<link rel="stylesheet" type="text/css" media="screen" href="css/bootstrap.min.css"/>
<link rel="stylesheet" type="text/css" media="screen" href="../sofue/css/jquery-ui.min.css"/>
<link rel="stylesheet" type="text/css" media="screen" href="../sofue/css/ui.jqgrid.css"/>
<link rel="stylesheet" type="text/css" media="screen" href="../sofue/css/jquery-ui-timepicker-addon.css"/>
<link rel="stylesheet" type="text/css" media="screen" href="css/sonnenf.css"/>
<script type="text/javascript" src="../sofue/js/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="../sofue/js/i18n/grid.locale-de.js"></script>
<script type="text/javascript" src="../sofue/js/jquery.jqGrid.min.js"></script>
<script type="text/javascript" src="../sofue/js/jquery-ui-1.10.0.custom.min.js"></script>
<script type="text/javascript" src="../sofue/js/jquery-ui-timepicker-addon.js"></script>
<script type="text/javascript" src="../sofue/js/moment.js"></script>
<script type="text/javascript" src="../sofue/js/de.js"></script>
<script type="text/javascript" src="../sofue/js/ajax.js"></script>
<script type="text/javascript" src="js/version.js"></script>
<script type="text/javascript" src="js/sonnenf.js"></script>
</head>
<?php
$ok = "false";
$nm = "Null";
$dbl = "false";
if ((isset($_GET['storno'])) && ($_GET['storno'] == "true")) {
$ok = "true";
}
if (isset($_GET['name'])) {
$nm = $_GET['name'];
}
if ((isset($_GET['double'])) && ($_GET['double'] == "true")) {
$dbl = "true";
}
?>
<script type="text/javascript">
var params = getAuthorisation('<?php echo "$ok,$nm,$dbl"?>');
</script>
<body>
<div id="container" class="anmeld">
<div class="col-12 text-center">
<h3>Anmeldungen zu Sonnenführungen</h3>
</div>
<div class="col-12 col-xm-8 text-center">
<div class="col-12" id="auswahl"><h5>Führung am</h5></div>
</div>
<br/>
<div class="col-12 col-xm-8 text-center">
<table id="tabAnmeld" class="table table-bordered table-sm"></table>
<br/>
<div class="row">
<div class="col-sm-1 text-left"></div>
<div class="col-12 col-sm-4 text-center">
<button type="button" val="OK" id="absagen" class="btn btn-primary">Absage <br/>senden</button>
</div>
<div class="col-sm-1 text-center"></div>
<div class="col-12 col-sm-4 text-center">
<button type="button" val="OK" id="uebernehmen" class="btn btn-primary">Teilnahme<br/>übernehmen
</button>
</div>
<div class="col-sm-1 text-right"></div>
</div>
<div id="absagedialog">
<div id="absagetext"></div>
</div>
<div id="eintragedialog">
<div id="eintragetext"></div>
</div>
<div id="detail">
<div id="detailtext"></div>
</div>
<!-- Info unter Tabelle -->
<div class="row" id="author">
<div class="col-6 text-left">
<a href="mailto:rxf@gmx.de">mailto:rxf@gmx.de</a>
</div>
<div id="versn" class="col-6 text-right"></div>
</div>
</div>
</div>
<!-- container -->
<div id="names" class="col-12 col-xm-8 text-center anmeld">
<table id="tnames" class="table table-bordered table-sm"></table>
</div>
</body>
</html>

View File

@@ -1,8 +1,7 @@
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
require 'vendor/autoload.php';
@@ -12,47 +11,83 @@ function sendmail($subject, $from, $body, $cc=[], $bcc=[], $to=[]) {
$ret = [];
$ret['error'] = false;
$mail = new PHPMailer();
$mail->CharSet = 'utf-8';
$mail->isSMTP();
if ($develop == 'true') {
$mail->Host = 'mailhog';
$mail->Port = 1025;
} else {
$mail->SMTPAuth = true;
$mail->Host = "sslout.df.eu";
$mail->Port = "465";
$mail->SMTPSecure = "ssl";
$mail->Username = "sonderfuehrung@sternwarte-welzheim.de";
$mail->Password = "v|kR9D8m}K";
}
$mail->setFrom($from);
if (count($to) != 0) {
foreach ($to as $t) {
$mail->addAddress($t);
$mail = new PHPMailer(true);
try {
// Debug-Einstellungen
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
$mail->Debugoutput = function($str, $level) {
file_put_contents(__DIR__ . '/phpmailer_debug.log',
date('Y-m-d H:i:s') . " [Level $level] $str\n", FILE_APPEND);
};
// Basis-Einstellungen
$mail->CharSet = 'UTF-8';
$mail->isSMTP();
if ($develop == 'true') {
$mail->Host = 'mailhog';
$mail->Port = 1025;
$mail->SMTPAuth = false;
} else {
// GMX Einstellungen
$mail->Host = 'smtp.gmx.com'; // ✅ Korrekter Host
$mail->Port = 465;
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mail->SMTPAuth = true;
$mail->Username = 'sternwarte.welzheim@gmx.de';
$mail->Password = '4NT&%nH9&5wz'; // ✅ Tippfehler korrigiert
// Optional: Zusätzliche Authentifizierung
$mail->AuthType = 'LOGIN';
// Optional: Timeout erhöhen
$mail->Timeout = 60;
}
}
$mail->Subject = $subject;
$mail->Body = $body;
if (count($cc) != 0) {
foreach ($cc as $c) {
$mail->addCC($c);
// Absender
$mail->setFrom('sternwarte.welzheim@gmx.de', 'Sternwarte-Welzheim');
// Empfänger
if (count($to) != 0) {
foreach ($to as $t) {
$mail->addAddress($t);
}
}
}
if(count($bcc) != 0) {
foreach ($bcc as $bc) {
$mail->addBCC($bc);
// CC
if (count($cc) != 0) {
foreach ($cc as $c) {
$mail->addCC($c);
}
}
}
$mail->addReplyTo($from);
if (!$mail->send()) {
// BCC
if (count($bcc) != 0) {
foreach ($bcc as $bc) {
$mail->addBCC($bc);
}
}
// Reply-To
if (!empty($from)) {
$mail->addReplyTo($from);
}
// Inhalt
$mail->Subject = $subject;
$mail->isHTML(false); // Oder true, je nach Bedarf
$mail->Body = $body;
// Senden
$mail->send();
$ret['oktext'] = 'Mail erfolgreich versendet';
} catch (Exception $e) {
$ret['error'] = true;
$ret['errortext'] = $mail->ErrorInfo;
$ret['errortext'] = "Mailer Error: {$mail->ErrorInfo}";
error_log("PHPMailer Error: " . $e->getMessage());
}
return $ret;
}
?>

View File

@@ -269,6 +269,11 @@ einer unserer freien Mitarbeiter/-innen die Sonderführung außerhalb unserer
<p>
<a name="form">&nbsp;</a><?PHP echo $stern_error_msg ?></p>
<p>
<p class="sondermeldung">
Unsere Sternwarte bleibt bis voraussichtlich 14. November 2025 wegen neuer technischer Einrichtung
geschlossen. <br />Bis dahin können keine Führungen durchgeführt werden.
</p>
<strong>Unverbindliche Anfrage zu einer Sonderführung auf der
Sternwarte Welzheim</strong><br/>
<div id="formular" class="fltrt">
@@ -436,6 +441,7 @@ einer unserer freien Mitarbeiter/-innen die Sonderführung außerhalb unserer
);
// Heute
$timestamp = time(); // jetzt (heute)
$timestamp = 1762001873; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$timestamp1 = $timestamp + 1209600; // 14 Tage weiter
// 365 Tage in die Zukunft...
for ($i = 0; $i < 365; $i++) {
@@ -508,7 +514,7 @@ einer unserer freien Mitarbeiter/-innen die Sonderführung außerhalb unserer
<p><br/><br/>Hinweis zum Datenschutz:
<a href="" id="dschu">Datenschutzerklärung</a></p>
<p class="lastchange">Letzte Änderungen: 2023-10-04 rxf</p>
<p class="lastchange">Letzte Änderungen: 2025-10-22 rxf</p>
</form>
</div>
<?

View File

@@ -97,6 +97,7 @@
$enddatum = new DateTime('now');
$enddatum->modify($monthstoadd);
$enddatum = $enddatum->format('Ymd');
$datum_heute = 20251114; //<<<<<<<<<<<<<<<<<<<<<<<<<
$sql_sel = "SELECT * FROM sonnedatum where datum >='$datum_heute' && datum <= '$enddatum' order by datum ASC";
$result = mysqli_query($db, $sql_sel) or die(mysqli_error($db));
while ($row = mysqli_fetch_assoc($result)) {
@@ -381,6 +382,11 @@
<p>
<?PHP echo $stern_error_msg ?>
</p>
<p class="sondermeldung">
Unsere Sternwarte bleibt bis voraussichtlich 14. November 2025 wegen neuer technischer Einrichtung
geschlossen. <br />Bis dahin können keine Führungen durchgeführt werden.
</p>
<strong>Anmeldung:</strong>
<span class="textklein">(Alle Felder mit '*' müssen ausgefüllt werden)</span><br />
<br />
@@ -465,7 +471,7 @@
<p>
Hinweis zum Datenschutz: <a href="" id="dschu">Datenschutzerklärung</a>
</p>
<p class="lastchange">Letzte Änderungen: 2024-09-19 rxf</p>
<p class="lastchange">Letzte Änderungen: 2025-10-22 rxf</p>
</form>
</div>