Compare commits
3
Commits
main
..
c8e7ce9174
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8e7ce9174 | ||
|
|
3731183654 | ||
|
|
a51fd9dbeb |
+15
-12
@@ -1,22 +1,25 @@
|
|||||||
config/.env.db
|
config/.env.db
|
||||||
|
config/.env.db-tables
|
||||||
config/.env.db-guest
|
config/.env.db-guest
|
||||||
config/.env.redis
|
config/.env.redis
|
||||||
config/.env.pw-encryption-key
|
config/.env.pw-encryption-key
|
||||||
|
config/.env.wk-id
|
||||||
config/.env.mail
|
config/.env.mail
|
||||||
config/.env.db-wkvs-user
|
|
||||||
config/.env.docker.db
|
|
||||||
websocket/node_modules
|
websocket/node_modules
|
||||||
composer/vendor
|
websocket/package-lock.json
|
||||||
|
websocket/package.json
|
||||||
|
composer
|
||||||
private-files/rechnungen/*
|
private-files/rechnungen/*
|
||||||
private-files/config-uploads/*
|
private-files/config-uploads/*
|
||||||
.php-ini
|
.php-ini
|
||||||
.php-version
|
.php-version
|
||||||
html/externe-geraete/json/*
|
www/externe-geraete/json/*
|
||||||
html/files/ranglisten/*
|
www/files/ranglisten/*
|
||||||
html/sponsoren.php
|
www/sponsoren.php
|
||||||
html/css/sponsoren.css
|
www/css/sponsoren.css
|
||||||
html/scripts
|
www/scripts
|
||||||
html/files/music/*
|
www/files/music/*
|
||||||
!html/files/music/piep.mp3
|
!www/files/music/piep.mp3
|
||||||
html/.well-known
|
www/.well-known
|
||||||
html/intern/kampfrichter/ajax/ajax-neu_dynamic-rangliste.php
|
www/intern/kampfrichter/ajax/ajax-neu_dynamic-rangliste.php
|
||||||
|
setup/database/*
|
||||||
+310
@@ -0,0 +1,310 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# WKVS Full Stack Installation Script
|
||||||
|
# Autor: Euria
|
||||||
|
# Datum: 2026-04-20
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
set -e # Stoppt das Skript bei jedem Fehler
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo " WKVS Full Stack Installation"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo ""
|
||||||
|
read -p "Dieses Skript funktioniert nur auf einer leeren Linux Instalation. Fohrtfahren? [y/n/c]: " choiceInstall
|
||||||
|
|
||||||
|
case $choiceInstall in
|
||||||
|
[yY]*) ;;
|
||||||
|
[nN]*)
|
||||||
|
echo "Installation abgebrochen."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
[cC]*)
|
||||||
|
echo "Installation abgebrochen."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Ungültige Eingabe."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# --- 1. System Update & Basisinstallation ---
|
||||||
|
echo "Schritt 1: System aktualisieren und Basis-Pakete installieren..."
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y mariadb-server apache2 nginx curl dig certbot python3-certbot-nginx
|
||||||
|
|
||||||
|
# --- 2. MariaDB Installation & Konfiguration ---
|
||||||
|
echo "Schritt 2: MariaDB Konfiguration..."
|
||||||
|
|
||||||
|
read -p "Willst du die Installation komplett automatisch abschließen? [y/n/c]: " choice
|
||||||
|
|
||||||
|
case $choice in
|
||||||
|
[yY]*)
|
||||||
|
PREFIX=$(openssl rand -hex 3)
|
||||||
|
DB_NAME="${PREFIX}_wkvs_db"
|
||||||
|
DB_USER_NORMAL="${PREFIX}_wkvs_user"
|
||||||
|
DB_USER_GUEST="${PREFIX}_wkvs_guest"
|
||||||
|
DB_PASS_NORMAL=$(openssl rand -base64 24)
|
||||||
|
DB_PASS_GUEST=$(openssl rand -base64 24)
|
||||||
|
DB_PORT="3306"
|
||||||
|
AUTO_INSTALL="true"
|
||||||
|
;;
|
||||||
|
[nN]*)
|
||||||
|
read -p "Name der Datenbank: " DB_NAME
|
||||||
|
read -sp "Passwort für $DB_USER_NORMAL: " DB_PASS_NORMAL
|
||||||
|
echo ""
|
||||||
|
read -p "Name des Gastbenutzers: " DB_USER_GUEST
|
||||||
|
read -sp "Passwort für $DB_USER_GUEST: " DB_PASS_GUEST
|
||||||
|
echo ""
|
||||||
|
read -p "Custom Port (Standard 3306): " DB_PORT
|
||||||
|
DB_PORT=${DB_PORT:-3306}
|
||||||
|
AUTO_INSTALL="false"
|
||||||
|
;;
|
||||||
|
[cC]*)
|
||||||
|
echo "Installation abgebrochen."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Ungültige Eingabe."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# MariaDB Port umstellen (falls Custom)
|
||||||
|
if [ "$DB_PORT" != "3306" ]; then
|
||||||
|
echo " Stelle MariaDB auf Port $DB_PORT um..."
|
||||||
|
if [ -f /etc/mysql/mariadb.conf.d/50-server.cnf ]; then
|
||||||
|
sudo sed -i "s/.*port\s*=\s*3306/port = $DB_PORT/" /etc/mysql/mariadb.conf.d/50-server.cnf
|
||||||
|
sudo systemctl restart mariadb
|
||||||
|
else
|
||||||
|
echo " Fehler: Konfigurationsdatei nicht gefunden."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
sudo systemctl restart mariadb
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- 3. Datenbank Setup ---
|
||||||
|
echo "Schritt 3: Datenbank und Benutzer erstellen..."
|
||||||
|
sudo mysql -P "$DB_PORT" <<EOF
|
||||||
|
CREATE DATABASE IF NOT EXISTS \`${DB_NAME}\`;
|
||||||
|
|
||||||
|
-- Normaler User
|
||||||
|
CREATE USER IF NOT EXISTS \`$DB_USER_NORMAL\`@'127.0.0.1' IDENTIFIED BY '$DB_PASS_NORMAL';
|
||||||
|
GRANT SELECT, INSERT, UPDATE, DELETE ON \`${DB_NAME}\`.* TO \`${DB_USER_NORMAL}\`@'127.0.0.1';
|
||||||
|
|
||||||
|
-- Gast User (Nur SELECT)
|
||||||
|
CREATE USER IF NOT EXISTS \`$DB_USER_GUEST\`@'127.0.0.1' IDENTIFIED BY '$DB_PASS_GUEST';
|
||||||
|
GRANT SELECT ON \`${DB_NAME}\`.* TO \`${DB_USER_GUEST}\`@'127.0.0.1';
|
||||||
|
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# --- 4. Environment Files & SQL Import ---
|
||||||
|
mkdir -p config
|
||||||
|
|
||||||
|
cat <<EOT > config/.env.db
|
||||||
|
DB_USER=$DB_USER_NORMAL
|
||||||
|
DB_PASSWORD=$DB_PASS_NORMAL
|
||||||
|
DB_NAME=$DB_NAME
|
||||||
|
DB_HOST=127.0.0.1
|
||||||
|
DB_PORT=$DB_PORT
|
||||||
|
EOT
|
||||||
|
|
||||||
|
cat <<EOT > config/.env.db-guest
|
||||||
|
DB_GUEST_USER=$DB_USER_GUEST
|
||||||
|
DB_GUEST_PASSWORD=$DB_PASS_GUEST
|
||||||
|
DB_NAME=$DB_NAME
|
||||||
|
DB_HOST=127.0.0.1
|
||||||
|
DB_PORT=$DB_PORT
|
||||||
|
EOT
|
||||||
|
|
||||||
|
# SQL Import (falls vorhanden)
|
||||||
|
if [ -f "setup/database/generate-sql.php" ]; then
|
||||||
|
echo " Generiere SQL-Struktur..."
|
||||||
|
php setup/database/generate-sql.php
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "setup/database/sql-database.sql" ]; then
|
||||||
|
echo " Importiere Datenbank-Struktur..."
|
||||||
|
sudo mysql -P "$DB_PORT" "$DB_NAME" < setup/database/sql-database.sql
|
||||||
|
echo " Datenbank-Schema erfolgreich importiert."
|
||||||
|
else
|
||||||
|
echo " Warnung: SQL-Datei nicht gefunden. Import übersprungen."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- 5. Verschlüsselungsschlüssel ---
|
||||||
|
if [ "$AUTO_INSTALL" = "true" ]; then
|
||||||
|
ENCRYPTION_KEY=$(openssl rand -base64 32)
|
||||||
|
echo " Automatischer Modus: Verschlüsselungsschlüssel generiert."
|
||||||
|
else
|
||||||
|
read -sp "Schlüssel zur symmetrischen Verschlüsselung (durch WK-Leitung): " ENCRYPTION_KEY
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat <<EOT > config/.env.pw-encryption-key
|
||||||
|
PW_ENCRYPTION_KEY=$ENCRYPTION_KEY
|
||||||
|
EOT
|
||||||
|
|
||||||
|
# --- 6. Composer & PHP Dependencies ---
|
||||||
|
if ! command -v composer &> /dev/null; then
|
||||||
|
echo " Composer wird installiert..."
|
||||||
|
sudo apt install -y composer
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " Installiere Composer Pakete..."
|
||||||
|
composer require vlucas/phpdotenv
|
||||||
|
composer require phpmailer/phpmailer
|
||||||
|
composer require shuchkin/simplexlsx
|
||||||
|
composer require sprain/swiss-qr-bill
|
||||||
|
composer require james-heinrich/getid3
|
||||||
|
composer require chriskonnertz/string-calc
|
||||||
|
composer require tecnickcom/tcpdf
|
||||||
|
|
||||||
|
# --- 7. Node.js WebSocket ---
|
||||||
|
cd websocket || { echo "Fehler: websocket Ordner nicht gefunden!"; exit 1; }
|
||||||
|
|
||||||
|
npm init -y
|
||||||
|
npm install redis ws dotenv
|
||||||
|
npm install -g pm2
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
echo " WebSocket (Node.js) Installation abgeschlossen."
|
||||||
|
|
||||||
|
# --- 8. Apache & Nginx Konfiguration ---
|
||||||
|
echo "Schritt 8: Webserver konfigurieren..."
|
||||||
|
|
||||||
|
# Apache auf internen Port umstellen
|
||||||
|
APACHE_INTERNAL_PORT=8080
|
||||||
|
if grep -q "Listen 80" /etc/apache2/ports.conf 2>/dev/null; then
|
||||||
|
sudo sed -i "s/^Listen 80$/Listen $APACHE_INTERNAL_PORT/" /etc/apache2/ports.conf
|
||||||
|
# Falls Default VHost auch 80 hat
|
||||||
|
if [ -f /etc/apache2/sites-enabled/000-default.conf ]; then
|
||||||
|
sudo sed -i "s/Listen 80/Listen $APACHE_INTERNAL_PORT/" /etc/apache2/sites-enabled/000-default.conf 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
sudo systemctl restart apache2
|
||||||
|
echo " Apache auf internen Port $APACHE_INTERNAL_PORT umgestellt."
|
||||||
|
|
||||||
|
# --- 9. Nginx Reverse Proxy & SSL ---
|
||||||
|
echo "Schritt 9: Nginx Reverse Proxy & HTTPS einrichten..."
|
||||||
|
|
||||||
|
read -p "Domain der Webseite: (Beispiel: wk.wkvs.ch) " DOMAIN
|
||||||
|
|
||||||
|
if [ -z "$DOMAIN" ]; then
|
||||||
|
echo "❌ FEHLER: Die Domain darf nicht leer sein!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DOMAIN=$(echo "$DOMAIN" | xargs)
|
||||||
|
|
||||||
|
# DNS Prüfung
|
||||||
|
echo " DNS-Prüfung für $DOMAIN..."
|
||||||
|
RESOLVED_IP=$(dig +short $DOMAIN 2>/dev/null | head -n1)
|
||||||
|
SERVER_IP=$(curl -s https://api.ipify.org 2>/dev/null)
|
||||||
|
|
||||||
|
if [ -z "$RESOLVED_IP" ]; then
|
||||||
|
echo "❌ FEHLER: Domain '$DOMAIN' kann nicht aufgelöst werden."
|
||||||
|
echo " Bitte warten Sie, bis die DNS-Einträge aktiv sind."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$SERVER_IP" ] && [ "$RESOLVED_IP" != "$SERVER_IP" ]; then
|
||||||
|
echo "⚠️ WARNUNG: Domain zeigt auf $RESOLVED_IP, Server ist $SERVER_IP."
|
||||||
|
echo " Bitte prüfen Sie Ihre DNS-Einträge."
|
||||||
|
read -p "Möchten Sie trotzdem fortfahren? [y/n]: " confirm
|
||||||
|
if [ "$confirm" != "y" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Nginx Konfiguration erstellen
|
||||||
|
NGINX_CONF="/etc/nginx/sites-available/$DOMAIN"
|
||||||
|
NGINX_LINK="/etc/nginx/sites-enabled/$DOMAIN"
|
||||||
|
|
||||||
|
rm -f /etc/nginx/sites-enabled/default 2>/dev/null || true
|
||||||
|
rm -f "$NGINX_CONF" 2>/dev/null || true
|
||||||
|
|
||||||
|
cat > "$NGINX_CONF" <<EOF
|
||||||
|
# HTTP -> HTTPS Weiterleitung
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name $DOMAIN;
|
||||||
|
return 301 https://\$host\$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTPS Server
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name $DOMAIN;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
# WebSocket Route
|
||||||
|
location /ws/ {
|
||||||
|
proxy_pass http://127.0.0.1:8082;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
|
proxy_read_timeout 3600s;
|
||||||
|
proxy_send_timeout 3600s;
|
||||||
|
proxy_connect_timeout 75s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Versteckte Dateien
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
access_log off;
|
||||||
|
log_not_found off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Apache Proxy
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:$APACHE_INTERNAL_PORT;
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo ln -sf "$NGINX_CONF" "$NGINX_LINK"
|
||||||
|
|
||||||
|
# Let's Encrypt Zertifikat
|
||||||
|
echo " Starte Let's Encrypt Zertifikatsanfrage..."
|
||||||
|
read -p "E-Mail für Let's Encrypt: " EMAIL
|
||||||
|
|
||||||
|
sudo certbot --nginx -d $DOMAIN --agree-tos --no-eff-email --redirect --email "$EMAIL" --non-interactive
|
||||||
|
|
||||||
|
# Dienste neu starten
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
sudo systemctl restart apache2
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "✅ Installation erfolgreich abgeschlossen!"
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Zusammenfassung:"
|
||||||
|
echo "- Datenbank: $DB_NAME (Port: $DB_PORT)"
|
||||||
|
echo "- Apache intern: Port $APACHE_INTERNAL_PORT"
|
||||||
|
echo "- Node.js WS: Port 8082 (unter /ws/)"
|
||||||
|
echo "- HTTPS: https://$DOMAIN/intern/wk-leitung/logindata"
|
||||||
|
echo ""
|
||||||
|
echo "Nächste Schritte:"
|
||||||
|
echo "1. Starten Sie den WebSocket Server: cd websocket && pm2 start app.js"
|
||||||
|
echo "2. Testen Sie die Seite: https://$DOMAIN/intern/wk-leitung/logindata"
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
services:
|
|
||||||
nginx:
|
|
||||||
image: nginx:latest
|
|
||||||
ports:
|
|
||||||
- "127.0.0.1:8081:80"
|
|
||||||
depends_on:
|
|
||||||
- apache
|
|
||||||
- node
|
|
||||||
volumes:
|
|
||||||
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
|
||||||
networks:
|
|
||||||
- app-network
|
|
||||||
|
|
||||||
apache:
|
|
||||||
build: ./docker/apache
|
|
||||||
volumes:
|
|
||||||
- .:/var/www/wkvs
|
|
||||||
networks:
|
|
||||||
- app-network
|
|
||||||
|
|
||||||
mariadb:
|
|
||||||
image: mariadb:11
|
|
||||||
container_name: test-mariadb
|
|
||||||
restart: unless-stopped
|
|
||||||
env_file:
|
|
||||||
- ./config/.env.docker.db
|
|
||||||
volumes:
|
|
||||||
- db_data:/var/lib/mysql
|
|
||||||
networks:
|
|
||||||
- app-network
|
|
||||||
|
|
||||||
node:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: docker/node/Dockerfile
|
|
||||||
expose:
|
|
||||||
- "8082"
|
|
||||||
volumes:
|
|
||||||
- .:/var/www/wkvs
|
|
||||||
- /var/www/wkvs/websocket/node_modules
|
|
||||||
networks:
|
|
||||||
- app-network
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:7
|
|
||||||
container_name: wkvs-redis
|
|
||||||
networks:
|
|
||||||
- app-network
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db_data:
|
|
||||||
|
|
||||||
networks:
|
|
||||||
app-network:
|
|
||||||
driver: bridge
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"require": {
|
|
||||||
"vlucas/phpdotenv": "^5.6",
|
|
||||||
"phpmailer/phpmailer": "^7.0",
|
|
||||||
"shuchkin/simplexlsx": "^1.1",
|
|
||||||
"sprain/swiss-qr-bill": "^5.3",
|
|
||||||
"james-heinrich/getid3": "^1.9",
|
|
||||||
"chriskonnertz/string-calc": "^2.0",
|
|
||||||
"tecnickcom/tcpdf": "^6.11",
|
|
||||||
"predis/predis": "^3.5"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Generated
-1583
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
|||||||
|
# This Account must have have permissions SELECT, INSERT, UPDATE !
|
||||||
|
|
||||||
|
DB_USER=DB_GUESTUSER_USERNAME
|
||||||
|
DB_PASSWORD=DB_GUESTUSER_PASSWORD
|
||||||
|
DB_NAME=DATABASE_NAME # Same as .env.db
|
||||||
|
DB_HOST=DB_HOST # Same as .env.db, An IP without Port, often 127.0.0.1 or localhost
|
||||||
|
DB_PORT=3306 # default Port is 3306
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# Tabellennamen
|
|
||||||
DB_TABLE_TEILNEHMENDE=teilnehmende
|
|
||||||
DB_TABLE_TEILNEHMENDE_GRUPPEN=teilnehmende_gruppen
|
|
||||||
DB_TABLE_TEILNEHMENDE_AUDIOFILES=teilnehmende_audiofiles
|
|
||||||
|
|
||||||
DB_TABLE_VEREINE=vereine
|
|
||||||
DB_TABLE_DISZIPLINEN=disziplinen
|
|
||||||
DB_TABLE_KATEGORIEN=kategorien
|
|
||||||
|
|
||||||
DB_TABLE_WERTUNGEN=wertungen
|
|
||||||
DB_TABLE_WERTUNGEN_LOG=wertungen_log
|
|
||||||
DB_TABLE_WERTUNGSTYPEN=wertungstypen
|
|
||||||
|
|
||||||
DB_TABLE_GRUPPEN=gruppen
|
|
||||||
DB_TABLE_GRUPPEN_ZEITEN=gruppen_zeiten
|
|
||||||
|
|
||||||
DB_TABLE_WARENKORB_STARTGEBUEREN=warenkorb_startgebueren
|
|
||||||
DB_TABLE_VERBUCHTE_STARTGEBUEREN=verbuchte_startgebueren
|
|
||||||
DB_TABLE_VERBUCHTE_STARTGEBUEREN_LOG=verbuchte_startgebueren_log
|
|
||||||
|
|
||||||
DB_TABLE_ZEITPLAN_TYPES=zeitplan_types
|
|
||||||
DB_TABLE_TABELLEN_KONFIGURATION=tabellen_konfiguration
|
|
||||||
|
|
||||||
DB_TABLE_VARIABLES=variables
|
|
||||||
DB_EINMAL_LINKS=einmal_links
|
|
||||||
DB_TABLE_INTERN_BENUTZENDE=intern_benutzende
|
|
||||||
DB_TABLE_AUDIOFILES=audiofiles
|
|
||||||
DB_TABLE_WETTKAEMPFE=wettkaempfe
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
DB_PREFIX=PREFIX
|
||||||
|
|
||||||
|
# Tabellennamen
|
||||||
|
DB_TABLE_TEILNEHMENDE=teilnehmende
|
||||||
|
DB_TABLE_ORDERS=orders
|
||||||
|
DB_TABLE_BASKET_ITEMS=basket_items
|
||||||
|
DB_TABLE_VARIABLES=variables
|
||||||
|
DB_TABLE_OTL=onetimeloginlinks
|
||||||
|
DB_TABLE_KR_PROTOKOLL=kampfricherinnen_protokoll
|
||||||
|
DB_TABLE_PROGRAMME=programme
|
||||||
|
DB_TABLE_INTERN_USERS=intern_users
|
||||||
|
DB_TABLE_VEREINE=vereine
|
||||||
|
DB_TABLE_ABTEILUNGEN=abteilungen
|
||||||
|
DB_TABLE_TEILNEHMENDE_ABTEILUNGEN=teilnehmende_abteilungen
|
||||||
|
DB_TABLE_GERAETE=geraete
|
||||||
|
DB_TABLE_AUDIOFILES=audiofiles
|
||||||
|
DB_TABLE_TEILNEHMENDE_AUDIOFILES=teilnehmende_audiofiles
|
||||||
|
DB_TABLE_NOTEN=noten
|
||||||
|
DB_TABLE_NOTEN_CHANGES=noten_changes
|
||||||
|
DB_TABLE_NOTEN_BEZEICHNUNGEN=noten_bezeichnungen
|
||||||
|
DB_TABLE_ORDERS_LOG=orders_log
|
||||||
|
DB_TABLE_ZEITPLAN_TYPES=zeitplan_types
|
||||||
|
DB_TABLE_ABTEILUNGEN_ZEITEN=abteilungen_zeiten
|
||||||
|
DB_TABLE_RANKLIVE_CONFIGS=rankLive_configs
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# This Account must have at least have permissions SELECT, INSERT, UPDATE, DELETE !
|
||||||
|
|
||||||
|
DB_USER=DB_USER_USERNAME
|
||||||
|
DB_PASSWORD=DB_USER_PASSWORD
|
||||||
|
DB_NAME=DATABASE_NAME
|
||||||
|
DB_HOST=DB_HOST # An IP with Port 127.0.0.1 or localhost
|
||||||
|
DB_PORT=3306 # default Port is 3306
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
PW_ENCRYPTION_KEY=YOUR_CUSTOM_PASSWORD_ENCRYPTION_KEY
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
REDDIS_PASSWORD=YOUR_REDDIS_PASSWORD
|
||||||
|
REDDIS_HOST=YOUR_REDDIS_IP # An IP, often 127.0.0.1 or localhost
|
||||||
|
REDDIS_PORT=YOUR_REDDIS_PORT # Default 6379
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# 1. Reset containers and volumes
|
|
||||||
docker compose down -v
|
|
||||||
|
|
||||||
# Ensure the config directory exists
|
|
||||||
mkdir -p config
|
|
||||||
|
|
||||||
# 2. Generate Random Variables correctly using $(...)
|
|
||||||
MYSQL_USER=$(openssl rand -hex 16)
|
|
||||||
MYSQL_PASSWORD=$(openssl rand -base64 32)
|
|
||||||
MYSQL_DATABASE="wkvs_database"
|
|
||||||
MYSQL_ROOT_PASSWORD=$(openssl rand -base64 32)
|
|
||||||
|
|
||||||
cat <<EOF > config/.env.docker.db
|
|
||||||
MYSQL_ROOT_PASSWORD="$MYSQL_ROOT_PASSWORD"
|
|
||||||
MYSQL_DATABASE=$MYSQL_DATABASE
|
|
||||||
MYSQL_USER=$MYSQL_USER
|
|
||||||
MYSQL_PASSWORD="$MYSQL_PASSWORD"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# 3. Handle Admin Hashing
|
|
||||||
KEYWORD=$(openssl rand -hex 16)
|
|
||||||
HASHED_KEYWORD=$(php -r "echo password_hash('$KEYWORD', PASSWORD_ARGON2ID);")
|
|
||||||
|
|
||||||
# Replace placeholder in SQL template
|
|
||||||
sed "s|__ARGON_HASH_PLACEHOLDER__|$HASHED_KEYWORD|g" docker/database/wkvs-database-template.sql > docker/database/db-sql.sql
|
|
||||||
|
|
||||||
# 1. Generate password
|
|
||||||
REDIS_PASSWORD=$(openssl rand -hex 32)
|
|
||||||
|
|
||||||
# 3. Save variables to your .env file
|
|
||||||
cat <<EOF > config/.env.redis
|
|
||||||
REDIS_PASSWORD="$REDIS_PASSWORD"
|
|
||||||
REDIS_HOST=redis
|
|
||||||
REDIS_PORT=6379
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# 4. Start Docker Containers
|
|
||||||
docker compose up -d --build
|
|
||||||
|
|
||||||
# 5. Wait until MariaDB is fully up and accepting connections
|
|
||||||
echo "Waiting for MariaDB to start..."
|
|
||||||
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
until docker compose exec -T mariadb mariadb-admin ping -h localhost -u root -p"$MYSQL_ROOT_PASSWORD" --silent >/dev/null 2>&1; do
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
|
|
||||||
# 6. Execute Primary Schema Import
|
|
||||||
docker compose exec -T mariadb mariadb -u root -p"$MYSQL_ROOT_PASSWORD" "$MYSQL_DATABASE" < docker/database/db-sql.sql
|
|
||||||
rm docker/database/db-sql.sql
|
|
||||||
|
|
||||||
# 7. Generate Additional Application Users & Passwords
|
|
||||||
MYSQL_WKVS_USERNAME="wkvs_normal_user"
|
|
||||||
MYSQL_GUEST_USERNAME="wkvs_guest_user"
|
|
||||||
|
|
||||||
MYSQL_WKVS_PASSWORD=$(openssl rand -hex 32)
|
|
||||||
MYSQL_GUEST_PASSWORD=$(openssl rand -hex 16)
|
|
||||||
|
|
||||||
# Write app user configuration files
|
|
||||||
cat <<EOF > config/.env.db-wkvs-user
|
|
||||||
DB_USER=$MYSQL_WKVS_USERNAME
|
|
||||||
DB_PASSWORD="$MYSQL_WKVS_PASSWORD"
|
|
||||||
DB_NAME=$MYSQL_DATABASE
|
|
||||||
DB_HOST=mariadb
|
|
||||||
DB_PORT=3306
|
|
||||||
EOF
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cat <<EOF > config/.env.db-guest
|
|
||||||
DB_GUEST_USER=$MYSQL_GUEST_USERNAME
|
|
||||||
DB_GUEST_PASSWORD="$MYSQL_GUEST_PASSWORD"
|
|
||||||
DB_NAME=$MYSQL_DATABASE
|
|
||||||
DB_HOST=mariadb
|
|
||||||
DB_PORT=3306
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# 8. Create Additional Users & Grant Permissions in MariaDB
|
|
||||||
echo "Creating application users and setting permissions..."
|
|
||||||
|
|
||||||
docker compose exec -T mariadb mariadb -u root -p"$MYSQL_ROOT_PASSWORD" <<EOF
|
|
||||||
-- Create Normal User
|
|
||||||
CREATE USER IF NOT EXISTS '$MYSQL_WKVS_USERNAME'@'%' IDENTIFIED BY '$MYSQL_WKVS_PASSWORD';
|
|
||||||
GRANT SELECT, INSERT, UPDATE, DELETE ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_WKVS_USERNAME'@'%';
|
|
||||||
|
|
||||||
-- Create Guest User
|
|
||||||
CREATE USER IF NOT EXISTS '$MYSQL_GUEST_USERNAME'@'%' IDENTIFIED BY '$MYSQL_GUEST_PASSWORD';
|
|
||||||
GRANT SELECT, INSERT, UPDATE ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_GUEST_USERNAME'@'%';
|
|
||||||
|
|
||||||
FLUSH PRIVILEGES;
|
|
||||||
EOF
|
|
||||||
|
|
||||||
SERVICE_NAME="apache"
|
|
||||||
COMPOSER_DIR="/var/www/wkvs/composer"
|
|
||||||
|
|
||||||
echo "Running Composer setup via Docker Compose..."
|
|
||||||
|
|
||||||
# 1. Download Composer inside the service container if not installed globally
|
|
||||||
docker compose exec "$SERVICE_NAME" bash -c '
|
|
||||||
if ! command -v composer &> /dev/null && [ ! -f "composer.phar" ]; then
|
|
||||||
php -r "copy('\''https://getcomposer.org/installer'\'', '\''composer-setup.php'\'');"
|
|
||||||
php composer-setup.php --quiet
|
|
||||||
php -r "unlink('\''composer-setup.php'\'');"
|
|
||||||
fi
|
|
||||||
'
|
|
||||||
|
|
||||||
# 2. Run composer install against the specified directory
|
|
||||||
docker compose exec "$SERVICE_NAME" bash -c "
|
|
||||||
COMPOSER_CMD=\$(command -v composer || echo \"php \$(pwd)/composer.phar\")
|
|
||||||
TARGET_DIR=\"$COMPOSER_DIR\"
|
|
||||||
|
|
||||||
if [ -f \"\$TARGET_DIR/composer.lock\" ] || [ -f \"\$TARGET_DIR/composer.json\" ]; then
|
|
||||||
\$COMPOSER_CMD install --working-dir=\"\$TARGET_DIR\" --no-interaction --prefer-dist --quiet
|
|
||||||
else
|
|
||||||
echo \"Error: Neither composer.json nor composer.lock found in '\$TARGET_DIR'.\" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
"
|
|
||||||
|
|
||||||
echo "Konfiguriere Redis..."
|
|
||||||
|
|
||||||
# 2. Set password in the currently running Redis container
|
|
||||||
docker compose exec redis redis-cli CONFIG SET requirepass "$REDIS_PASSWORD"
|
|
||||||
|
|
||||||
PASSWORD_KEY=openssl rand -base64 32
|
|
||||||
|
|
||||||
cat <<EOF > config/.env.pw-encryption-key
|
|
||||||
PW_ENCRYPTION_KEY=$PASSWORD_KEY
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "------------------------------------------------------"
|
|
||||||
echo "Setup Complete!"
|
|
||||||
echo "Admin Plain Keyword: $KEYWORD"
|
|
||||||
echo "------------------------------------------------------"
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
FROM php:8.5-apache
|
|
||||||
|
|
||||||
# Enable Apache rewrite module
|
|
||||||
RUN a2enmod rewrite
|
|
||||||
|
|
||||||
# Install system dependencies, PHP extensions, and clean up apt cache
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
unzip \
|
|
||||||
libzip-dev \
|
|
||||||
libicu-dev \
|
|
||||||
git \
|
|
||||||
&& docker-php-ext-install \
|
|
||||||
bcmath \
|
|
||||||
mysqli \
|
|
||||||
pdo_mysql \
|
|
||||||
zip \
|
|
||||||
intl \
|
|
||||||
&& pecl install redis \
|
|
||||||
&& docker-php-ext-enable redis \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Update Apache DocumentRoot to /var/www/wkvs/html/ and enable .htaccess overrides
|
|
||||||
ENV APACHE_DOCUMENT_ROOT=/var/www/wkvs/html/
|
|
||||||
|
|
||||||
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \
|
|
||||||
&& sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf \
|
|
||||||
&& sed -i 's/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
include_path=".:/var/www/html:/usr/local/lib/php"
|
|
||||||
@@ -1,335 +0,0 @@
|
|||||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
|
||||||
START TRANSACTION;
|
|
||||||
SET time_zone = "+00:00";
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `audiofiles`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `audiofiles` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`file_name` varchar(1024) NOT NULL,
|
|
||||||
`file_path` varchar(1024) NOT NULL,
|
|
||||||
`edited_by` int(11) DEFAULT NULL,
|
|
||||||
`timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `disziplinen`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `disziplinen` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` varchar(1024) DEFAULT NULL,
|
|
||||||
`start_index` int(11) DEFAULT NULL,
|
|
||||||
`color_kampfrichter` char(7) NOT NULL DEFAULT '#424242',
|
|
||||||
`audiofile` tinyint(1) DEFAULT NULL,
|
|
||||||
`audiofile_max_duration` int(11) DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `einmal_links`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `einmal_links` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`url` varchar(1000) DEFAULT NULL,
|
|
||||||
`user_id` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`type` enum('login','pwreset','create_profile','') NOT NULL,
|
|
||||||
`timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
|
|
||||||
`expires_at` timestamp NULL DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `url` (`url`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
DELIMITER $$
|
|
||||||
CREATE TRIGGER `before_insert_login_tokens`
|
|
||||||
BEFORE INSERT ON `einmal_links`
|
|
||||||
FOR EACH ROW
|
|
||||||
BEGIN
|
|
||||||
IF NEW.url IS NULL THEN
|
|
||||||
SET NEW.url = HEX(RANDOM_BYTES(32));
|
|
||||||
END IF;
|
|
||||||
END$$
|
|
||||||
DELIMITER ;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `gruppen`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `gruppen` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` varchar(100) NOT NULL DEFAULT 'KEIN NAME',
|
|
||||||
`order_index` int(11) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `gruppen_zeiten`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `gruppen_zeiten` (
|
|
||||||
`zeitplan_id` int(11) NOT NULL,
|
|
||||||
`start_time` time NOT NULL,
|
|
||||||
`end_time` time DEFAULT NULL,
|
|
||||||
`abt_id` int(11) NOT NULL,
|
|
||||||
UNIQUE KEY `unique_index` (`zeitplan_id`,`abt_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `intern_benutzende`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `intern_benutzende` (
|
|
||||||
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`username` varchar(191) DEFAULT NULL,
|
|
||||||
`name_person` varchar(255) DEFAULT NULL,
|
|
||||||
`password_hash` varchar(255) DEFAULT NULL,
|
|
||||||
`password_cipher` text DEFAULT NULL,
|
|
||||||
`created_at` datetime NOT NULL DEFAULT current_timestamp(),
|
|
||||||
`updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
|
||||||
`edited_by` varchar(20) NOT NULL DEFAULT '0',
|
|
||||||
`freigabe` varchar(500) NOT NULL DEFAULT 'keine',
|
|
||||||
`login_active` tinyint(1) DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `username_page_unique` (`username`,`password_hash`) USING BTREE,
|
|
||||||
KEY `indexFreigabe` (`freigabe`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- Admin Seed Entry (Uses Argon2id placeholder for replacement via bash sed script)
|
|
||||||
INSERT INTO `intern_benutzende` (`username`, `password_hash`, `password_cipher`, `freigabe`, `login_active`)
|
|
||||||
VALUES ('admin', '__ARGON_HASH_PLACEHOLDER__', 'not_set', '{"types":["wk_leitung","trainer","kampfrichter"],"freigabenTrainer":["admin"],"freigabenKampfrichter":["A"]}', 1);
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `kategorien`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `kategorien` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`programm` text NOT NULL,
|
|
||||||
`order_index` int(11) DEFAULT NULL,
|
|
||||||
`preis` decimal(10,2) DEFAULT 0.00,
|
|
||||||
`aktiv` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `tabellen_konfiguration`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `tabellen_konfiguration` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`type_slug` varchar(128) NOT NULL,
|
|
||||||
`json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`json`)),
|
|
||||||
`all_noten_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`all_noten_json`)),
|
|
||||||
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
|
|
||||||
`updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
|
||||||
`created_by` int(11) DEFAULT NULL,
|
|
||||||
`updated_by` int(11) DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `unique_slug` (`type_slug`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `teilnehmende`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `teilnehmende` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`wk_id` int(11) DEFAULT NULL,
|
|
||||||
`name` text NOT NULL,
|
|
||||||
`vorname` text NOT NULL,
|
|
||||||
`geburtsdatum` date NOT NULL,
|
|
||||||
`programm` text NOT NULL,
|
|
||||||
`verein` text NOT NULL,
|
|
||||||
`bezahlt` int(11) NOT NULL DEFAULT 1,
|
|
||||||
`bezahltoverride` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`betrag_bezahlt` decimal(12,2) NOT NULL DEFAULT 0.00,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `wk_index` (`wk_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `teilnehmende_audiofiles`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `teilnehmende_audiofiles` (
|
|
||||||
`person_id` int(7) NOT NULL,
|
|
||||||
`geraet_id` int(7) NOT NULL,
|
|
||||||
`audiofile_id` int(7) NOT NULL,
|
|
||||||
UNIQUE KEY `unique_combo` (`person_id`,`geraet_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `teilnehmende_gruppen`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `teilnehmende_gruppen` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`turnerin_id` int(11) NOT NULL,
|
|
||||||
`abteilung_id` int(11) NOT NULL,
|
|
||||||
`geraet_id` int(11) NOT NULL,
|
|
||||||
`turnerin_index` int(11) DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `unique_turnerin` (`turnerin_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `variables`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `variables` (
|
|
||||||
`name` varchar(255) NOT NULL DEFAULT 'NaN',
|
|
||||||
`value` varchar(255) DEFAULT NULL,
|
|
||||||
UNIQUE KEY `uniqueIndex` (`name`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `verbuchte_startgebueren`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `verbuchte_startgebueren` (
|
|
||||||
`order_id` int(11) NOT NULL,
|
|
||||||
`order_type` varchar(100) DEFAULT NULL,
|
|
||||||
`preis` float DEFAULT NULL,
|
|
||||||
`user_id` int(11) NOT NULL,
|
|
||||||
`item_ids` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`item_ids`)),
|
|
||||||
`used_verein_konten` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
|
|
||||||
`order_status` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
|
|
||||||
`edited_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
|
||||||
PRIMARY KEY (`order_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `verbuchte_startgebueren_log`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `verbuchte_startgebueren_log` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`order_id` int(11) NOT NULL,
|
|
||||||
`old_order_status` int(11) NOT NULL,
|
|
||||||
`new_order_status` int(11) NOT NULL,
|
|
||||||
`edited_by` int(11) NOT NULL,
|
|
||||||
`edited_at` timestamp NOT NULL DEFAULT current_timestamp(),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `vereine`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `vereine` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`verein` text NOT NULL,
|
|
||||||
`email` varchar(100) NOT NULL DEFAULT 'forms@testseite-fh.ch',
|
|
||||||
`konto` decimal(12,2) NOT NULL DEFAULT 0.00,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `indexturnerinnen` (`id`,`verein`(31))
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `warenkorb_startgebueren`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `warenkorb_startgebueren` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`user_id` bigint(20) UNSIGNED NOT NULL,
|
|
||||||
`item_id` int(11) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `basket_items_ibfk_1` (`user_id`),
|
|
||||||
KEY `basket_items_ibfk_2` (`item_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `wertungen`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `wertungen` (
|
|
||||||
`person_id` int(11) NOT NULL,
|
|
||||||
`note_bezeichnung_id` int(11) NOT NULL,
|
|
||||||
`geraet_id` int(11) NOT NULL,
|
|
||||||
`wk_id` int(11) NOT NULL,
|
|
||||||
`run_number` tinyint(3) NOT NULL DEFAULT 1,
|
|
||||||
`value` float DEFAULT NULL,
|
|
||||||
`is_public` tinyint(1) DEFAULT NULL,
|
|
||||||
`public_value` float DEFAULT NULL,
|
|
||||||
`timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
|
|
||||||
UNIQUE KEY `uniquePersonNoteJahrGereat` (`person_id`,`note_bezeichnung_id`,`wk_id`,`geraet_id`,`run_number`) USING BTREE
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `wertungen_log`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `wertungen_log` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`person_id` int(11) NOT NULL,
|
|
||||||
`note_bezeichnung_id` int(11) NOT NULL,
|
|
||||||
`geraet_id` int(11) NOT NULL,
|
|
||||||
`wk_id` int(11) NOT NULL,
|
|
||||||
`run_number` tinyint(3) NOT NULL DEFAULT 1,
|
|
||||||
`old_value` float DEFAULT NULL,
|
|
||||||
`new_value` float DEFAULT NULL,
|
|
||||||
`edited_by` int(11) NOT NULL,
|
|
||||||
`timestamp` timestamp NOT NULL DEFAULT current_timestamp(),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `wertungstypen`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `wertungstypen` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` varchar(255) NOT NULL,
|
|
||||||
`default_value` float DEFAULT NULL,
|
|
||||||
`type` enum('input','berechnung') NOT NULL DEFAULT 'input',
|
|
||||||
`berechnung` varchar(255) DEFAULT NULL,
|
|
||||||
`berechnung_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`berechnung_json`)),
|
|
||||||
`max_value` float DEFAULT NULL,
|
|
||||||
`min_value` float DEFAULT NULL,
|
|
||||||
`pro_geraet` tinyint(1) NOT NULL DEFAULT 1,
|
|
||||||
`anzahl_laeufe_json` text DEFAULT NULL,
|
|
||||||
`geraete_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '[]',
|
|
||||||
`zeige_auf_rangliste` float DEFAULT NULL,
|
|
||||||
`groesse_auf_rangliste` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`nullstellen` int(11) NOT NULL DEFAULT 2,
|
|
||||||
`display_string` varchar(63) NOT NULL DEFAULT '${note}',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `uniqueName` (`name`) USING BTREE,
|
|
||||||
KEY `indexMaxValue` (`max_value`),
|
|
||||||
KEY `indexMinValue` (`min_value`),
|
|
||||||
KEY `indexBerechnungJson` (`berechnung_json`(768)),
|
|
||||||
KEY `indexDefaultValue` (`default_value`),
|
|
||||||
KEY `indexType` (`type`),
|
|
||||||
KEY `indexNullstellen` (`nullstellen`) USING BTREE
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `wettkaempfe`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `wettkaempfe` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` varchar(256) NOT NULL,
|
|
||||||
`slug` varchar(64) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `slug` (`slug`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
-- Tabellenstruktur für Tabelle `zeitplan_types`
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
CREATE TABLE `zeitplan_types` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` varchar(2048) NOT NULL,
|
|
||||||
`has_endtime` tinyint(1) DEFAULT NULL,
|
|
||||||
`display_index` int(11) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
# Dynamically set Connection header (handles 'upgrade' and 'Upgrade')
|
|
||||||
map $http_upgrade $connection_upgrade {
|
|
||||||
default upgrade;
|
|
||||||
'' close;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
|
|
||||||
# Standard HTTP Proxy to Apache
|
|
||||||
location / {
|
|
||||||
proxy_pass http://apache:80;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# WebSocket Proxy to Node
|
|
||||||
location /ws/ {
|
|
||||||
# Note: Add trailing slash if you want Nginx to strip '/ws/' before reaching Node
|
|
||||||
proxy_pass http://node:8082/;
|
|
||||||
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $connection_upgrade; # Dynamic connection header
|
|
||||||
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
# Keep-alive settings for long-lived WebSocket connections
|
|
||||||
proxy_read_timeout 36000s;
|
|
||||||
proxy_send_timeout 36000s;
|
|
||||||
proxy_connect_timeout 75s;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Block access to hidden files (.htaccess, .git, .env, etc.)
|
|
||||||
location ~ /\. {
|
|
||||||
deny all;
|
|
||||||
access_log off;
|
|
||||||
log_not_found off;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
FROM node:20-alpine
|
|
||||||
|
|
||||||
WORKDIR /var/www/wkvs/websocket
|
|
||||||
|
|
||||||
# Install pm2 globally
|
|
||||||
RUN npm install -g pm2
|
|
||||||
|
|
||||||
# Copy package files from the websocket folder
|
|
||||||
COPY websocket/package*.json ./
|
|
||||||
|
|
||||||
# Install dependencies strictly following lockfile
|
|
||||||
RUN npm ci
|
|
||||||
|
|
||||||
# Copy the rest of the application source code from websocket folder
|
|
||||||
COPY websocket/ ./
|
|
||||||
|
|
||||||
# Change ownership to the non-root node user for security
|
|
||||||
RUN chown -R node:node /var/www/wkvs/websocket
|
|
||||||
USER node
|
|
||||||
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
CMD ["pm2-runtime", "start", "index.js"]
|
|
||||||
Vendored
BIN
Binary file not shown.
@@ -1,315 +0,0 @@
|
|||||||
:root {
|
|
||||||
--header-bg: #f8fcffcc;
|
|
||||||
--header-border: 1px solid #ffffff4d;
|
|
||||||
--header-shadow: 0 8px 32px rgba(0, 0, 0, 0.05);
|
|
||||||
--header-top: 40px;
|
|
||||||
--header-clamp: clamp(0.5px, 0.225vw, 1px);
|
|
||||||
--accent: #391c36;
|
|
||||||
--menu-box-shadows: rgba(0, 0, 0, 0.1);
|
|
||||||
--menu-dropdown-bg: #fff;
|
|
||||||
--dropdown-el-hover: #f0f0f0;
|
|
||||||
--sidebar-dropdown: rgba(255, 255, 255, 0.4);
|
|
||||||
--sidebar-dropdown-shadow: rgba(0, 0, 0, 0.02);
|
|
||||||
--sidebar-dropdown-el-hover: rgba(0, 0, 0, 0.05);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--header-bg: #000000cc; /* Dark, semi-transparent background with blur support */
|
|
||||||
--header-border: 1px solid #ffffff10; /* Subtle, soft border for dark interfaces */
|
|
||||||
--header-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); /* Stronger shadow to stand out against dark backgrounds */
|
|
||||||
--header-top: 40px;
|
|
||||||
--header-clamp: clamp(0.5px, 0.225vw, 1px);
|
|
||||||
--accent: #f9d8f7; /* Brightened, vibrant purple/pink accent to pop on dark backgrounds */
|
|
||||||
--menu-box-shadows: rgba(0, 0, 0, 0.5); /* Deeper shadow for menu items */
|
|
||||||
--menu-dropdown-bg: #1a1a1a; /* Dark solid background for dropdowns */
|
|
||||||
--dropdown-el-hover: #2a2a2a; /* Slightly lighter dark tone for hover states */
|
|
||||||
--sidebar-dropdown: rgba(30, 30, 30, 0.6); /* Semi-transparent dark background for sidebar dropdowns */
|
|
||||||
--sidebar-dropdown-shadow: rgba(0, 0, 0, 0.2);
|
|
||||||
--sidebar-dropdown-el-hover: rgba(255, 255, 255, 0.08); /* Soft white highlight on hover */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
position: fixed;
|
|
||||||
top: calc(var(--header-clamp) * 40);
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
width: calc(100% - 2 * var(--header-clamp) * 40);
|
|
||||||
max-width: var(--max-width-content);
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: calc(var(--header-clamp) * 24);
|
|
||||||
padding: calc(var(--header-clamp) * 16) calc(var(--header-clamp) * 40);
|
|
||||||
background-color: var(--header-bg);
|
|
||||||
backdrop-filter: blur(12px);
|
|
||||||
-webkit-backdrop-filter: blur(12px);
|
|
||||||
border: var(--heder-border);
|
|
||||||
box-shadow: var(--header-shadow);
|
|
||||||
z-index: 100;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rankLiveHeaderTitle {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--accent);
|
|
||||||
font-size: 24px;
|
|
||||||
letter-spacing: 1.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.menuLinksDiv {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 8px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv>a,
|
|
||||||
.menuLinksDiv>div>span {
|
|
||||||
padding: 8px 16px;
|
|
||||||
color: var(--accent);
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 1.25;
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: color 0.2s ease;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv .menu-icon {
|
|
||||||
margin-right: 8px;
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
opacity: 0.85;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv>div {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv>a::after,
|
|
||||||
.menuLinksDiv>div>span::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
left: 16px;
|
|
||||||
right: 16px;
|
|
||||||
bottom: 2px;
|
|
||||||
height: 2px;
|
|
||||||
background-color: var(--accent);
|
|
||||||
transform: scaleX(0);
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv>div>span {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv>div>span>svg.menu-chevron {
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv>div>span:hover>svg.menu-chevron,
|
|
||||||
.menuLinksDiv>div.open>span>svg.menu-chevron {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv>a:hover::after,
|
|
||||||
.menuLinksDiv>div>span:hover::after,
|
|
||||||
.menuLinksDiv>div.open>span::after {
|
|
||||||
transform: scaleX(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv .dropdown {
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
background-color: var(--menu-dropdown-bg);
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 4px 12px var(--menu-box-shadows);
|
|
||||||
padding: 8px 0;
|
|
||||||
display: none;
|
|
||||||
min-width: 160px;
|
|
||||||
z-index: 101;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv .dropdown::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: -15px;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
height: 15px;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv .dropdown a {
|
|
||||||
display: block;
|
|
||||||
padding: 8px 16px;
|
|
||||||
color: var(--accent);
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 16px;
|
|
||||||
transition: background-color 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown a:hover, .dropdown form:hover {
|
|
||||||
background-color: var(--dropdown-el-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100vh;
|
|
||||||
background-color: var(--header-bg);
|
|
||||||
backdrop-filter: blur(16px);
|
|
||||||
-webkit-backdrop-filter: blur(16px);
|
|
||||||
border-right: 1px solid rgba(255, 255, 255, 0.3);
|
|
||||||
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.06);
|
|
||||||
padding: calc(var(--header-clamp) * 60) 24px 32px 24px;
|
|
||||||
gap: 8px;
|
|
||||||
width: 288px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar>a,
|
|
||||||
.sidebar>div>.menu-item {
|
|
||||||
color: var(--accent);
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 500;
|
|
||||||
padding: 14px 16px;
|
|
||||||
border-radius: 12px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar>a:hover,
|
|
||||||
.sidebar>a:active,
|
|
||||||
.sidebar>div>.menu-item:hover,
|
|
||||||
.sidebar>div.open>.menu-item {
|
|
||||||
background-color: rgba(0, 0, 0, 0.014);
|
|
||||||
transform: translateX(4px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .menu-icon {
|
|
||||||
margin-right: 14px;
|
|
||||||
opacity: 0.85;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar>div>.menu-item>.menu-chevron {
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar>div.open>.menu-item>.menu-chevron {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .dropdown {
|
|
||||||
background-color: var(--sidebar-dropdown);
|
|
||||||
border-radius: 12px;
|
|
||||||
box-shadow: inset 0 2px 8px var(--sidebar-dropdown-shadow);
|
|
||||||
padding: 8px;
|
|
||||||
margin: 4px 16px 8px 16px;
|
|
||||||
display: none;
|
|
||||||
min-width: 160px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .dropdown a, .sidebar button {
|
|
||||||
display: block;
|
|
||||||
padding: 10px 16px;
|
|
||||||
color: var(--accent);
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 16px;
|
|
||||||
border-radius: 8px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .dropdown a:hover {
|
|
||||||
background-color: var(--sidebar-dropdown-el-hover);
|
|
||||||
transform: translateX(2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a,
|
|
||||||
.sidebar>div {
|
|
||||||
-webkit-tap-highlight-color: transparent !important;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 920px) {
|
|
||||||
|
|
||||||
.burgerMenuDiv {
|
|
||||||
display: flex !important;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: calc(var(--header-clamp) * 30);
|
|
||||||
height: calc(var(--header-clamp) * 21);
|
|
||||||
cursor: pointer;
|
|
||||||
z-index: 99;
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.burgerMenuLine {
|
|
||||||
height: calc(var(--header-clamp) * 3);
|
|
||||||
width: 100%;
|
|
||||||
background-color: var(--accent);
|
|
||||||
border-radius: calc(var(--header-clamp) * 3);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.burgerMenuDiv.active .burgerMenuLine:nth-child(1) {
|
|
||||||
transform: translateY(calc(var(--header-clamp) * 9)) rotate(45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.burgerMenuDiv.active .burgerMenuLine:nth-child(2) {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.burgerMenuDiv.active .burgerMenuLine:nth-child(3) {
|
|
||||||
transform: translateY(calc(var(--header-clamp) * -9)) rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
position: fixed;
|
|
||||||
left: 0px;
|
|
||||||
top: 0px;
|
|
||||||
height: 100vh;
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(-100%);
|
|
||||||
transition: all 0.5s cubic-bezier(0.25, 1, 0.5, 1);
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar.active {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuLinksDiv {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 921px) {
|
|
||||||
.burgerMenuDiv {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
:root {
|
|
||||||
--main: #2d2726;
|
|
||||||
--bg: #FDFDFD;
|
|
||||||
--border-subtle: #d4d7e1;
|
|
||||||
--text-main: #191919;
|
|
||||||
--text-muted: #5e5e5e;
|
|
||||||
--paddingSite: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--main: #f0f0f0; /* Flipped to a bright off-white for main accents/highlights */
|
|
||||||
--bg: #121212; /* Dark background (replacing the near-white #FDFDFD) */
|
|
||||||
--border-subtle: #2d2d2d; /* Soft, dark border that won't clip harshly against the background */
|
|
||||||
--text-main: #f5f5f5; /* Light grey/white for high readability */
|
|
||||||
--text-muted: #a0a0a0; /* Mid-tone grey for secondary text */
|
|
||||||
--paddingSite: 20px; /* Kept identical for layout consistency */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- BASE & TYPOGRAPHY --- */
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
b {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
width: 100vw;
|
|
||||||
background: var(--bg);
|
|
||||||
color: var(--text-main);
|
|
||||||
overflow-x: hidden;
|
|
||||||
overscroll-behavior: none;
|
|
||||||
font-optical-sizing: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bgSection {
|
|
||||||
position: relative;
|
|
||||||
width: 100vw;
|
|
||||||
margin: 100px auto 80px auto;
|
|
||||||
padding: var(--paddingSite);
|
|
||||||
max-width: 1800px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
.bgSection {
|
|
||||||
margin-top: 100px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerWrapper {
|
|
||||||
margin: 40px 0;
|
|
||||||
color: var(--main);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerMain {
|
|
||||||
margin: 0 0 10px 0;
|
|
||||||
font-weight: 200;
|
|
||||||
font-size: clamp(34px, 6vw, 3.5rem);
|
|
||||||
letter-spacing: 12px;
|
|
||||||
position: relative;
|
|
||||||
z-index: 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerWrapper > h4 {
|
|
||||||
margin: 0 0 10px 0;
|
|
||||||
letter-spacing: 3px;
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerAbt {
|
|
||||||
margin: 0;
|
|
||||||
font-weight: 400;
|
|
||||||
color: var(--main);
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tableCutter {
|
|
||||||
height: 120px;
|
|
||||||
z-index: 3;
|
|
||||||
width: 100%;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
background: var(--bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tableWraper {
|
|
||||||
margin: 20px 0 80px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.customDisplayEditorTable th {
|
|
||||||
top: 120px !important;
|
|
||||||
}
|
|
||||||
Vendored
BIN
Binary file not shown.
@@ -1,670 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Sprain\SwissQrBill\PaymentPart\Output\DisplayOptions;
|
|
||||||
use Sprain\SwissQrBill\PaymentPart\Output\TcPdfOutput\TcPdfOutput;
|
|
||||||
use TCPDF;
|
|
||||||
use Sprain\SwissQrBill as QrBill;
|
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
ini_set('display_errors', 1);
|
|
||||||
ini_set('display_startup_errors', 1);
|
|
||||||
error_reporting(E_ALL);
|
|
||||||
|
|
||||||
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|
||||||
|
|
||||||
require_once $baseDir . '/../scripts/session_functions.php';
|
|
||||||
|
|
||||||
ini_wkvs_session();
|
|
||||||
|
|
||||||
check_user_permission('trainer');
|
|
||||||
|
|
||||||
verify_csrf();
|
|
||||||
|
|
||||||
if (!isset($_POST['name']) || !isset($_POST['vorname']) || !isset($_POST['strasse']) || !isset($_POST['plz']) || !isset($_POST['ort'])) {
|
|
||||||
http_response_code(400);
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Daten für die Rechnungserstellung fehlen.']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function generateInvoiceNumber() : int {
|
|
||||||
return random_int(10000000, 99999999);
|
|
||||||
}
|
|
||||||
|
|
||||||
$orderType = 'Startgebühr';
|
|
||||||
|
|
||||||
function createInvoice(mysqli $conn, $db_tabelle_verbuchte_startgebueren, $orderType, $userId, $jsonIds, $used_verein_konten, $order_status): int
|
|
||||||
{
|
|
||||||
$maxRetries = 25;
|
|
||||||
|
|
||||||
for ($i = 0; $i < $maxRetries; $i++) {
|
|
||||||
|
|
||||||
$invoiceNumber = generateInvoiceNumber();
|
|
||||||
|
|
||||||
|
|
||||||
$stmt = $conn->prepare(
|
|
||||||
"INSERT INTO `$db_tabelle_verbuchte_startgebueren` (order_id, order_type, user_id, item_ids, used_verein_konten, order_status)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?)"
|
|
||||||
);
|
|
||||||
|
|
||||||
$stmt->bind_param(
|
|
||||||
"isissi",
|
|
||||||
$invoiceNumber, $orderType, $userId, $jsonIds, $used_verein_konten, $order_status
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($stmt->execute()) {
|
|
||||||
return $invoiceNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Duplicate key error → retry
|
|
||||||
if ($conn->errno !== 1062) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"Database error ({$conn->errno}): {$conn->error}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new RuntimeException('Failed to generate unique invoice number');
|
|
||||||
}
|
|
||||||
|
|
||||||
$userId = $_SESSION['user_id_trainer'];
|
|
||||||
|
|
||||||
$type = 'tr';
|
|
||||||
|
|
||||||
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
|
|
||||||
|
|
||||||
if ($data['success'] === false){
|
|
||||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
require $baseDir . '/../scripts/db/db-tables.php';
|
|
||||||
require $baseDir . '/../scripts/db/db-functions.php';
|
|
||||||
require $baseDir . '/../composer/vendor/autoload.php';
|
|
||||||
|
|
||||||
$sql = "SELECT
|
|
||||||
bi.id AS basket_id,
|
|
||||||
bi.item_id,
|
|
||||||
p.programm AS programm_name,
|
|
||||||
p.preis,
|
|
||||||
bi.id,
|
|
||||||
t.betrag_bezahlt
|
|
||||||
FROM $db_tabelle_warenkorb_startgebueren bi
|
|
||||||
LEFT JOIN $db_tabelle_teilnehmende t ON bi.item_id = t.id
|
|
||||||
LEFT JOIN $db_tabelle_kategorien p ON p.programm = t.programm
|
|
||||||
WHERE bi.user_id = ?";
|
|
||||||
|
|
||||||
$stmt = $mysqli->prepare($sql);
|
|
||||||
$stmt->bind_param("i", $userId);
|
|
||||||
$stmt->execute();
|
|
||||||
$result = $stmt->get_result();
|
|
||||||
$rows = $result->fetch_all(MYSQLI_ASSOC);
|
|
||||||
|
|
||||||
if (!$rows || count($rows) < 1) {
|
|
||||||
http_response_code(422);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$used_konten_json = $_POST['usedKonten'] ?? '{}';
|
|
||||||
|
|
||||||
$used_konten = json_decode($used_konten_json, true) ?? [];
|
|
||||||
|
|
||||||
$konten_save = [];
|
|
||||||
|
|
||||||
if (count($used_konten) > 0) {
|
|
||||||
$db_konten = db_select($mysqli, $db_tabelle_vereine, '`verein`, `konto`');
|
|
||||||
$indexed_konten = array_column($db_konten, 'konto', 'verein');
|
|
||||||
|
|
||||||
$db_user_permissions = db_get_var($mysqli, "SELECT `freigabe` FROM $db_tabelle_intern_benutzende WHERE `id` = ?", [$userId]);
|
|
||||||
|
|
||||||
$array_permissions = json_decode($db_user_permissions ?? '', true) ?? [];
|
|
||||||
|
|
||||||
$trainer_permissions = $array_permissions['freigabenTrainer'] ?? [];
|
|
||||||
|
|
||||||
foreach ($used_konten as $verein => $betrag) {
|
|
||||||
if (!isset($indexed_konten[$verein])) {
|
|
||||||
http_response_code(400);
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Invalider Verein ' . htmlspecialchars($verein)]);
|
|
||||||
exit;
|
|
||||||
} elseif (!isset($trainer_permissions[$verein]) && !in_array('admin', $trainer_permissions)) {
|
|
||||||
http_response_code(403);
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Keine Berechtigung auf den Zugriff des Kontos des Vereins ' . htmlspecialchars($verein)]);
|
|
||||||
exit;
|
|
||||||
} elseif ((float) $indexed_konten[$verein] < (float) $betrag) {
|
|
||||||
http_response_code(403);
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Der Abzug des Vereins ' . htmlspecialchars($verein) . ' übersteigt das Guthaben dieses Vereins.']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$konten_save[$verein] = (float) $betrag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$used_verein_konten = json_encode($konten_save);
|
|
||||||
|
|
||||||
$preis = 0;
|
|
||||||
|
|
||||||
$ids = [];
|
|
||||||
|
|
||||||
foreach ($rows as $r) {
|
|
||||||
$r_preis = max(floatval($r['preis']) - floatval($r['betrag_bezahlt']), 0);
|
|
||||||
$preis += $r_preis;
|
|
||||||
$ids[$r['item_id']] = $r_preis;
|
|
||||||
}
|
|
||||||
|
|
||||||
$preis = min($preis - array_sum($konten_save), 0);
|
|
||||||
|
|
||||||
$jsonIds = json_encode($ids);
|
|
||||||
|
|
||||||
$all_teilnehmende_ids = array_keys($ids);
|
|
||||||
|
|
||||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
||||||
http_response_code(400);
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Invalid JSON']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Check for existing open order ---
|
|
||||||
$order_id = db_get_var($mysqli, "SELECT order_id FROM `$db_tabelle_verbuchte_startgebueren` WHERE user_id = ? AND order_status = 0 LIMIT 1", [$userId]);
|
|
||||||
|
|
||||||
$orderId = null;
|
|
||||||
|
|
||||||
if ($order_id === null) {
|
|
||||||
// --- INSERT new order ---
|
|
||||||
$stmt->close();
|
|
||||||
|
|
||||||
$order_status = 0;
|
|
||||||
|
|
||||||
$new_id = createInvoice($mysqli, $db_tabelle_verbuchte_startgebueren, $orderType, $userId, $jsonIds, $used_verein_konten, $order_status);
|
|
||||||
|
|
||||||
$orderId = $new_id;
|
|
||||||
} else {
|
|
||||||
// --- UPDATE existing order ---
|
|
||||||
$stmt->close();
|
|
||||||
|
|
||||||
$orderId = $order_id;
|
|
||||||
|
|
||||||
$sql = "
|
|
||||||
UPDATE `$db_tabelle_verbuchte_startgebueren`
|
|
||||||
SET item_ids = ?, used_verein_konten = ?
|
|
||||||
WHERE order_id = ?
|
|
||||||
";
|
|
||||||
|
|
||||||
$stmt = $mysqli->prepare($sql);
|
|
||||||
$stmt->bind_param("ssi", $jsonIds, $used_verein_konten, $order_id);
|
|
||||||
$stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
$keys = [
|
|
||||||
'wkName', 'rechnungenName', 'rechnungenVorname', 'rechnungenStrasse',
|
|
||||||
'rechnungenHausnummer', 'rechnungenPostleitzahl', 'rechnungenOrt',
|
|
||||||
'rechnungenIBAN', 'linkWebseite', 'rechnungenPostversand', 'rechnungenPostversandKosten'
|
|
||||||
];
|
|
||||||
|
|
||||||
$placeholders = implode(',', array_fill(0, count($keys), '?'));
|
|
||||||
|
|
||||||
$stmt = $mysqli->prepare("SELECT `name`, `value` FROM $db_tabelle_var WHERE `name` IN ($placeholders)");
|
|
||||||
$stmt->bind_param(str_repeat('s', count($keys)), ...$keys);
|
|
||||||
$stmt->execute();
|
|
||||||
|
|
||||||
|
|
||||||
$variables = array_column($stmt->get_result()->fetch_all(MYSQLI_ASSOC), 'value', 'name');
|
|
||||||
|
|
||||||
$kats = db_select($mysqli, $db_tabelle_kategorien, '`programm`, `preis`');
|
|
||||||
|
|
||||||
$indexed_kats_preis = array_column($kats, 'preis', 'programm');
|
|
||||||
|
|
||||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
|
||||||
|
|
||||||
$current_wk_name = db_get_var($mysqli, "SELECT `name` FROM $db_tabelle_wettkaempfe WHERE `id` = ? LIMIT 1", [$current_wk_id]) ?: ($wkName . ' ' . $current_year);
|
|
||||||
class MYPDF extends TCPDF
|
|
||||||
{
|
|
||||||
public $columns;
|
|
||||||
public $headerBottomY = 0;
|
|
||||||
public $firstPageDone = false; // track first page
|
|
||||||
public $abzuegeHeader = false; // track first page
|
|
||||||
public $printfooter;
|
|
||||||
|
|
||||||
public function Header()
|
|
||||||
{
|
|
||||||
// Logo always
|
|
||||||
$image_file = $_SERVER['DOCUMENT_ROOT'] . '/intern/img/logo-normal.png';
|
|
||||||
$this->Image($image_file, 180, 15, 15);
|
|
||||||
|
|
||||||
// Table header only for subsequent pages
|
|
||||||
if ($this->abzuegeHeader) {
|
|
||||||
// Use same top margin as table
|
|
||||||
$this->SetY(35); // or another fixed Y
|
|
||||||
$this->SetX(15);
|
|
||||||
$this->SetFont('GoogleSansFlex-Regular', '', 11);
|
|
||||||
$this->setCellPaddings(2, 0, 2, 0);
|
|
||||||
$this->Cell($this->columns['name']['max_width'] + $this->columns['programm']['max_width'] + $this->columns['verein']['max_width'], 10, 'Beschreibung', 0, 0, 'L');
|
|
||||||
$this->Cell($this->columns['preis']['max_width'], 10, 'Abzug', 0, 0, 'C');
|
|
||||||
$this->Ln();
|
|
||||||
$this->headerBottomY = $this->GetY();
|
|
||||||
$this->SetLineWidth(0.6);
|
|
||||||
$this->Line(15, $this->GetY(), 210 - 15, $this->GetY());
|
|
||||||
$this->SetLineWidth(0.2);
|
|
||||||
} elseif ($this->firstPageDone && !empty($this->columns)) {
|
|
||||||
// Use same top margin as table
|
|
||||||
$this->SetY(35); // or another fixed Y
|
|
||||||
$this->SetX(15);
|
|
||||||
$this->SetFont('GoogleSansFlex-Regular', '', 11);
|
|
||||||
$this->setCellPaddings(2, 0, 2, 0);
|
|
||||||
foreach ($this->columns as $c) {
|
|
||||||
$this->Cell($c['max_width'], 10, $c['header'], 0, 0, 'L');
|
|
||||||
}
|
|
||||||
$this->Ln();
|
|
||||||
$this->headerBottomY = $this->GetY();
|
|
||||||
$this->SetLineWidth(0.6);
|
|
||||||
$this->Line(15, $this->GetY(), 210 - 15, $this->GetY());
|
|
||||||
$this->SetLineWidth(0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Footer()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Create PDF ---
|
|
||||||
$pdf = new MYPDF('P', 'mm', 'A4', true, 'UTF-8', false);
|
|
||||||
$pdf->current_year = (date('n') > 6) ? date('Y') + 1 : date('Y');
|
|
||||||
|
|
||||||
$pdf->wkp_name = trim(($variables['rechnungenVorname'] ?? '') . ' ' . ($variables['rechnungenName'] ?? ''));
|
|
||||||
$pdf->wkp_adresse = trim(($variables['rechnungenStrasse'] ?? '') . ' ' . ($variables['rechnungenHausnummer'] ?? ''));
|
|
||||||
$pdf->wkp_plz_ort = trim(($variables['rechnungenPostleitzahl'] ?? '') . ' ' . ($variables['rechnungenOrt'] ?? ''));
|
|
||||||
$pdf->wkp_url = $variables['linkWebseite'] ?? '';
|
|
||||||
$pdf->wk_name = $variables['wkName'] ?? '';
|
|
||||||
|
|
||||||
$pdf->pers_name = trim(($_POST['vorname'] ?? '') . ' ' . ($_POST['name'] ?? ''));
|
|
||||||
$pdf->pers_adresse = trim(($_POST['strasse'] ?? '') . ' ' . ($_POST['hausnummer'] ?? ''));
|
|
||||||
$pdf->pers_plz_ort = trim(($_POST['plz'] ?? '') . ' ' . ($_POST['ort'] ?? ''));
|
|
||||||
|
|
||||||
$pdf->printfooter = true;
|
|
||||||
$pdf->current_wk_name = $current_wk_name;
|
|
||||||
|
|
||||||
// Mark first page done so Header() prints table headers on subsequent pages
|
|
||||||
$pdf->firstPageDone = false;
|
|
||||||
|
|
||||||
$pdf->setCellPaddings(2, 0, 2, 0);
|
|
||||||
|
|
||||||
$pdf->SetMargins(15, 35, 15);
|
|
||||||
|
|
||||||
// Fonts
|
|
||||||
$pdf->AddFont('GoogleSansFlex9pt-Bold', '', $_SERVER['DOCUMENT_ROOT'] . '/../private-files/tcpdf-fonts/googlesansflex_9ptb.php');
|
|
||||||
$pdf->AddFont('GoogleSansFlex-Regular', '', $_SERVER['DOCUMENT_ROOT'] . '/../private-files/tcpdf-fonts/gsf.php');
|
|
||||||
|
|
||||||
$pdf->SetCreator(PDF_CREATOR);
|
|
||||||
$pdf->SetAuthor('WKVS');
|
|
||||||
$pdf->SetAutoPageBreak(TRUE, 10);
|
|
||||||
|
|
||||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 11);
|
|
||||||
|
|
||||||
// --- Add a page ---
|
|
||||||
$pdf->AddPage();
|
|
||||||
|
|
||||||
// --- Sender block (left) ---
|
|
||||||
$pdf->SetX(15);
|
|
||||||
$pdf->Cell(0, 0, $pdf->wkp_name, 0, 1);
|
|
||||||
$pdf->Cell(0, 0, $pdf->wkp_adresse, 0, 1);
|
|
||||||
$pdf->Cell(0, 0, $pdf->wkp_plz_ort, 0, 1);
|
|
||||||
$pdf->Ln(7);
|
|
||||||
$pdf->Cell(0, 0, $pdf->wkp_url, 0, 1);
|
|
||||||
|
|
||||||
// --- Recipient block (right / window) ---
|
|
||||||
$x = 110; // X coordinate for right window
|
|
||||||
$y = 50; // Y coordinate
|
|
||||||
$w = 80; // Width of recipient block
|
|
||||||
|
|
||||||
$address = implode("\n", [
|
|
||||||
$pdf->pers_name,
|
|
||||||
$pdf->pers_adresse,
|
|
||||||
$pdf->pers_plz_ort
|
|
||||||
]);
|
|
||||||
|
|
||||||
$pdf->MultiCell($w, 5, $address, 0, 'L', false, 1, $x, $y, true);
|
|
||||||
|
|
||||||
date_default_timezone_set('UTC');
|
|
||||||
|
|
||||||
// --- Invoice title ---
|
|
||||||
$pdf->Ln(20); // space below recipient
|
|
||||||
$pdf->SetFont('GoogleSansFlex9pt-Bold', '', 15);
|
|
||||||
$pdf->Cell(0, 10, 'Startgebührenrechnung ' . $pdf->current_wk_name, 0, 1, 'L');
|
|
||||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 10);
|
|
||||||
$pdf->Cell(0, 9, "Rechnungsnummer: " . $orderId, 0, 1, 'L');
|
|
||||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 7);
|
|
||||||
$pdf->Cell(0, 0, "Ausstellungsdatum: " . date("d.m.y"), 0, 1, 'L');
|
|
||||||
|
|
||||||
$pdf->Ln(10); // space below title
|
|
||||||
|
|
||||||
$pdf->SetFont('GoogleSansFlex9pt-Bold', '', 13);
|
|
||||||
|
|
||||||
//$turnerinnnenIds = [];
|
|
||||||
|
|
||||||
$placeholders = implode(', ', array_fill(0, count($all_teilnehmende_ids), '?'));
|
|
||||||
|
|
||||||
$all_teilnehmende = db_select($mysqli, $db_tabelle_teilnehmende, '`id`, name, vorname, programm, verein, `betrag_bezahlt`', "id IN ($placeholders)", $all_teilnehmende_ids);
|
|
||||||
|
|
||||||
$all_teilnehmende_indexed = array_column($all_teilnehmende, null, 'id');
|
|
||||||
|
|
||||||
$columns = ['name' => ['header' => 'Name'],
|
|
||||||
'programm' => ['header' => 'Programm'],
|
|
||||||
'verein' => ['header' => 'Verein'],
|
|
||||||
'preis' => ['header' => 'Startgebühr']];
|
|
||||||
|
|
||||||
foreach ($columns as $key => $column){
|
|
||||||
$columns[$key]['max_width'] = $pdf->GetStringWidth($column['header']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$totalPreis = 0.00;
|
|
||||||
|
|
||||||
$dbdata = [];
|
|
||||||
|
|
||||||
foreach ($ids as $singleid => $s_preis){
|
|
||||||
|
|
||||||
if (!isset($all_teilnehmende_indexed[$singleid])) continue;
|
|
||||||
|
|
||||||
$row = &$all_teilnehmende_indexed[$singleid];
|
|
||||||
|
|
||||||
if (count($row) !== 6) continue;
|
|
||||||
|
|
||||||
$float_preis = (float) $s_preis;
|
|
||||||
|
|
||||||
$formated_preis = number_format($float_preis, 2, '.', "'");
|
|
||||||
|
|
||||||
$totalPreis += $float_preis;
|
|
||||||
|
|
||||||
$row['formated_preis'] = $formated_preis;
|
|
||||||
|
|
||||||
$programm = $row['programm'] ?? '';
|
|
||||||
$kosten_kat_normal = (float) ($indexed_kats_preis[$programm] ?? 0.00);
|
|
||||||
|
|
||||||
$preis_text = $float_preis !== $kosten_kat_normal ? 'Die Startgebühren dieser Person wurden reduziert, da diese Person bereits CHF ' . number_format($row['betrag_bezahlt'], 2, '.', "'") . ' an Startgebühren zahlte' : '';
|
|
||||||
|
|
||||||
$row['preis_text'] = $preis_text;
|
|
||||||
|
|
||||||
$pdf->SetFont('', '', 10);
|
|
||||||
$text = 'Startgebühr '. ($row['name'] ?? '') .' '. ($row['vorname'] ?? '');
|
|
||||||
|
|
||||||
$text_width = $pdf->GetStringWidth($text);
|
|
||||||
$kat_width = $pdf->GetStringWidth($row['programm'] ?? '');
|
|
||||||
$verein_width = $pdf->GetStringWidth($row['verein'] ?? '');
|
|
||||||
$preis_width = $pdf->GetStringWidth('CHF '. $formated_preis);
|
|
||||||
|
|
||||||
$columns['name']['max_width'] = max($columns['name']['max_width'] ?? 0, $text_width);
|
|
||||||
$columns['programm']['max_width'] = max($columns['programm']['max_width'] ?? 0, $kat_width);
|
|
||||||
$columns['verein']['max_width'] = max($columns['verein']['max_width'] ?? 0, $verein_width);
|
|
||||||
$columns['preis']['max_width'] = max($columns['preis']['max_width'] ?? 0, $preis_width);
|
|
||||||
}
|
|
||||||
|
|
||||||
unset($row);
|
|
||||||
|
|
||||||
|
|
||||||
foreach ($columns as $key => $column){
|
|
||||||
$columns[$key]['max_width'] += 2; // Add some padding
|
|
||||||
}
|
|
||||||
|
|
||||||
$maxWidth = 210 - 30; // A4 width minus margins
|
|
||||||
$totalColumnWidth = 0;
|
|
||||||
foreach ($columns as $column){
|
|
||||||
$totalColumnWidth += $column['max_width'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($totalColumnWidth < $maxWidth){
|
|
||||||
$scalingFactor = $maxWidth / $totalColumnWidth;
|
|
||||||
foreach ($columns as $key => $column){
|
|
||||||
$columns[$key]['max_width'] = $column['max_width'] * $scalingFactor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($columns as $c) {
|
|
||||||
$pdf->Cell($c['max_width'], 10, $c['header'], 0, 0, 'L');
|
|
||||||
}
|
|
||||||
$pdf->Ln();
|
|
||||||
|
|
||||||
$pdf->SetLineWidth(0.6);
|
|
||||||
$pdf->Line(15, $pdf->GetY(), 210 - 15, $pdf->GetY());
|
|
||||||
$pdf->SetLineWidth(0.2);
|
|
||||||
|
|
||||||
$pdf->headerBottomY = $pdf->GetY();
|
|
||||||
|
|
||||||
// --- Set top margin for table below title ---
|
|
||||||
|
|
||||||
// Mark first page done so Header() prints table headers on subsequent pages
|
|
||||||
$pdf->firstPageDone = true;
|
|
||||||
|
|
||||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 11);
|
|
||||||
|
|
||||||
$pdf->columns = $columns;
|
|
||||||
|
|
||||||
$margin_top = $pdf->headerBottomY;
|
|
||||||
|
|
||||||
$pdf->SetMargins(15, 45, 15); // +5 mm padding below header
|
|
||||||
$pdf->SetY($margin_top); // Move cursor below header manually
|
|
||||||
|
|
||||||
foreach ($all_teilnehmende_indexed as $s_id => $row){
|
|
||||||
$pdf->SetFont('', '', 10);
|
|
||||||
|
|
||||||
$text = 'Startgebühr '. ($row['name'] ?? '') .' '. ($row['vorname'] ?? '');
|
|
||||||
|
|
||||||
$pdf->Cell($columns['name']['max_width'], 10, $text, 0, 0, 'L');
|
|
||||||
$pdf->Cell($columns['programm']['max_width'], 10, $row['programm'] ?? '', 0, 0, 'L');
|
|
||||||
$pdf->Cell($columns['verein']['max_width'], 10, $row['verein'] ?? '', 0, 0, 'L');
|
|
||||||
|
|
||||||
$pdf->SetFillColor(100, 100, 100);
|
|
||||||
|
|
||||||
$formated_preis = $row['formated_preis'] ?? '';
|
|
||||||
|
|
||||||
$pdf->Cell($columns['preis']['max_width'], 10, 'CHF ' . $formated_preis, 0, 1, 'C');
|
|
||||||
|
|
||||||
if ($row['preis_text'] !== '') {
|
|
||||||
$pdf->SetY($pdf->getY() - 3);
|
|
||||||
$pdf->SetFont('', '', 6);
|
|
||||||
$pdf->Cell(195, 6, $row['preis_text'], 0, 1, 'L');
|
|
||||||
$pdf->SetFont('', '', 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
$pdf->SetDrawColor(100, 100, 100);
|
|
||||||
$pdf->Line(15, $pdf->getY(), 210 - 15, $pdf->getY());
|
|
||||||
$pdf->SetDrawColor(0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($variables['rechnungenPostversand'] && isset($_POST['postversand'])) {
|
|
||||||
$pdf->SetFont('', '', 10);
|
|
||||||
|
|
||||||
$text = 'Postversand der Rechnung';
|
|
||||||
$pdf->Cell($columns['name']['max_width'], 10, $text, 0, 0, 'L');
|
|
||||||
$pdf->Cell($columns['programm']['max_width'], 10, '', 0, 0, 'L');
|
|
||||||
$pdf->Cell($columns['verein']['max_width'], 10, '', 0, 0, 'L');
|
|
||||||
|
|
||||||
$pdf->SetFillColor(100, 100, 100);
|
|
||||||
|
|
||||||
$pdf->Cell($columns['preis']['max_width'], 10, 'CHF '. number_format(floatval($variables['rechnungenPostversandKosten'] ?? 0), 2, ".", "'"), 0, 1, 'C');
|
|
||||||
|
|
||||||
$pdf->SetDrawColor(100, 100, 100);
|
|
||||||
$pdf->Line(15, $pdf->getY(), 210 - 15, $pdf->getY());
|
|
||||||
$pdf->SetDrawColor(0, 0, 0);
|
|
||||||
|
|
||||||
$totalPreis += floatval($variables['rechnungenPostversandKosten'] ?? 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($konten_save) > 0) {
|
|
||||||
$pdf->Ln(8);
|
|
||||||
$pdf->SetFont('GoogleSansFlex9pt-Bold', '', 10);
|
|
||||||
$pdf->Cell(0, 10, 'Abzüge (Vereinsguthaben)', 0, 1, 'L');
|
|
||||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 10);
|
|
||||||
|
|
||||||
$pdf->SetFont('GoogleSansFlex9pt-Bold', '', 11);
|
|
||||||
$pdf->Cell($columns['name']['max_width'] + $columns['programm']['max_width'] + $columns['verein']['max_width'], 10, 'Beschreibung', 0, 0, 'L');
|
|
||||||
$pdf->Cell($columns['preis']['max_width'], 10, 'Abzug', 0, 0, 'C');
|
|
||||||
$pdf->Ln();
|
|
||||||
$pdf->SetLineWidth(0.6);
|
|
||||||
$pdf->Line(15, $pdf->GetY(), 210 - 15, $pdf->GetY());
|
|
||||||
$pdf->SetLineWidth(0.2);
|
|
||||||
|
|
||||||
$pdf->abzuegeHeader = true;
|
|
||||||
|
|
||||||
foreach ($konten_save as $verein => $betrag) {
|
|
||||||
$pdf->SetFont('', '', 10);
|
|
||||||
|
|
||||||
$text = 'Guthaben '. $verein;
|
|
||||||
|
|
||||||
$pdf->Cell($columns['name']['max_width'] + $columns['programm']['max_width'] + $columns['verein']['max_width'], 10, $text, 0, 0, 'L');
|
|
||||||
$pdf->SetFillColor(100, 100, 100);
|
|
||||||
|
|
||||||
$formated_preis = number_format(floatval($betrag ?? 0), 2, ".", "'");
|
|
||||||
|
|
||||||
$pdf->Cell($columns['preis']['max_width'], 10, '- CHF ' . $formated_preis, 0, 1, 'C');
|
|
||||||
|
|
||||||
$pdf->SetDrawColor(100, 100, 100);
|
|
||||||
$pdf->Line(15, $pdf->getY(), 210 - 15, $pdf->getY());
|
|
||||||
$pdf->SetDrawColor(0, 0, 0);
|
|
||||||
|
|
||||||
$totalPreis -= (float) $betrag;
|
|
||||||
}
|
|
||||||
|
|
||||||
$pdf->abzuegeHeader = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$pdf->Ln(3);
|
|
||||||
$pdf->SetFont('GoogleSansFlex9pt-Bold', '', 10);
|
|
||||||
$pdf->Cell(100, 10, "Gesamt:", 0, 0, 'L');
|
|
||||||
$pdf->SetX($columns['name']['max_width'] + $columns['programm']['max_width'] + $columns['verein']['max_width'] + 15);
|
|
||||||
$pdf->Cell($columns['preis']['max_width'], 10, 'CHF ' . number_format($totalPreis, 2, ".", "'"), 0, 1, 'C');
|
|
||||||
$pdf->SetFont('GoogleSansFlex-Regular', '', 10);
|
|
||||||
|
|
||||||
$cent_total_preis = (int) round($totalPreis * 100);
|
|
||||||
|
|
||||||
$rechnung_is_null = $cent_total_preis === 0;
|
|
||||||
|
|
||||||
if ($rechnung_is_null) {
|
|
||||||
$pdf->Ln(10);
|
|
||||||
$pdf->SetTextColor(90, 103, 39);
|
|
||||||
$pdf->MultiCell(0, 8, 'Diese Rechnung wurde als bezahlt eingetragen, da der Betrag CHF 0.00 beträgt', 0, 'L');
|
|
||||||
$pdf->SetTextColor(0, 0, 0);
|
|
||||||
} else {
|
|
||||||
$qrBill = QrBill\QrBill::create();
|
|
||||||
|
|
||||||
$qrBill->setCreditor(
|
|
||||||
QrBill\DataGroup\Element\StructuredAddress::createWithStreet(
|
|
||||||
$pdf->wkp_name,
|
|
||||||
trim($variables['rechnungenStrasse'] ?? ''),
|
|
||||||
trim($variables['rechnungenHausnummer'] ?? ''),
|
|
||||||
trim($variables['rechnungenPostleitzahl'] ?? ''),
|
|
||||||
trim($variables['rechnungenOrt'] ?? ''),
|
|
||||||
'CH'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$iban = strtoupper(str_replace(' ', '', (string)($variables['rechnungenIBAN'] ?? '')));
|
|
||||||
|
|
||||||
$qrBill->setCreditorInformation(
|
|
||||||
QrBill\DataGroup\Element\CreditorInformation::create($iban)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add debtor information
|
|
||||||
// Who has to pay the invoice? This part is optional.
|
|
||||||
$qrBill->setUltimateDebtor(
|
|
||||||
QrBill\DataGroup\Element\StructuredAddress::createWithStreet(
|
|
||||||
$_POST['vorname'] . ' ' . $_POST['name'],
|
|
||||||
$_POST['strasse'],
|
|
||||||
$_POST['hausnummer'],
|
|
||||||
$_POST['plz'],
|
|
||||||
$_POST['ort'],
|
|
||||||
'CH'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add payment amount information
|
|
||||||
// What amount is to be paid?
|
|
||||||
$qrBill->setPaymentAmountInformation(
|
|
||||||
QrBill\DataGroup\Element\PaymentAmountInformation::create(
|
|
||||||
'CHF',
|
|
||||||
$totalPreis
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add payment reference
|
|
||||||
// This is what you will need to identify incoming payments.
|
|
||||||
$qrBill->setPaymentReference(
|
|
||||||
QrBill\DataGroup\Element\PaymentReference::create(
|
|
||||||
QrBill\DataGroup\Element\PaymentReference::TYPE_SCOR,
|
|
||||||
QrBill\Reference\RfCreditorReferenceGenerator::generate($orderId)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$referenz = "Startgebührenrechnung ". $pdf->wkp_name;
|
|
||||||
|
|
||||||
// Optionally, add some human-readable information about what the bill is for.
|
|
||||||
$qrBill->setAdditionalInformation(
|
|
||||||
QrBill\DataGroup\Element\AdditionalInformation::create(
|
|
||||||
$referenz
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// 3. Create a full payment part for TcPDF
|
|
||||||
$output = new TcPdfOutput($qrBill, 'de', $pdf);
|
|
||||||
|
|
||||||
// 4. Optional, set layout options
|
|
||||||
if (class_exists(DisplayOptions::class)) {
|
|
||||||
$displayOptions = new DisplayOptions();
|
|
||||||
$displayOptions
|
|
||||||
->setPrintable(false) // true to remove lines for printing on a perforated stationery
|
|
||||||
->setDisplayTextDownArrows(false) // true to show arrows next to separation text, if shown
|
|
||||||
->setDisplayScissors(false) // true to show scissors instead of separation text
|
|
||||||
->setPositionScissorsAtBottom(false) // true to place scissors at the bottom, if shown
|
|
||||||
;
|
|
||||||
|
|
||||||
// 5. Generate the output, applying display options when supported
|
|
||||||
if (method_exists($output, 'setDisplayOptions')) {
|
|
||||||
$output->setDisplayOptions($displayOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($pdf->getY() > 297 - 120) {
|
|
||||||
$pdf->firstPageDone = false;
|
|
||||||
$pdf->printfooter = false;
|
|
||||||
$pdf->addPage();
|
|
||||||
}
|
|
||||||
$output->getPaymentPart();
|
|
||||||
}
|
|
||||||
|
|
||||||
$filename = 'Rechnung Startgebuehren '.$current_wk_name.' '.date('YmdHis').'.pdf';
|
|
||||||
|
|
||||||
$pdf->SetTitle($filename);
|
|
||||||
|
|
||||||
$savePath = $baseDir . '/../private-files/rechnungen/' . $orderId . '.pdf';
|
|
||||||
|
|
||||||
// Save PDF to disk
|
|
||||||
$pdf->Output($savePath, 'F');
|
|
||||||
|
|
||||||
$orderStatus = $rechnung_is_null ? 2 : 1 ;
|
|
||||||
|
|
||||||
$sql = "UPDATE $db_tabelle_verbuchte_startgebueren SET order_status = ?, `preis` = ? WHERE order_id = ?";
|
|
||||||
|
|
||||||
$stmt = $mysqli->prepare($sql);
|
|
||||||
$stmt->bind_param("idi", $orderStatus, $totalPreis, $orderId);
|
|
||||||
$stmt->execute();
|
|
||||||
$stmt->close();
|
|
||||||
|
|
||||||
require $baseDir . '/../scripts/rechnungen/rechnungs-functions.php';
|
|
||||||
|
|
||||||
update_teilnehmende($ids, 0, $orderStatus, true);
|
|
||||||
update_konten_vereine($konten_save, 0, $orderStatus, true);
|
|
||||||
|
|
||||||
// 2. DELETE basket items
|
|
||||||
db_delete($mysqli, $db_tabelle_warenkorb_startgebueren, ['user_id' => intval($userId)]);
|
|
||||||
|
|
||||||
$mysqli->close();
|
|
||||||
|
|
||||||
// Send headers manually
|
|
||||||
header('Content-Type: application/pdf');
|
|
||||||
header('Content-Disposition: attachment; filename="' . $dirFileName . '"');
|
|
||||||
header('Content-Length: ' . filesize($savePath));
|
|
||||||
|
|
||||||
// Send file contents
|
|
||||||
readfile($savePath);
|
|
||||||
exit;
|
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
|
|
||||||
if (!isset($baseDir))
|
|
||||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|
||||||
|
|
||||||
require_once $baseDir . '/../scripts/session_functions.php';
|
|
||||||
|
|
||||||
ini_wkvs_session();
|
|
||||||
|
|
||||||
check_user_permission('trainer');
|
|
||||||
|
|
||||||
verify_csrf();
|
|
||||||
|
|
||||||
$personen_ids_json = $_POST['personen_ids'] ?? '';
|
|
||||||
|
|
||||||
$personen_ids = json_decode($personen_ids_json) ?? [];
|
|
||||||
|
|
||||||
$personen_ids = !is_array($personen_ids) ? array(intval($personen_ids)) : array_map('intval', $personen_ids);
|
|
||||||
|
|
||||||
if (count($personen_ids) < 1) {
|
|
||||||
echo json_encode(['success' => false, 'message' => "Keine Personen angegeben"]);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$neu_kat_id = (int) $_POST['kat_id'] ?? 0;
|
|
||||||
|
|
||||||
if ($neu_kat_id < 1) {
|
|
||||||
echo json_encode(['success' => false, 'message' => "Keine neue Kategorie angegeben"]);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
require $baseDir . '/../scripts/db/db-functions.php';
|
|
||||||
require $baseDir . '/../scripts/db/db-tables.php';
|
|
||||||
|
|
||||||
$type = 'tr';
|
|
||||||
|
|
||||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
|
||||||
|
|
||||||
if ($dbconnection['success'] !== true) {
|
|
||||||
echo 'Critical DB Error.';
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$all_kats = db_select($mysqli, $db_tabelle_kategorien, "`id`, `programm`, `preis`");
|
|
||||||
|
|
||||||
$all_kats_id_indexed = array_column($all_kats, null, 'id');
|
|
||||||
|
|
||||||
$preise_kats = array_column($all_kats, 'preis', 'programm');
|
|
||||||
|
|
||||||
if (!isset($all_kats_id_indexed[$neu_kat_id])) {
|
|
||||||
echo json_encode(['success' => false, 'message' => "Nicht valide Kategorie"]);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$new_kat_name = $all_kats_id_indexed[$neu_kat_id]['programm'];
|
|
||||||
$new_kat_preis = $all_kats_id_indexed[$neu_kat_id]['preis'];
|
|
||||||
$vereine_plus_array = [];
|
|
||||||
|
|
||||||
function get_kat_price_diff(array $old_data, string $new_kat): array {
|
|
||||||
global $preise_kats;
|
|
||||||
global $vereine_plus_array;
|
|
||||||
|
|
||||||
$return_array = [];
|
|
||||||
|
|
||||||
$old_kat = $old_data['programm'] ?? '';
|
|
||||||
$verein = $old_data['verein'] ?? '';
|
|
||||||
$bezahlt = (int) ($old_data['bezahlt'] ?? 1);
|
|
||||||
|
|
||||||
var_dump(!isset($preise_kats[$new_kat]), !in_array($bezahlt, [2, 4], true), $old_kat === $new_kat, $old_kat === '', $old_kat, $new_kat);
|
|
||||||
|
|
||||||
if ($old_kat === '' || $old_kat === $new_kat || !in_array($bezahlt, [2, 4], true) || !isset($preise_kats[$new_kat])) {
|
|
||||||
return $return_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
$betrag_bezahlt = (float) ($old_data['betrag_bezahlt'] ?? 0.00);
|
|
||||||
$new_kat_preis = (float) $preise_kats[$new_kat];
|
|
||||||
|
|
||||||
if ($new_kat_preis > $betrag_bezahlt) {
|
|
||||||
$return_array['bezahlt'] = ($betrag_bezahlt === 0.00) ? 1 : 2;
|
|
||||||
} elseif ($new_kat_preis < $betrag_bezahlt) {
|
|
||||||
$return_array['bezahlt'] = 4;
|
|
||||||
$return_array['betrag_bezahlt'] = $betrag_bezahlt - $new_kat_preis;
|
|
||||||
$vereine_plus_array[$verein] = ((float) ($vereine_plus_array[$verein] ?? 0.00)) + $betrag_bezahlt - $new_kat_preis;
|
|
||||||
} else {
|
|
||||||
$return_array['bezahlt'] = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $return_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
function update_verein_balances(array $vereine_plus_array_funct) {
|
|
||||||
global $mysqli;
|
|
||||||
global $db_tabelle_vereine;
|
|
||||||
|
|
||||||
if (empty($vereine_plus_array_funct)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $mysqli->prepare("UPDATE $db_tabelle_vereine SET `konto` = `konto` + ? WHERE `verein` = ?");
|
|
||||||
|
|
||||||
if ($stmt) {
|
|
||||||
foreach ($vereine_plus_array_funct as $verein => $betrag) {
|
|
||||||
if ($betrag <= 0.00) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt->bind_param("ds", $betrag, $verein);
|
|
||||||
$stmt->execute();
|
|
||||||
}
|
|
||||||
$stmt->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove_from_basket(array $ids_array = []) : bool {
|
|
||||||
global $mysqli;
|
|
||||||
global $db_tabelle_warenkorb_startgebueren;
|
|
||||||
|
|
||||||
if (empty($ids_array)) return true;
|
|
||||||
|
|
||||||
$tplaceholders = implode(", ", array_fill(0, count($ids_array), "?"));
|
|
||||||
|
|
||||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_warenkorb_startgebueren WHERE `item_id` IN ($tplaceholders)");
|
|
||||||
$stmt->bind_param(str_repeat('i', count($ids_array)), ...$ids_array);
|
|
||||||
$ret = $stmt->execute();
|
|
||||||
$stmt->close();
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Data Processing & Transaction Block
|
|
||||||
$placeholders = implode(", ", array_fill(0, count($personen_ids), "?"));
|
|
||||||
$entries = db_select($mysqli, $db_tabelle_teilnehmende, "`id`, `programm`, `bezahlt`, `betrag_bezahlt`, `verein`", "`id` IN ($placeholders)", $personen_ids);
|
|
||||||
|
|
||||||
$mysqli->begin_transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
$stmtbez = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende SET `bezahlt` = ?, `programm` = ? WHERE `id` = ?");
|
|
||||||
$stmtbezbet = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende SET `bezahlt` = ?, `programm` = ?, `betrag_bezahlt` = ? WHERE `id` = ?");
|
|
||||||
$stmtnorm = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende SET `programm` = ? WHERE `id` = ?");
|
|
||||||
|
|
||||||
$status_update_bez = null;
|
|
||||||
$current_id_bez = null;
|
|
||||||
$stmtbez->bind_param("isi", $status_update_bez, $new_kat_name, $current_id_bez);
|
|
||||||
|
|
||||||
$status_update_bet_bez = null;
|
|
||||||
$current_id_bet_bez = null;
|
|
||||||
$betrag_bezahlt = null;
|
|
||||||
$stmtbezbet->bind_param("isdi", $status_update_bet_bez, $new_kat_name, $betrag_bezahlt, $current_id_bet_bez);
|
|
||||||
|
|
||||||
$current_id_norm = null;
|
|
||||||
$stmtnorm->bind_param("si", $new_kat_name, $current_id_norm);
|
|
||||||
|
|
||||||
foreach ($entries as $s_entry) {
|
|
||||||
$res = get_kat_price_diff($s_entry, $new_kat_name);
|
|
||||||
|
|
||||||
if (count($res) < 1) {
|
|
||||||
$current_id_norm = $s_entry['id'];
|
|
||||||
$stmtnorm->execute();
|
|
||||||
} elseif (isset($res['betrag_bezahlt'])){
|
|
||||||
$status_update_bet_bez = $res['bezahlt'];
|
|
||||||
$current_id_bet_bez = $s_entry['id'];
|
|
||||||
$betrag_bezahlt = $res['betrag_bezahlt'];
|
|
||||||
$stmtbezbet->execute();
|
|
||||||
} else {
|
|
||||||
$status_update_bez = $res['bezahlt'];
|
|
||||||
$current_id_bez = $s_entry['id'];
|
|
||||||
$stmtbez->execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmtnorm->close();
|
|
||||||
$stmtbez->close();
|
|
||||||
|
|
||||||
remove_from_basket($personen_ids);
|
|
||||||
|
|
||||||
var_dump($vereine_plus_array);
|
|
||||||
|
|
||||||
update_verein_balances($vereine_plus_array);
|
|
||||||
|
|
||||||
$mysqli->commit();
|
|
||||||
|
|
||||||
// Fix #1: Added explicit echo for output tracking
|
|
||||||
http_response_code(200);
|
|
||||||
echo json_encode(['success' => true, 'message' => "Kategorie erfolgreich geändert"]);
|
|
||||||
exit;
|
|
||||||
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// Rollback instantly if anything fails
|
|
||||||
$mysqli->rollback();
|
|
||||||
|
|
||||||
// Fix #1 & #3: Proper error output formatting
|
|
||||||
http_response_code(500);
|
|
||||||
echo json_encode(['success' => false, 'message' => "Datenbankfehler"]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
<?php
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
if (!isset($baseDir)) {
|
|
||||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once $baseDir . '/../scripts/session_functions.php';
|
|
||||||
|
|
||||||
ini_wkvs_session();
|
|
||||||
|
|
||||||
check_user_permission('wk_leitung');
|
|
||||||
|
|
||||||
verify_csrf();
|
|
||||||
|
|
||||||
$name = trim($_POST['name'] ?? '');
|
|
||||||
$slug = trim($_POST['slug'] ?? '');
|
|
||||||
|
|
||||||
if ($name === '') {
|
|
||||||
http_response_code(400);
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Name ist leer']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($slug === ''){
|
|
||||||
http_response_code(400);
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Slug ist leer']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preg_match('/\s/', $slug)) {
|
|
||||||
http_response_code(400);
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Der Slug darf keine Leerzeichen enthalten']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optional: Ensure the slug only contains lowercase letters, numbers, and hyphens
|
|
||||||
if (!preg_match('/^[a-z0-9-]+$/', $slug)) {
|
|
||||||
http_response_code(400);
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Der Slug darf nur Kleinbuchstaben, Zahlen und Bindestriche enthaltenn']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$type = 'wkl';
|
|
||||||
|
|
||||||
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
|
|
||||||
|
|
||||||
if ($data['success'] === false){
|
|
||||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
require $baseDir . '/../scripts/db/db-tables.php';
|
|
||||||
require $baseDir . '/../scripts/db/db-functions.php';
|
|
||||||
|
|
||||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_wettkaempfe (`name`, `slug`) VALUES (?, ?)");
|
|
||||||
|
|
||||||
$stmt->bind_param("ss", $name, $slug);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$stmt->execute();
|
|
||||||
} catch (mysqli_sql_exception $e) {
|
|
||||||
|
|
||||||
if ($e->getCode() === 1062) {
|
|
||||||
http_response_code(400);
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Dieser Slug existiert bereits']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
http_response_code(500);
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Ein Datenbankfehler ist aufgetreten']);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt->close();
|
|
||||||
|
|
||||||
$insert_id = $mysqli->insert_id;
|
|
||||||
|
|
||||||
// Return JSON
|
|
||||||
echo json_encode([
|
|
||||||
'success' => true,
|
|
||||||
'message' => 'Wettkampf hinzugefügt',
|
|
||||||
'id' => $insert_id
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
<?php
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
if (!isset($baseDir)) {
|
|
||||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once $baseDir . '/../scripts/session_functions.php';
|
|
||||||
|
|
||||||
ini_wkvs_session();
|
|
||||||
|
|
||||||
check_user_permission('wk_leitung');
|
|
||||||
|
|
||||||
require_once $baseDir . '/../scripts/delete_request_type_functions.php';
|
|
||||||
|
|
||||||
parse_input_to_delete();
|
|
||||||
|
|
||||||
verify_delete_csrf($_DELETE);
|
|
||||||
|
|
||||||
$id = (int) ($_DELETE['id'] ?? 0);
|
|
||||||
|
|
||||||
if ($id <= 0) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'No valid ID']);
|
|
||||||
}
|
|
||||||
|
|
||||||
require $baseDir . '/../scripts/db/db-functions.php';
|
|
||||||
require $baseDir . '/../scripts/db/db-tables.php';
|
|
||||||
|
|
||||||
|
|
||||||
$type = 'wkl';
|
|
||||||
|
|
||||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
|
||||||
|
|
||||||
if ($dbconnection['success'] !== true){
|
|
||||||
echo 'Critical DB Error.';
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$entrys = db_select($mysqli, $db_tabelle_wettkaempfe, "1", '`id` = ?', [$id]);
|
|
||||||
|
|
||||||
if (count($entrys) < 1) {
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Wettkampf bereits gelöscht']);
|
|
||||||
http_response_code(410);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
db_delete($mysqli, $db_tabelle_wettkaempfe, ['id' => $id]);
|
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Wettkampf gelöscht']);
|
|
||||||
http_response_code(200);
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
<?php
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
ini_set('display_errors', 1);
|
|
||||||
|
|
||||||
if (!isset($baseDir)) {
|
|
||||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once $baseDir . '/../scripts/session_functions.php';
|
|
||||||
|
|
||||||
ini_wkvs_session();
|
|
||||||
|
|
||||||
check_user_permission('wk_leitung');
|
|
||||||
|
|
||||||
verify_csrf();
|
|
||||||
|
|
||||||
|
|
||||||
$id = (int) $_POST['id'] ?? 0;
|
|
||||||
|
|
||||||
if ($id < 1) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Nicht valide ID']);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
require $baseDir . '/../scripts/db/db-functions.php';
|
|
||||||
require $baseDir . '/../scripts/db/db-tables.php';
|
|
||||||
|
|
||||||
$type = 'wkl';
|
|
||||||
|
|
||||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
|
||||||
|
|
||||||
$id_row = db_select($mysqli, $db_tabelle_wettkaempfe, "1", "`id` = ?", [$id]);
|
|
||||||
|
|
||||||
if (count($id_row) !== 1) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Diese ID existiert nicht']);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_var (`name`, `value`) VALUES ('current_wk_id', ?) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)");
|
|
||||||
|
|
||||||
$stmt->bind_param("i", $id);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$stmt->execute();
|
|
||||||
} catch (mysqli_sql_exception $e) {
|
|
||||||
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Ein Datenbankfehler ist aufgetreten']);
|
|
||||||
http_response_code(500);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt->close();
|
|
||||||
|
|
||||||
// Return JSON
|
|
||||||
echo json_encode([
|
|
||||||
'success' => true,
|
|
||||||
'message' => 'Wert geändert'
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
<?php
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
if (!isset($baseDir)) {
|
|
||||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once $baseDir . '/../scripts/session_functions.php';
|
|
||||||
|
|
||||||
ini_wkvs_session();
|
|
||||||
|
|
||||||
check_user_permission('wk_leitung');
|
|
||||||
|
|
||||||
verify_csrf();
|
|
||||||
|
|
||||||
|
|
||||||
$id = (int) $_POST['id'] ?? 0;
|
|
||||||
$field_name = trim($_POST['inputType'] ?? '');
|
|
||||||
$value = trim($_POST['value'] ?? '');
|
|
||||||
|
|
||||||
$allowed_field_names = ['name', 'slug'];
|
|
||||||
|
|
||||||
if (!in_array($field_name, $allowed_field_names)) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Nicht valides Feld']);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($id < 1) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Nicht valide ID']);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($value === '') {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Inhalt ist leer']);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($field_name === 'slug'){
|
|
||||||
if (preg_match('/\s/', $slug)) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Der Slug darf keine Leerzeichen enthalten']);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optional: Ensure the slug only contains lowercase letters, numbers, and hyphens
|
|
||||||
if (!preg_match('/^[a-z0-9-]+$/', $slug)) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Der Slug darf nur Kleinbuchstaben, Zahlen und Bindestriche enthaltenn']);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
require $baseDir . '/../scripts/db/db-functions.php';
|
|
||||||
require $baseDir . '/../scripts/db/db-tables.php';
|
|
||||||
|
|
||||||
$type = 'wkl';
|
|
||||||
|
|
||||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
|
||||||
|
|
||||||
$id_row = db_select($mysqli, $db_tabelle_wettkaempfe, "1", "`id` = ?", [$id]);
|
|
||||||
|
|
||||||
if (count($id_row) !== 1) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Diese ID existiert nicht']);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt = $mysqli->prepare("UPDATE $db_tabelle_wettkaempfe SET `$field_name` = ? WHERE `id` = ?");
|
|
||||||
|
|
||||||
$stmt->bind_param("si", $value, $id);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$stmt->execute();
|
|
||||||
} catch (mysqli_sql_exception $e) {
|
|
||||||
|
|
||||||
// Error 1062: Duplicate entry
|
|
||||||
if ($e->getCode() === 1062) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Dieser Slug existiert bereits']);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error 1054: Unknown column (e.g., $field_name doesn't exist)
|
|
||||||
if ($e->getCode() === 1054) {
|
|
||||||
echo json_encode(['success' => false, 'message' => "Das Feld '$field_name' existiert nicht"]);
|
|
||||||
http_response_code(400);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback for other database errors
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Ein Datenbankfehler ist aufgetreten']);
|
|
||||||
http_response_code(500);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt->close();
|
|
||||||
|
|
||||||
// Return JSON
|
|
||||||
echo json_encode([
|
|
||||||
'success' => true,
|
|
||||||
'message' => 'Wert geändert'
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
@@ -1,431 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
ini_set('display_errors', 1);
|
|
||||||
ini_set('display_startup_errors', 1);
|
|
||||||
|
|
||||||
|
|
||||||
if (!isset($baseDir)) {
|
|
||||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once $baseDir . '/../scripts/session_functions.php';
|
|
||||||
|
|
||||||
ini_wkvs_session(true);
|
|
||||||
|
|
||||||
$csrf_token = $_SESSION['csrf_token'] ?? '';
|
|
||||||
|
|
||||||
$access_granted_wkl = check_user_permission('wk_leitung', true) ?? false;
|
|
||||||
|
|
||||||
if (!$access_granted_wkl):
|
|
||||||
|
|
||||||
$logintype = 'wk_leitung';
|
|
||||||
|
|
||||||
require $baseDir . '/../scripts/login/login.php';
|
|
||||||
|
|
||||||
$logintype = '';
|
|
||||||
|
|
||||||
else:
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<link rel="icon" type="png" href="/intern/img/icon.png">
|
|
||||||
<title>WK-leitung - Wettkämpfe</title>
|
|
||||||
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="/intern/css/einstellungen-ai.css">
|
|
||||||
<link rel="stylesheet" href="/intern/css/sidebar.css">
|
|
||||||
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
|
|
||||||
<script src="/intern/js/custom-msg-display.js"></script>
|
|
||||||
<link rel="stylesheet" href="/intern/css/custom-msg-display.css">
|
|
||||||
<script src="/intern/js/custom-select.js"></script>
|
|
||||||
<link rel="stylesheet" href="/intern/css/custom-select.css">
|
|
||||||
<link rel="stylesheet" href="/files/fonts/fonts.css">
|
|
||||||
<link rel="stylesheet" href="/intern/css/user.css">
|
|
||||||
<link rel="stylesheet" href="/externe-geraete/css/display.css">
|
|
||||||
|
|
||||||
<script src="/intern/js/ace/ace.js"></script>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="/intern/css/coloris/coloris.min.css" />
|
|
||||||
<script src="/intern/js/coloris/coloris.min.js"></script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body class="wettkaempfe">
|
|
||||||
<?php
|
|
||||||
|
|
||||||
|
|
||||||
require $baseDir . '/../scripts/db/db-functions.php';
|
|
||||||
require $baseDir . '/../scripts/db/db-tables.php';
|
|
||||||
|
|
||||||
require $baseDir . '/../scripts/websocket/ws-create-token.php';
|
|
||||||
|
|
||||||
|
|
||||||
$type = 'wkl';
|
|
||||||
|
|
||||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
|
||||||
|
|
||||||
if ($dbconnection['success'] !== true) {
|
|
||||||
echo 'Critical DB Error.';
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$currentPage = 'wettkaempfe';
|
|
||||||
|
|
||||||
require $baseDir . '/../scripts/sidebar/sidebar.php';
|
|
||||||
|
|
||||||
$wettkaempfe = db_select($mysqli, $db_tabelle_wettkaempfe, '*', '', [], 'id ASC');
|
|
||||||
|
|
||||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
|
||||||
|
|
||||||
?>
|
|
||||||
<section class="bgSection">
|
|
||||||
<?php sidebarRender('modal'); ?>
|
|
||||||
<div class="headerDivTrainer">
|
|
||||||
<div class="headingPanelDiv">
|
|
||||||
<h2 class="headingPanel">Wettkämpfe</h2>
|
|
||||||
</div>
|
|
||||||
<div class="menuWrapper">
|
|
||||||
<?php sidebarRender('button'); ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="dashboardGrid">
|
|
||||||
|
|
||||||
<div class="containerDiv">
|
|
||||||
<div>
|
|
||||||
<h3 class="containerHeading">Wettkämpfe</h3>
|
|
||||||
|
|
||||||
<table id="programmTable" class="wkvsTabelle">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Wettkampf ID</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Slug</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th>Löschen</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($wettkaempfe as $s_wk) :
|
|
||||||
$aktiv = ((int) $s_wk['id'] === $current_wk_id); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?= (int) $s_wk['id'] ?></td>
|
|
||||||
<td>
|
|
||||||
<input class="ajaxInput" data-type="name" data-id="<?= (int) $s_wk['id'] ?>" value="<?= htmlspecialchars($s_wk['name'] ?? '') ?>">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input class="ajaxInput" data-type="slug" data-id="<?= (int) $s_wk['id'] ?>" value="<?= htmlspecialchars($s_wk['slug'] ?? '') ?>">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span class="statusSpan <?= $aktiv ? 'activeWk' : 'inactiveWk' ?>"><?= $aktiv ? 'Aktiv' : 'Inaktiv' ?></span>
|
|
||||||
<span class="activateSpan <?= $aktiv ? 'hidden' : '' ?>" data-id="<?= (int) $s_wk['id'] ?>">Aktivieren</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<button class="deleteWk deleteBtn" data-id="<?= (int) $s_wk['id'] ?>">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22"
|
|
||||||
viewBox="0 0 24 24" fill="none" stroke="var(--ui-danger)"
|
|
||||||
stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<polyline points="3 6 5 6 21 6"></polyline>
|
|
||||||
<path
|
|
||||||
d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2">
|
|
||||||
</path>
|
|
||||||
<line x1="10" y1="11" x2="10" y2="17"></line>
|
|
||||||
<line x1="14" y1="11" x2="14" y2="17"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
<tr class="addRow">
|
|
||||||
<td></td>
|
|
||||||
<td>
|
|
||||||
<input type="text" required placeholder="Bezeichnung" class="inputNewWkName">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input type="text" required placeholder="Bsp. wkvs-2026" class="inputNewWkSlug">
|
|
||||||
</td>
|
|
||||||
<td colspan="2">
|
|
||||||
<button type="submit" class="blackBtn neuWkBtn">Neuen Wettkampf erstellen</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="msgDiv"></div>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
const csrf_token = "<?= $csrf_token ?>";
|
|
||||||
|
|
||||||
$('.neuWkBtn').on('click', function () {
|
|
||||||
const $btn = $(this);
|
|
||||||
const $row = $btn.closest(".addRow");
|
|
||||||
const $nameInput = $row.find(".inputNewWkName");
|
|
||||||
const $slugInput = $row.find(".inputNewWkSlug");
|
|
||||||
|
|
||||||
if ($nameInput.length !== 1 || $slugInput.length !== 1) return;
|
|
||||||
|
|
||||||
const name = $nameInput.val().trim();
|
|
||||||
|
|
||||||
if (name === '') {
|
|
||||||
displayMsg(2, "Der Wettkampfname darf nicht leer sein");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const slug = $slugInput.val().trim();
|
|
||||||
|
|
||||||
if (slug === '') {
|
|
||||||
displayMsg(2, "Der Slug darf nicht leer sein");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (/\s/.test(slug)) {
|
|
||||||
displayMsg(2, "Der Slug darf keine Leerzeichen enthalten");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!/^[a-z0-9-]+$/.test(slug)) {
|
|
||||||
displayMsg(2, "Der Slug darf nur Kleinbuchstaben, Zahlen und Bindestriche enthalten");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '/intern/scripts/wettkaempfe/ajax-add-wettkampf.php',
|
|
||||||
type: "POST",
|
|
||||||
data: {
|
|
||||||
csrf_token,
|
|
||||||
name,
|
|
||||||
slug
|
|
||||||
},
|
|
||||||
success: function(response) {
|
|
||||||
if (!response.success) {
|
|
||||||
displayMsg(0, response.message || "Der Wettkampf konnte nicht hinzugefügt werden");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const $newRow = $('<tr>', {});
|
|
||||||
|
|
||||||
// 1. ID Column (Plain text)
|
|
||||||
const $tdId = $('<td>', { text: response.id });
|
|
||||||
|
|
||||||
// 2. Name Column (with nested <input>)
|
|
||||||
const $tdName = $('<td>');
|
|
||||||
const $inputName = $('<input>', {
|
|
||||||
class: 'ajaxInput',
|
|
||||||
'data-type': 'name',
|
|
||||||
'data-id': response.id,
|
|
||||||
val: name // Sets the input value securely
|
|
||||||
});
|
|
||||||
$tdName.append($inputName);
|
|
||||||
|
|
||||||
// 3. Slug Column (with nested <input>)
|
|
||||||
const $tdSlug = $('<td>');
|
|
||||||
const $inputSlug = $('<input>', {
|
|
||||||
class: 'ajaxInput',
|
|
||||||
'data-type': 'slug',
|
|
||||||
'data-id': response.id,
|
|
||||||
val: slug // Sets the input value securely
|
|
||||||
});
|
|
||||||
$tdSlug.append($inputSlug);
|
|
||||||
|
|
||||||
// 4. Empty Column
|
|
||||||
const $tdStatus = $('<td>', {});
|
|
||||||
|
|
||||||
const $spanStatus = $('<span>', {
|
|
||||||
text: 'Inaktiv',
|
|
||||||
class: "statusSpan inactiveWk"
|
|
||||||
});
|
|
||||||
|
|
||||||
const $spanActivate = $('<span>', {
|
|
||||||
text: 'aktivieren',
|
|
||||||
'data-id': response.id,
|
|
||||||
class: "activateSpan"
|
|
||||||
});
|
|
||||||
|
|
||||||
$tdStatus.append($spanStatus, $spanActivate);
|
|
||||||
|
|
||||||
// 5. Action Column (Delete button with SVG)
|
|
||||||
const $tdAction = $('<td>', {});
|
|
||||||
|
|
||||||
const $deleteBtn = $('<button>', {
|
|
||||||
class: 'deleteWk deleteBtn',
|
|
||||||
'data-id': response.id
|
|
||||||
});
|
|
||||||
|
|
||||||
const $svgIcon = $(`
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22"
|
|
||||||
viewBox="0 0 24 24" fill="none" stroke="var(--ui-danger)"
|
|
||||||
stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<polyline points="3 6 5 6 21 6"></polyline>
|
|
||||||
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
|
|
||||||
<line x1="10" y1="11" x2="10" y2="17"></line>
|
|
||||||
<line x1="14" y1="11" x2="14" y2="17"></line>
|
|
||||||
</svg>
|
|
||||||
`);
|
|
||||||
|
|
||||||
$deleteBtn.append($svgIcon);
|
|
||||||
$tdAction.append($deleteBtn);
|
|
||||||
|
|
||||||
// 6. Assemble everything
|
|
||||||
$newRow.append($tdId, $tdName, $tdSlug, $tdStatus, $tdAction);
|
|
||||||
|
|
||||||
// 7. Insert into the DOM
|
|
||||||
// Note: If you want to insert the new row *before* an existing row ($row), use this:
|
|
||||||
$newRow.insertBefore($row);
|
|
||||||
|
|
||||||
displayMsg(1, "Neuer Wettkampf hinzugefügt");
|
|
||||||
|
|
||||||
},
|
|
||||||
error: () => {
|
|
||||||
displayMsg(0, "Fehler beim Hinzufügen des Wettkampfes");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('click', '.deleteWk', async function () {
|
|
||||||
const $btn = $(this);
|
|
||||||
const $row = $btn.closest("tr");
|
|
||||||
const name = $row.find('.ajaxInput[data-type="name"]').val() || '';
|
|
||||||
|
|
||||||
if (!await displayConfirm(`Wettkampf "${name}" wirklich unwiederruflich löschen? Diese Aktion löscht alle Ergebnisse dieses Wettkampfes!`)) return;
|
|
||||||
|
|
||||||
const dataId = $btn.data('id');
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '/intern/scripts/wettkaempfe/ajax-delete-wettkampf.php',
|
|
||||||
type: "DELETE",
|
|
||||||
data: {
|
|
||||||
csrf_token,
|
|
||||||
id: dataId
|
|
||||||
},
|
|
||||||
success: function(response) {
|
|
||||||
if (!response.success) {
|
|
||||||
displayMsg(0, response.message || "Der Wettkampf konnte nicht gelöscht werden");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$row.remove();
|
|
||||||
|
|
||||||
displayMsg(1, "Wettkampf gelöscht");
|
|
||||||
|
|
||||||
},
|
|
||||||
error: () => {
|
|
||||||
displayMsg(0, "Fehler beim Löschen des Wettkampfes");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('change', '.ajaxInput', function () {
|
|
||||||
const $input = $(this);
|
|
||||||
const value = $input.val().trim();
|
|
||||||
const inputType = $input.data('type');
|
|
||||||
const dataId = $input.data('id');
|
|
||||||
|
|
||||||
if (value === '') {
|
|
||||||
displayMsg(2, "Dieses Feld darf nicht leer sein");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputType === "slug") {
|
|
||||||
if (/\s/.test(value)) {
|
|
||||||
displayMsg(2, "Der Slug darf keine Leerzeichen enthalten");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!/^[a-z0-9-]+$/.test(value)) {
|
|
||||||
displayMsg(2, "Der Slug darf nur Kleinbuchstaben, Zahlen und Bindestriche enthalten");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '/intern/scripts/wettkaempfe/ajax-update-wettkampf.php',
|
|
||||||
type: "POST",
|
|
||||||
data: {
|
|
||||||
csrf_token,
|
|
||||||
id: dataId,
|
|
||||||
value,
|
|
||||||
inputType
|
|
||||||
},
|
|
||||||
success: function(response) {
|
|
||||||
if (!response.success) {
|
|
||||||
displayMsg(0, response.message || "Wert konnte nicht geändert werden");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
displayMsg(1, "Wert geändert");
|
|
||||||
|
|
||||||
},
|
|
||||||
error: () => {
|
|
||||||
displayMsg(0, "Fehler beim Ändern des Wertes");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('click', '.activateSpan', async function() {
|
|
||||||
const $btn = $(this);
|
|
||||||
const dataId = $btn.data('id');
|
|
||||||
|
|
||||||
if (!await displayConfirm(`Das wechseln des Wettkampfes lädt alle Daten in der Kampfrichteransicht und RankLive neu.`)) return;
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '/intern/scripts/wettkaempfe/ajax-update-aktiv-wettkampf.php',
|
|
||||||
type: "POST",
|
|
||||||
data: {
|
|
||||||
csrf_token,
|
|
||||||
id: dataId
|
|
||||||
},
|
|
||||||
success: function(response) {
|
|
||||||
if (!response.success) {
|
|
||||||
displayMsg(0, response.message || "Aktiver Wettkampf konnte nicht geändert werden");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const $tbody = $btn.closest('tbody');
|
|
||||||
|
|
||||||
// 1. Show ALL activation triggers in the table again
|
|
||||||
$tbody.find('.activateSpan').removeClass('hidden');
|
|
||||||
|
|
||||||
// 2. Hide only the trigger that was just clicked
|
|
||||||
$btn.addClass('hidden');
|
|
||||||
|
|
||||||
// 3. Find the single currently active swatch and turn it inactive
|
|
||||||
$tbody.find('.statusSpan.activeWk')
|
|
||||||
.removeClass('activeWk')
|
|
||||||
.addClass('inactiveWk')
|
|
||||||
.text('Inaktiv');
|
|
||||||
|
|
||||||
// 4. Find the swatch in the CURRENT row and turn it active
|
|
||||||
// (Using .closest('tr') ensures we look inside the same row)
|
|
||||||
$btn.closest('tr')
|
|
||||||
.find('.statusSpan')
|
|
||||||
.removeClass('inactiveWk')
|
|
||||||
.addClass('activeWk')
|
|
||||||
.text('Aktiv');
|
|
||||||
|
|
||||||
displayMsg(1, "Aktiver Wettkampf wurde gewechselt");
|
|
||||||
|
|
||||||
},
|
|
||||||
error: () => {
|
|
||||||
displayMsg(0, "Fehler beim Ändern des aktiven Wettkampfes");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
<?php endif; ?>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
$(document).ready(function () {
|
|
||||||
$('.menuLinksDiv>div').hover(function () {
|
|
||||||
const $this = $(this);
|
|
||||||
clearTimeout($this.data('hoverTimeout'));
|
|
||||||
$this.find('.dropdown').stop(true, false).slideDown(200);
|
|
||||||
$this.addClass('open');
|
|
||||||
}, function () {
|
|
||||||
const $this = $(this);
|
|
||||||
const timeout = setTimeout(function () {
|
|
||||||
$this.find('.dropdown').stop(true, false).slideUp(200);
|
|
||||||
$this.removeClass('open');
|
|
||||||
}, 200); // Small delay to prevent flickering
|
|
||||||
$this.data('hoverTimeout', timeout);
|
|
||||||
});
|
|
||||||
$('.sidebar>div').on('click', function (e) {
|
|
||||||
if ($(e.target).closest('.dropdown').length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!$(this).hasClass('open')) {
|
|
||||||
$('.sidebar>div.open').removeClass('open').find('.dropdown').slideUp();
|
|
||||||
$(this).addClass('open');
|
|
||||||
$(this).find('.dropdown').slideDown();
|
|
||||||
} else {
|
|
||||||
$(this).find('.dropdown').slideUp();
|
|
||||||
$(this).removeClass('open');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$(document).on('click', function (e) {
|
|
||||||
// If sidebar is not active, do nothing
|
|
||||||
if ($(e.target).closest('.burgerMenuDiv').length) {
|
|
||||||
$('.burgerMenuDiv').toggleClass('active');
|
|
||||||
$('.sidebar').toggleClass('active');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$('.sidebar').hasClass('active')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If click is inside the sidebar or burger menu, do nothing
|
|
||||||
if (
|
|
||||||
$(e.target).closest('.sidebar').length ||
|
|
||||||
$(e.target).closest('.burgerMenuDiv').length
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, close the sidebar
|
|
||||||
$('.sidebar').removeClass('active');
|
|
||||||
$('.burgerMenuDiv').removeClass('active');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,24 +1,24 @@
|
|||||||
<?php
|
<?php
|
||||||
function generateIntersectCache($mysqli, $baseDir) {
|
function generateIntersectCache($mysqli, $baseDir) {
|
||||||
global $db_tabelle_kategorien;
|
global $tableProgramme;
|
||||||
global $db_tabelle_disziplinen;
|
global $tableGeraete;
|
||||||
global $db_tabelle_wertungstypen;
|
global $tableNotenBezeichnungen;
|
||||||
global $db_tabelle_tabellen_konfiguration;
|
global $tableRankLiveConfigs;
|
||||||
global $db_tabelle_var;
|
global $tableVar;
|
||||||
|
|
||||||
// 1. Fetch all unique IDs you need to loop through
|
// 1. Fetch all unique IDs you need to loop through
|
||||||
$all_programms = array_column(db_select($mysqli, $db_tabelle_kategorien, '`id`', '`aktiv` = ?', [1]) ?? [], 'id');
|
$all_programms = array_column(db_select($mysqli, $tableProgramme, '`id`', '`aktiv` = ?', [1]) ?? [], 'id');
|
||||||
$all_geraete = array_column(db_select($mysqli, $db_tabelle_disziplinen, 'id') ?? [], 'id');
|
$all_geraete = array_column(db_select($mysqli, $tableGeraete, 'id') ?? [], 'id');
|
||||||
|
|
||||||
// 2. Fetch the static DB configs ONCE before starting the massive loop
|
// 2. Fetch the static DB configs ONCE before starting the massive loop
|
||||||
$rang_note_id = db_get_variable($mysqli, $db_tabelle_var, ['rangNote']);
|
$rang_note_id = db_get_variable($mysqli, $tableVar, ['rangNote']);
|
||||||
|
|
||||||
$json_geraet = db_get_var($mysqli, "SELECT `all_noten_json` FROM $db_tabelle_tabellen_konfiguration WHERE `type_slug` = ?", ["rankLive-geraet"]) ?: '';
|
$json_geraet = db_get_var($mysqli, "SELECT `all_noten_json` FROM $tableRankLiveConfigs WHERE `type_slug` = ?", ["rankLive-geraet"]) ?: '';
|
||||||
$json_overview = db_get_var($mysqli, "SELECT `all_noten_json` FROM $db_tabelle_tabellen_konfiguration WHERE `type_slug` = ?", ["rankLive-overview"]) ?: '';
|
$json_overview = db_get_var($mysqli, "SELECT `all_noten_json` FROM $tableRankLiveConfigs WHERE `type_slug` = ?", ["rankLive-overview"]) ?: '';
|
||||||
$noten_rank_live_geraet = json_decode($json_geraet, true) ?? [];
|
$noten_rank_live_geraet = json_decode($json_geraet, true) ?? [];
|
||||||
$noten_rank_live_overview = json_decode($json_overview, true) ?? [];
|
$noten_rank_live_overview = json_decode($json_overview, true) ?? [];
|
||||||
|
|
||||||
$notenConfig_db = db_select($mysqli, $db_tabelle_wertungstypen, '`berechnung_json`, `id`, `type`, `anzahl_laeufe_json`');
|
$notenConfig_db = db_select($mysqli, $tableNotenBezeichnungen, '`berechnung_json`, `id`, `type`, `anzahl_laeufe_json`');
|
||||||
$noten_config = array_column($notenConfig_db, null, 'id');
|
$noten_config = array_column($notenConfig_db, null, 'id');
|
||||||
$following_config_array = array_column($notenConfig_db, 'berechnung_json', 'id');
|
$following_config_array = array_column($notenConfig_db, 'berechnung_json', 'id');
|
||||||
$all_inputs_noten_ids = array_filter(array_column($notenConfig_db, 'type', 'id'), fn($type) => $type === 'input');
|
$all_inputs_noten_ids = array_filter(array_column($notenConfig_db, 'type', 'id'), fn($type) => $type === 'input');
|
||||||
|
|||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
function regenerate_noten_cache($mysqli, $db_tabelle_wertungstypen, $baseDir) {
|
function regenerate_noten_cache($mysqli, $tableNotenBezeichnungen, $baseDir) {
|
||||||
if (!function_exists('db_select')) require $baseDir . '/../scripts/db/db-functions.php';
|
if (!function_exists('db_select')) require $baseDir . '/../scripts/db/db-functions.php';
|
||||||
|
|
||||||
$notenRechnerCache = new NotenRechner();
|
$notenRechnerCache = new NotenRechner();
|
||||||
|
|
||||||
$all = db_select($mysqli, $db_tabelle_wertungstypen, "id, default_value, pro_geraet, geraete_json, anzahl_laeufe_json, berechnung, nullstellen, display_string");
|
$all = db_select($mysqli, $tableNotenBezeichnungen, "id, default_value, pro_geraet, geraete_json, anzahl_laeufe_json, berechnung, nullstellen, zeige_in_rank_live, display_string");
|
||||||
|
|
||||||
$ascArrayDefaultValues = array_column($all, 'default_value', 'id');
|
$ascArrayDefaultValues = array_column($all, 'default_value', 'id');
|
||||||
$ascArrayProGeraet = array_column($all, 'pro_geraet', 'id');
|
$ascArrayProGeraet = array_column($all, 'pro_geraet', 'id');
|
||||||
|
|||||||
+658
@@ -1,3 +1,661 @@
|
|||||||
<?php
|
<?php
|
||||||
return array (
|
return array (
|
||||||
|
4 =>
|
||||||
|
array (
|
||||||
|
1 =>
|
||||||
|
array (
|
||||||
|
1 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 60,
|
||||||
|
1 => 1,
|
||||||
|
2 => 1,
|
||||||
|
3 => 70,
|
||||||
|
4 => 1,
|
||||||
|
5 => 1,
|
||||||
|
6 => 80,
|
||||||
|
7 => 0,
|
||||||
|
8 => 1,
|
||||||
|
9 => 40,
|
||||||
|
10 => 1,
|
||||||
|
11 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'60|1|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 60,
|
||||||
|
),
|
||||||
|
'70|1|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
'40|1|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 60,
|
||||||
|
1 => 1,
|
||||||
|
2 => 2,
|
||||||
|
3 => 70,
|
||||||
|
4 => 1,
|
||||||
|
5 => 1,
|
||||||
|
6 => 80,
|
||||||
|
7 => 0,
|
||||||
|
8 => 1,
|
||||||
|
9 => 40,
|
||||||
|
10 => 1,
|
||||||
|
11 => 2,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'60|1|2' =>
|
||||||
|
array (
|
||||||
|
'r' => 2,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 60,
|
||||||
|
),
|
||||||
|
'70|1|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
'40|1|2' =>
|
||||||
|
array (
|
||||||
|
'r' => 2,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 =>
|
||||||
|
array (
|
||||||
|
1 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 60,
|
||||||
|
1 => 2,
|
||||||
|
2 => 1,
|
||||||
|
3 => 70,
|
||||||
|
4 => 2,
|
||||||
|
5 => 1,
|
||||||
|
6 => 80,
|
||||||
|
7 => 0,
|
||||||
|
8 => 1,
|
||||||
|
9 => 40,
|
||||||
|
10 => 2,
|
||||||
|
11 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'60|2|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 2,
|
||||||
|
'n_id' => 60,
|
||||||
|
),
|
||||||
|
'70|2|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 2,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
'40|2|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 2,
|
||||||
|
'n_id' => 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 70,
|
||||||
|
1 => 2,
|
||||||
|
2 => 1,
|
||||||
|
3 => 80,
|
||||||
|
4 => 0,
|
||||||
|
5 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'70|2|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 2,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
3 =>
|
||||||
|
array (
|
||||||
|
1 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 60,
|
||||||
|
1 => 3,
|
||||||
|
2 => 1,
|
||||||
|
3 => 70,
|
||||||
|
4 => 3,
|
||||||
|
5 => 1,
|
||||||
|
6 => 80,
|
||||||
|
7 => 0,
|
||||||
|
8 => 1,
|
||||||
|
9 => 40,
|
||||||
|
10 => 3,
|
||||||
|
11 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'60|3|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 3,
|
||||||
|
'n_id' => 60,
|
||||||
|
),
|
||||||
|
'70|3|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 3,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
'40|3|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 3,
|
||||||
|
'n_id' => 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 70,
|
||||||
|
1 => 3,
|
||||||
|
2 => 1,
|
||||||
|
3 => 80,
|
||||||
|
4 => 0,
|
||||||
|
5 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'70|3|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 3,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
4 =>
|
||||||
|
array (
|
||||||
|
1 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 60,
|
||||||
|
1 => 4,
|
||||||
|
2 => 1,
|
||||||
|
3 => 70,
|
||||||
|
4 => 4,
|
||||||
|
5 => 1,
|
||||||
|
6 => 80,
|
||||||
|
7 => 0,
|
||||||
|
8 => 1,
|
||||||
|
9 => 40,
|
||||||
|
10 => 4,
|
||||||
|
11 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'60|4|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 4,
|
||||||
|
'n_id' => 60,
|
||||||
|
),
|
||||||
|
'70|4|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 4,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
'40|4|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 4,
|
||||||
|
'n_id' => 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 70,
|
||||||
|
1 => 4,
|
||||||
|
2 => 1,
|
||||||
|
3 => 80,
|
||||||
|
4 => 0,
|
||||||
|
5 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'70|4|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 4,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
13 =>
|
||||||
|
array (
|
||||||
|
1 =>
|
||||||
|
array (
|
||||||
|
1 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 60,
|
||||||
|
1 => 1,
|
||||||
|
2 => 1,
|
||||||
|
3 => 70,
|
||||||
|
4 => 1,
|
||||||
|
5 => 1,
|
||||||
|
6 => 80,
|
||||||
|
7 => 0,
|
||||||
|
8 => 1,
|
||||||
|
9 => 40,
|
||||||
|
10 => 1,
|
||||||
|
11 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'60|1|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 60,
|
||||||
|
),
|
||||||
|
'70|1|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
'40|1|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 60,
|
||||||
|
1 => 1,
|
||||||
|
2 => 2,
|
||||||
|
3 => 70,
|
||||||
|
4 => 1,
|
||||||
|
5 => 1,
|
||||||
|
6 => 80,
|
||||||
|
7 => 0,
|
||||||
|
8 => 1,
|
||||||
|
9 => 40,
|
||||||
|
10 => 1,
|
||||||
|
11 => 2,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'60|1|2' =>
|
||||||
|
array (
|
||||||
|
'r' => 2,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 60,
|
||||||
|
),
|
||||||
|
'70|1|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
'40|1|2' =>
|
||||||
|
array (
|
||||||
|
'r' => 2,
|
||||||
|
'g_id' => 1,
|
||||||
|
'n_id' => 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 =>
|
||||||
|
array (
|
||||||
|
1 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 60,
|
||||||
|
1 => 2,
|
||||||
|
2 => 1,
|
||||||
|
3 => 70,
|
||||||
|
4 => 2,
|
||||||
|
5 => 1,
|
||||||
|
6 => 80,
|
||||||
|
7 => 0,
|
||||||
|
8 => 1,
|
||||||
|
9 => 40,
|
||||||
|
10 => 2,
|
||||||
|
11 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'60|2|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 2,
|
||||||
|
'n_id' => 60,
|
||||||
|
),
|
||||||
|
'70|2|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 2,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
'40|2|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 2,
|
||||||
|
'n_id' => 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 70,
|
||||||
|
1 => 2,
|
||||||
|
2 => 1,
|
||||||
|
3 => 80,
|
||||||
|
4 => 0,
|
||||||
|
5 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'70|2|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 2,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
3 =>
|
||||||
|
array (
|
||||||
|
1 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 60,
|
||||||
|
1 => 3,
|
||||||
|
2 => 1,
|
||||||
|
3 => 70,
|
||||||
|
4 => 3,
|
||||||
|
5 => 1,
|
||||||
|
6 => 80,
|
||||||
|
7 => 0,
|
||||||
|
8 => 1,
|
||||||
|
9 => 40,
|
||||||
|
10 => 3,
|
||||||
|
11 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'60|3|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 3,
|
||||||
|
'n_id' => 60,
|
||||||
|
),
|
||||||
|
'70|3|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 3,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
'40|3|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 3,
|
||||||
|
'n_id' => 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 70,
|
||||||
|
1 => 3,
|
||||||
|
2 => 1,
|
||||||
|
3 => 80,
|
||||||
|
4 => 0,
|
||||||
|
5 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'70|3|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 3,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
4 =>
|
||||||
|
array (
|
||||||
|
1 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 60,
|
||||||
|
1 => 4,
|
||||||
|
2 => 1,
|
||||||
|
3 => 70,
|
||||||
|
4 => 4,
|
||||||
|
5 => 1,
|
||||||
|
6 => 80,
|
||||||
|
7 => 0,
|
||||||
|
8 => 1,
|
||||||
|
9 => 40,
|
||||||
|
10 => 4,
|
||||||
|
11 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'60|4|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 4,
|
||||||
|
'n_id' => 60,
|
||||||
|
),
|
||||||
|
'70|4|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 4,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
'40|4|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 4,
|
||||||
|
'n_id' => 40,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
2 =>
|
||||||
|
array (
|
||||||
|
'SQL' => '(`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?) OR (`note_bezeichnung_id` = ? AND `geraet_id` = ? AND `run_number` = ?)',
|
||||||
|
'values' =>
|
||||||
|
array (
|
||||||
|
0 => 70,
|
||||||
|
1 => 4,
|
||||||
|
2 => 1,
|
||||||
|
3 => 80,
|
||||||
|
4 => 0,
|
||||||
|
5 => 1,
|
||||||
|
),
|
||||||
|
'intersect_noten' =>
|
||||||
|
array (
|
||||||
|
'70|4|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 4,
|
||||||
|
'n_id' => 70,
|
||||||
|
),
|
||||||
|
'80|0|1' =>
|
||||||
|
array (
|
||||||
|
'r' => 1,
|
||||||
|
'g_id' => 0,
|
||||||
|
'n_id' => 80,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
+10
@@ -119,6 +119,16 @@ return [
|
|||||||
60 => 2,
|
60 => 2,
|
||||||
70 => 2,
|
70 => 2,
|
||||||
80 => 2,
|
80 => 2,
|
||||||
|
),
|
||||||
|
'zeige_in_rank_live' => array (
|
||||||
|
10 => 1,
|
||||||
|
11 => 1,
|
||||||
|
20 => 1,
|
||||||
|
40 => 1,
|
||||||
|
50 => 1,
|
||||||
|
60 => 1,
|
||||||
|
70 => 1,
|
||||||
|
80 => 1,
|
||||||
),
|
),
|
||||||
'display_string' => array (
|
'display_string' => array (
|
||||||
10 => '${note}',
|
10 => '${note}',
|
||||||
|
|||||||
@@ -131,9 +131,9 @@ function db_get_var($mysqli, $sql, $params = []) {
|
|||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function db_get_variable($mysqli, $db_tabelle_var, $params = []) {
|
function db_get_variable($mysqli, $tableVar, $params = []) {
|
||||||
if (count($params) !== 1) return null;
|
if (count($params) !== 1) return null;
|
||||||
$stmt = $mysqli->prepare("SELECT `value` FROM $db_tabelle_var WHERE `name` = ?");
|
$stmt = $mysqli->prepare("SELECT `value` FROM $tableVar WHERE `name` = ?");
|
||||||
$stmt->bind_param("s", ...$params);
|
$stmt->bind_param("s", ...$params);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$stmt->bind_result($value);
|
$stmt->bind_result($value);
|
||||||
@@ -142,9 +142,9 @@ function db_get_variable($mysqli, $db_tabelle_var, $params = []) {
|
|||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function db_update_variable($mysqli, $db_tabelle_var, $params = ['name', 'value']) {
|
function db_update_variable($mysqli, $tableVar, $params = ['name', 'value']) {
|
||||||
if (count($params) !== 2) return false;
|
if (count($params) !== 2) return false;
|
||||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_var (`name`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)");
|
$stmt = $mysqli->prepare("INSERT INTO $tableVar (`name`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)");
|
||||||
$stmt->bind_param("ss", ...$params);
|
$stmt->bind_param("ss", ...$params);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$stmt->close();
|
$stmt->close();
|
||||||
|
|||||||
+29
-23
@@ -29,28 +29,32 @@ try {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$prefix = $_ENV['DB_PREFIX'] ?? '';
|
||||||
|
|
||||||
|
|
||||||
$tableDefinitions = [
|
$tableDefinitions = [
|
||||||
'teilnehmende' => 'DB_TABLE_TEILNEHMENDE',
|
'Teilnehmende' => 'DB_TABLE_TEILNEHMENDE',
|
||||||
'verbuchte_startgebueren' => 'DB_TABLE_VERBUCHTE_STARTGEBUEREN',
|
'Orders' => 'DB_TABLE_ORDERS',
|
||||||
'warenkorb_startgebueren' => 'DB_TABLE_WARENKORB_STARTGEBUEREN',
|
'BasketItems' => 'DB_TABLE_BASKET_ITEMS',
|
||||||
'var' => 'DB_TABLE_VARIABLES',
|
'Var' => 'DB_TABLE_VARIABLES',
|
||||||
'einmal_links' => 'DB_EINMAL_LINKS',
|
'OTL' => 'DB_TABLE_OTL',
|
||||||
'kategorien' => 'DB_TABLE_KATEGORIEN',
|
'KrProtokoll' => 'DB_TABLE_KR_PROTOKOLL',
|
||||||
'intern_benutzende' => 'DB_TABLE_INTERN_BENUTZENDE',
|
'Programme' => 'DB_TABLE_PROGRAMME',
|
||||||
'vereine' => 'DB_TABLE_VEREINE',
|
'InternUsers' => 'DB_TABLE_INTERN_USERS',
|
||||||
'gruppen' => 'DB_TABLE_GRUPPEN',
|
'Vereine' => 'DB_TABLE_VEREINE',
|
||||||
'teilnehmende_gruppen' => 'DB_TABLE_TEILNEHMENDE_GRUPPEN',
|
'Abt' => 'DB_TABLE_ABTEILUNGEN',
|
||||||
'disziplinen' => 'DB_TABLE_DISZIPLINEN',
|
'TeilnehmendeAbt' => 'DB_TABLE_TEILNEHMENDE_ABTEILUNGEN',
|
||||||
'audiofiles' => 'DB_TABLE_AUDIOFILES',
|
'Geraete' => 'DB_TABLE_GERAETE',
|
||||||
'teilnehmende_audiofiles' => 'DB_TABLE_TEILNEHMENDE_AUDIOFILES',
|
'Audiofiles' => 'DB_TABLE_AUDIOFILES',
|
||||||
'wertungen' => 'DB_TABLE_WERTUNGEN',
|
'TeilnehmendeAudiofiles' => 'DB_TABLE_TEILNEHMENDE_AUDIOFILES',
|
||||||
'wertungen_log' => 'DB_TABLE_WERTUNGEN_LOG',
|
'Noten' => 'DB_TABLE_NOTEN',
|
||||||
'wertungstypen' => 'DB_TABLE_WERTUNGSTYPEN',
|
'NotenChanges' => 'DB_TABLE_NOTEN_CHANGES',
|
||||||
'verbuchte_startgebueren_log' => 'DB_TABLE_VERBUCHTE_STARTGEBUEREN_LOG',
|
'NotenBezeichnungen' => 'DB_TABLE_NOTEN_BEZEICHNUNGEN',
|
||||||
'zeitplan_types' => 'DB_TABLE_ZEITPLAN_TYPES',
|
'OrdersLog' => 'DB_TABLE_ORDERS_LOG',
|
||||||
'gruppen_zeiten' => 'DB_TABLE_GRUPPEN_ZEITEN',
|
'ZeitplanTypes' => 'DB_TABLE_ZEITPLAN_TYPES',
|
||||||
'tabellen_konfiguration' => 'DB_TABLE_TABELLEN_KONFIGURATION',
|
'AbtZeiten' => 'DB_TABLE_ABTEILUNGEN_ZEITEN',
|
||||||
'wettkaempfe' => 'DB_TABLE_WETTKAEMPFE'
|
'RankLiveConfigs' => 'DB_TABLE_RANKLIVE_CONFIGS'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
@@ -58,7 +62,9 @@ foreach ($tableDefinitions as $baseName => $envVarKey) {
|
|||||||
|
|
||||||
$rawTableName = $_ENV[$envVarKey] ?? '';
|
$rawTableName = $_ENV[$envVarKey] ?? '';
|
||||||
|
|
||||||
$variableName = 'db_tabelle_' . $baseName;
|
$fullTableName = $prefix . $rawTableName;
|
||||||
|
|
||||||
$$variableName = $rawTableName;
|
$variableName = 'table' . ucfirst($baseName);
|
||||||
|
|
||||||
|
$$variableName = $fullTableName;
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@ if ($type === 'kr'){
|
|||||||
|
|
||||||
require __DIR__ . '/../../composer/vendor/autoload.php';
|
require __DIR__ . '/../../composer/vendor/autoload.php';
|
||||||
|
|
||||||
$envFile = realpath(__DIR__ . '/../../config/.env.db-wkvs-user');
|
$envFile = realpath(__DIR__ . '/../../config/.env.db');
|
||||||
|
|
||||||
if ($envFile === false) {
|
if ($envFile === false) {
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
@@ -45,7 +45,7 @@ if ($envFile === false) {
|
|||||||
try {
|
try {
|
||||||
$envDir = dirname($envFile);
|
$envDir = dirname($envFile);
|
||||||
|
|
||||||
$dotenv = Dotenv::createImmutable($envDir, '.env.db-wkvs-user');
|
$dotenv = Dotenv::createImmutable($envDir, '.env.db');
|
||||||
|
|
||||||
$dotenv->load();
|
$dotenv->load();
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ $userid = intval($_SESSION['user_id_kampfrichter'] ?? 0);
|
|||||||
$arrayfreigaben = [];
|
$arrayfreigaben = [];
|
||||||
|
|
||||||
if ($userid > 0) {
|
if ($userid > 0) {
|
||||||
$stmt = $mysqli->prepare("SELECT freigabe, username FROM $db_tabelle_intern_benutzende WHERE id = ?");
|
$stmt = $mysqli->prepare("SELECT freigabe, username FROM $tableInternUsers WHERE id = ?");
|
||||||
$stmt->bind_param("s", $userid);
|
$stmt->bind_param("s", $userid);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$result = $stmt->get_result();
|
$result = $stmt->get_result();
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ if (isset($_POST['prev_abt_submit'])) {
|
|||||||
$value = $aktabt;
|
$value = $aktabt;
|
||||||
if ($value > 1){
|
if ($value > 1){
|
||||||
$value -= 1;
|
$value -= 1;
|
||||||
db_update_variable($mysqli, $db_tabelle_var, ['wk_panel_current_abt', $value]);
|
db_update_variable($mysqli, $tableVar, ['wk_panel_current_abt', $value]);
|
||||||
}
|
}
|
||||||
header("Location: /intern/kampfrichter");
|
header("Location: /intern/kampfrichter");
|
||||||
exit;
|
exit;
|
||||||
@@ -18,11 +18,11 @@ if (isset($_POST['prev_abt_submit'])) {
|
|||||||
if (isset($_POST['next_abt_submit'])) {
|
if (isset($_POST['next_abt_submit'])) {
|
||||||
verify_csrf();
|
verify_csrf();
|
||||||
$value = $aktabt;
|
$value = $aktabt;
|
||||||
$maxvalue = (int) (db_get_var($mysqli, "SELECT `order_index` FROM $db_tabelle_gruppen ORDER BY `order_index` DESC LIMIT 1") ?? 1);
|
$maxvalue = (int) (db_get_var($mysqli, "SELECT name FROM $tableAbt ORDER BY name DESC LIMIT 1") ?? 1);
|
||||||
|
|
||||||
if ($value < $maxvalue){
|
if ($value < $maxvalue){
|
||||||
$value += 1;
|
$value += 1;
|
||||||
db_update_variable($mysqli, $db_tabelle_var, ['wk_panel_current_abt', $value]);
|
db_update_variable($mysqli, $tableVar, ['wk_panel_current_abt', $value]);
|
||||||
}
|
}
|
||||||
header("Location: /intern/kampfrichter");
|
header("Location: /intern/kampfrichter");
|
||||||
exit;
|
exit;
|
||||||
@@ -33,7 +33,7 @@ if (isset($_POST['prev_subabt_admin_submit']) && $isAdmin) {
|
|||||||
$value = $akt_subabt_admin;
|
$value = $akt_subabt_admin;
|
||||||
if ($value > 1){
|
if ($value > 1){
|
||||||
$value -= 1;
|
$value -= 1;
|
||||||
db_update_variable($mysqli, $db_tabelle_var, ['wk_panel_current_subabt_admin', $value]);
|
db_update_variable($mysqli, $tableVar, ['wk_panel_current_subabt_admin', $value]);
|
||||||
$_SESSION['ws_Message_json'] = json_encode(['type' => 'UPDATE_RANKLIVE_C_SUBABT', 'payload' => []]);
|
$_SESSION['ws_Message_json'] = json_encode(['type' => 'UPDATE_RANKLIVE_C_SUBABT', 'payload' => []]);
|
||||||
}
|
}
|
||||||
header("Location: /intern/kampfrichter");
|
header("Location: /intern/kampfrichter");
|
||||||
@@ -47,7 +47,7 @@ if (isset($_POST['next_subabt_admin_submit']) && $isAdmin) {
|
|||||||
|
|
||||||
if ($value < $max_value_admin_subabt){
|
if ($value < $max_value_admin_subabt){
|
||||||
$value += 1;
|
$value += 1;
|
||||||
db_update_variable($mysqli, $db_tabelle_var, ['wk_panel_current_subabt_admin', $value]);
|
db_update_variable($mysqli, $tableVar, ['wk_panel_current_subabt_admin', $value]);
|
||||||
$_SESSION['ws_Message_json'] = json_encode(['type' => 'UPDATE_RANKLIVE_C_SUBABT', 'payload' => []]);
|
$_SESSION['ws_Message_json'] = json_encode(['type' => 'UPDATE_RANKLIVE_C_SUBABT', 'payload' => []]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ if ($_SESSION['lockout_time_'. $logintype] > time()) {
|
|||||||
$password = trim($_POST['access_passcode']);
|
$password = trim($_POST['access_passcode']);
|
||||||
|
|
||||||
// Prepare statement
|
// Prepare statement
|
||||||
$stmt = $guest->prepare("SELECT * FROM $db_tabelle_intern_benutzende WHERE username = ? AND login_active = ? LIMIT 1");
|
$stmt = $guest->prepare("SELECT * FROM $tableInternUsers WHERE username = ? AND login_active = ? LIMIT 1");
|
||||||
$loginActive = 1;
|
$loginActive = 1;
|
||||||
$stmt->bind_param("ss", $username, $loginActive);
|
$stmt->bind_param("ss", $username, $loginActive);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
<header>
|
|
||||||
<a class="rankLiveHeaderTitle" href="/RankLive">
|
|
||||||
RankLive
|
|
||||||
</a>
|
|
||||||
<div class="menuLinksDiv">
|
|
||||||
<?php include __DIR__ ."/rankLive-menu.php"?>
|
|
||||||
</div>
|
|
||||||
<div class="burgerMenuDiv">
|
|
||||||
<div class="burgerMenuLine"></div>
|
|
||||||
<div class="burgerMenuLine"></div>
|
|
||||||
<div class="burgerMenuLine"></div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<div class="sidebar">
|
|
||||||
<?php include __DIR__ ."/rankLive-menu.php"?>
|
|
||||||
</div>
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
if (!isset($guest) || !$guest instanceof mysqli) {
|
|
||||||
require $_SERVER['DOCUMENT_ROOT'] . "/../scripts/db/db-verbindung-script-guest.ph";
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = $guest->query("SELECT `programm` FROM $db_tabelle_kategorien WHERE `aktiv` = '1'");
|
|
||||||
|
|
||||||
$yearsGalleryArray = [];
|
|
||||||
|
|
||||||
while ($row = $result->fetch_assoc()) {
|
|
||||||
$kategorien[str_replace(' ', '-', strtolower(htmlspecialchars($row['programm'])))] = htmlspecialchars($row['programm']);
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
|
|
||||||
<a href="/RankLive/live" class="menu-item">
|
|
||||||
<svg class="menu-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<circle cx="12" cy="12" r="10"/>
|
|
||||||
<polygon points="10 8 16 12 10 16 10 8"/>
|
|
||||||
</svg>
|
|
||||||
Aktueller Durchgang
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="/RankLive/" class="menu-item">
|
|
||||||
<svg class="menu-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<line x1="18" y1="20" x2="18" y2="10"/>
|
|
||||||
<line x1="12" y1="20" x2="12" y2="4"/>
|
|
||||||
<line x1="6" y1="20" x2="6" y2="14"/>
|
|
||||||
</svg>
|
|
||||||
Alle Ergebnisse
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<?php if ($kategorien !== []): ?>
|
|
||||||
<div>
|
|
||||||
<span class="menu-item">
|
|
||||||
<svg class="menu-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<rect x="3" y="3" width="7" height="7"/>
|
|
||||||
<rect x="14" y="3" width="7" height="7"/>
|
|
||||||
<rect x="14" y="14" width="7" height="7"/>
|
|
||||||
<rect x="3" y="14" width="7" height="7"/>
|
|
||||||
</svg>
|
|
||||||
Kategorien
|
|
||||||
<svg class="menu-chevron" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true" focusable="false" style="margin-left: auto;">
|
|
||||||
<path fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" d="M2.5 5.5L8 11l5.5-5.5"></path>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<div class="dropdown">
|
|
||||||
<?php foreach ($kategorien as $kat_slug => $kat_name) : ?>
|
|
||||||
<a href="/RankLive/programm/<?= $kat_slug ?>"><?= $kat_name ?></a>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
@@ -33,9 +33,9 @@ try {
|
|||||||
// Create a Redis connection
|
// Create a Redis connection
|
||||||
$redis = new PredisClient([
|
$redis = new PredisClient([
|
||||||
'scheme' => 'tcp',
|
'scheme' => 'tcp',
|
||||||
'host' => $_ENV['REDIS_HOST'],
|
'host' => $_ENV['REDDIS_HOST'],
|
||||||
'port' => $_ENV['REDIS_PORT'],
|
'port' => $_ENV['REDDIS_PORT'],
|
||||||
'password' => $_ENV['REDIS_PASSWORD']
|
'password' => $_ENV['REDDIS_PASSWORD']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,154 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
function update_teilnehmende($ids_json = '', $old_status, $new_status, bool $ids_are_array = false) {
|
|
||||||
global $mysqli;
|
|
||||||
global $db_tabelle_teilnehmende;
|
|
||||||
global $db_tabelle_kategorien;
|
|
||||||
|
|
||||||
// 1. Quick exits
|
|
||||||
if (intval($old_status) === intval($new_status)) return false;
|
|
||||||
|
|
||||||
if (!$ids_are_array) {
|
|
||||||
$programm_ids = json_decode($ids_json, true) ?? [];
|
|
||||||
} else {
|
|
||||||
if (!is_array($ids_json)) return false;
|
|
||||||
$programm_ids = $ids_json;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($programm_ids) < 1) return false;
|
|
||||||
|
|
||||||
// 2. Extract IDs (which are the keys of the associative array)
|
|
||||||
$ids = array_keys($programm_ids);
|
|
||||||
$tparams = implode(", ", array_fill(0, count($ids), "?"));
|
|
||||||
|
|
||||||
// 3. Fetch current paid amounts
|
|
||||||
$all_teilnehmede_stmt = $mysqli->prepare("SELECT `id`, `betrag_bezahlt`, `programm` FROM $db_tabelle_teilnehmende WHERE `id` IN ($tparams)");
|
|
||||||
$all_teilnehmede_stmt->bind_param(str_repeat("i", count($ids)), ...$ids);
|
|
||||||
$all_teilnehmede_stmt->execute();
|
|
||||||
$all_teilnehmede_res = $all_teilnehmede_stmt->get_result();
|
|
||||||
$all_teilnehmede = $all_teilnehmede_res->fetch_all(MYSQLI_ASSOC);
|
|
||||||
$all_teilnehmede_stmt->close();
|
|
||||||
|
|
||||||
$all_preise_db = db_select($mysqli, $db_tabelle_kategorien, "`programm`, `preis`");
|
|
||||||
|
|
||||||
$all_preise = array_column($all_preise_db, 'preis', 'programm');
|
|
||||||
|
|
||||||
// Creates a clean map of [id => betrag_bezahlt]
|
|
||||||
$all_teilnehmede_indexed = array_column($all_teilnehmede, 'betrag_bezahlt', 'id');
|
|
||||||
$all_teilnehmede_indexed_kat = array_column($all_teilnehmede, 'programm', 'id');
|
|
||||||
|
|
||||||
// 4. Prepare the update statement ONCE
|
|
||||||
$update_teiln_stmt = $mysqli->prepare("UPDATE $db_tabelle_teilnehmende SET `betrag_bezahlt` = ?, `bezahlt` = ? WHERE `id` = ?");
|
|
||||||
|
|
||||||
// Bind variables by reference once
|
|
||||||
$n_preis = 0.0;
|
|
||||||
|
|
||||||
$normal_order_status = match ($new_status) {
|
|
||||||
1 => 3,
|
|
||||||
2 => 4,
|
|
||||||
3 => 1,
|
|
||||||
default => 1
|
|
||||||
};
|
|
||||||
|
|
||||||
$status_to_set = $normal_order_status;
|
|
||||||
|
|
||||||
$s_teiln_id = 0;
|
|
||||||
$update_teiln_stmt->bind_param("dii", $n_preis, $status_to_set, $s_teiln_id);
|
|
||||||
|
|
||||||
// 5. Loop through and execute updates
|
|
||||||
foreach ($programm_ids as $id_key => $preis) {
|
|
||||||
$s_teiln_id = (int) $id_key;
|
|
||||||
|
|
||||||
// FIX: Check directly against the flat ID key map
|
|
||||||
if (!isset($all_teilnehmede_indexed[$s_teiln_id])) continue;
|
|
||||||
|
|
||||||
$eff_preis = 0.0;
|
|
||||||
if (intval($new_status) === 2) {
|
|
||||||
$eff_preis = (float) $preis;
|
|
||||||
} elseif (intval($new_status) !== 2 && intval($old_status) === 2) {
|
|
||||||
$eff_preis = ((float) $preis) * -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the new absolute value
|
|
||||||
$n_preis = max(((float) $all_teilnehmede_indexed[$s_teiln_id]) + $eff_preis, 0);
|
|
||||||
|
|
||||||
if ($normal_order_status === 1) {
|
|
||||||
$kat = $all_teilnehmede_indexed_kat[$s_teiln_id];
|
|
||||||
|
|
||||||
$preis_kat = (float) $all_preise[$kat] ?? PHP_INT_MAX;
|
|
||||||
|
|
||||||
if ($n_preis >= $preis_kat) {
|
|
||||||
$status_to_set = 4;
|
|
||||||
} elseif ($n_preis !== 0.00) {
|
|
||||||
$status_to_set = 2;
|
|
||||||
} else {
|
|
||||||
$status_to_set = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$status_to_set = $normal_order_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute using the bound references
|
|
||||||
$update_teiln_stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
$update_teiln_stmt->close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function update_konten_vereine($benutzte_konten = '', $old_status, $new_status, bool $ids_are_array = false): bool {
|
|
||||||
global $mysqli, $db_tabelle_vereine;
|
|
||||||
|
|
||||||
$int_old_status = (int) $old_status;
|
|
||||||
$int_new_status = (int) $new_status;
|
|
||||||
|
|
||||||
// 1. Quick exit: No status change
|
|
||||||
if ($int_old_status === $int_new_status) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Validate status transitions (Fixed $old_status === 0 || $old_status === 1 bug)
|
|
||||||
$isValidTransition =
|
|
||||||
(in_array($int_old_status, [0, 1, 3]) && $int_new_status === 2) ||
|
|
||||||
(in_array($int_new_status, [0, 1, 3]) && $int_old_status === 2) ||
|
|
||||||
($int_old_status === 0 && $int_new_status === 1);
|
|
||||||
|
|
||||||
if (!$isValidTransition) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$ids_are_array) {
|
|
||||||
$benutzte_konten_array = json_decode($benutzte_konten, true) ?? [];
|
|
||||||
} else {
|
|
||||||
if (!is_array($benutzte_konten)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$benutzte_konten_array = $benutzte_konten;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($benutzte_konten_array)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$faktor = ($int_new_status === 3) ? 1 : -1;
|
|
||||||
|
|
||||||
$stmt = $mysqli->prepare("UPDATE `$db_tabelle_vereine` SET `konto` = `konto` + ? WHERE `verein` = ?");
|
|
||||||
|
|
||||||
$konto_change = 0.0;
|
|
||||||
$verein = '';
|
|
||||||
$stmt->bind_param("ds", $konto_change, $verein);
|
|
||||||
|
|
||||||
foreach ($benutzte_konten_array as $verein_key => $konto_change_absolute) {
|
|
||||||
$verein = (string) $verein_key;
|
|
||||||
$konto_change = (float) $konto_change_absolute * $faktor;
|
|
||||||
|
|
||||||
if ($konto_change == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
$stmt->close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -38,11 +38,11 @@ function connectToRedis(): bool
|
|||||||
|
|
||||||
$redis = new Redis();
|
$redis = new Redis();
|
||||||
|
|
||||||
if (!$redis->connect($_ENV['REDIS_HOST'], $_ENV['REDIS_PORT'])) {
|
if (!$redis->connect($_ENV['REDDIS_HOST'], $_ENV['REDDIS_PORT'])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$redis->auth($_ENV['REDIS_PASSWORD'])) {
|
if (!$redis->auth($_ENV['REDDIS_PASSWORD'])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ function check_user_permission(string $type, bool $return = false, bool $display
|
|||||||
} else {
|
} else {
|
||||||
if ($display) {
|
if ($display) {
|
||||||
http_response_code(403);
|
http_response_code(403);
|
||||||
include __DIR__ . "/../html/error-pages/403.html";
|
include __DIR__ . "/../www/error-pages/403.html";
|
||||||
exit;
|
exit;
|
||||||
} else {
|
} else {
|
||||||
http_response_code(403);
|
http_response_code(403);
|
||||||
@@ -98,7 +98,7 @@ function check_user_permission(string $type, bool $return = false, bool $display
|
|||||||
} else {
|
} else {
|
||||||
if ($display) {
|
if ($display) {
|
||||||
http_response_code(403);
|
http_response_code(403);
|
||||||
include __DIR__ . "/../html/error-pages/403.html";
|
include __DIR__ . "/../www/error-pages/403.html";
|
||||||
exit;
|
exit;
|
||||||
} else {
|
} else {
|
||||||
http_response_code(403);
|
http_response_code(403);
|
||||||
|
|||||||
@@ -32,14 +32,13 @@ $icons = [
|
|||||||
'rechnungen' => '<svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>',
|
'rechnungen' => '<svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>',
|
||||||
'logindata' => '<svg viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>',
|
'logindata' => '<svg viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>',
|
||||||
'displaycontrol' => '<svg viewBox="0 0 24 24"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>',
|
'displaycontrol' => '<svg viewBox="0 0 24 24"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>',
|
||||||
//'kalender' => '<svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>',
|
'kalender' => '<svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>',
|
||||||
'rankLive' => '<svg viewBox="0 0 24 24"><path d="M12 4h6a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h6"/><line x1="9" y1="9" x2="15" y2="9"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/></svg>',
|
'rankLive' => '<svg viewBox="0 0 24 24"><path d="M12 4h6a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h6"/><line x1="9" y1="9" x2="15" y2="9"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/></svg>',
|
||||||
'wettkaempfe' => '<svg viewBox="0 0 24 24"><path d="M12 4h6a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h6"/><line x1="9" y1="9" x2="15" y2="9"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/></svg>',
|
|
||||||
'riegeneinteilung' => '<svg viewBox="0 0 24 24"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><rect x="8" y="2" width="8" height="4" rx="1" ry="1"/><line x1="9" y1="12" x2="15" y2="12"/><line x1="9" y1="16" x2="15" y2="16"/></svg>',
|
'riegeneinteilung' => '<svg viewBox="0 0 24 24"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><rect x="8" y="2" width="8" height="4" rx="1" ry="1"/><line x1="9" y1="12" x2="15" y2="12"/><line x1="9" y1="16" x2="15" y2="16"/></svg>',
|
||||||
'einstellungen' => '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>',
|
'einstellungen' => '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (isset($mysqli) && isset($db_tabelle_intern_benutzende)) {
|
if (isset($mysqli) && isset($tableInternUsers)) {
|
||||||
|
|
||||||
if ($currentPage === 'kampfrichter' && checkIfUserHasSessionId('kampfrichter')):
|
if ($currentPage === 'kampfrichter' && checkIfUserHasSessionId('kampfrichter')):
|
||||||
$userDispId = intval($_SESSION['user_id_kampfrichter']);
|
$userDispId = intval($_SESSION['user_id_kampfrichter']);
|
||||||
@@ -49,7 +48,7 @@ if (isset($mysqli) && isset($db_tabelle_intern_benutzende)) {
|
|||||||
$userDispId = intval($_SESSION['user_id_wk_leitung']);
|
$userDispId = intval($_SESSION['user_id_wk_leitung']);
|
||||||
endif;
|
endif;
|
||||||
|
|
||||||
$sql = "SELECT `username`, `freigabe` FROM $db_tabelle_intern_benutzende WHERE id = ?";
|
$sql = "SELECT `username`, `freigabe` FROM $tableInternUsers WHERE id = ?";
|
||||||
$stmt = $mysqli->prepare($sql);
|
$stmt = $mysqli->prepare($sql);
|
||||||
|
|
||||||
$stmt->bind_param('i', $userDispId);
|
$stmt->bind_param('i', $userDispId);
|
||||||
@@ -87,7 +86,6 @@ if ($isWKL) {
|
|||||||
$links[] = ['key' => 'rankLive', 'label' => 'Rank Live', 'url' => '/intern/wk-leitung/rank-live', 'freigaben' => false];
|
$links[] = ['key' => 'rankLive', 'label' => 'Rank Live', 'url' => '/intern/wk-leitung/rank-live', 'freigaben' => false];
|
||||||
$links[] = ['key' => 'riegeneinteilung', 'label' => 'Riegeneinteilung', 'url' => '/intern/wk-leitung/riegeneinteilung', 'freigaben' => false];
|
$links[] = ['key' => 'riegeneinteilung', 'label' => 'Riegeneinteilung', 'url' => '/intern/wk-leitung/riegeneinteilung', 'freigaben' => false];
|
||||||
$links[] = ['key' => 'einstellungen', 'label' => 'Einstellungen', 'url' => '/intern/wk-leitung/einstellungen', 'freigaben' => false];
|
$links[] = ['key' => 'einstellungen', 'label' => 'Einstellungen', 'url' => '/intern/wk-leitung/einstellungen', 'freigaben' => false];
|
||||||
$links[] = ['key' => 'wettkaempfe', 'label' => 'Wettkämpfe', 'url' => '/intern/wk-leitung/wettkaempfe', 'freigaben' => false];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkIfUserHasSessionId($type) : bool {
|
function checkIfUserHasSessionId($type) : bool {
|
||||||
|
|||||||
@@ -1,77 +1,95 @@
|
|||||||
<?php
|
<?php
|
||||||
function get_kat_price_diff(array $old_data, string $new_kat): array {
|
|
||||||
global $preise_kats;
|
|
||||||
global $vereine_plus_array;
|
|
||||||
|
|
||||||
$return_array = [];
|
if (isset($_POST['apply_bulk_action'])) {
|
||||||
|
verify_csrf();
|
||||||
$old_kat = $old_data['programm'] ?? '';
|
if (empty($_POST['turnerin_ids']) || !is_array($_POST['turnerin_ids'])) {
|
||||||
$verein = $old_data['verein'] ?? '';
|
$_SESSION['form_message'] = 'Keine ' . $personMehrzahl . ' für die Aktion ausgewählt.';
|
||||||
$bezahlt = (int) ($old_data['bezahlt'] ?? 1);
|
$_SESSION['form_message_type'] = 0;
|
||||||
|
} elseif (!isset($_POST['bulk_action_programm']) && !isset($_POST['bulk_action_bezahlt'])) {
|
||||||
if ($old_kat === '' || $old_kat === $new_kat || !in_array($bezahlt, [2, 4], true) || !isset($preise_kats[$new_kat])) {
|
$_SESSION['form_message'] = 'Kein Programm für die Massenänderung ausgewählt.';
|
||||||
return $return_array;
|
$_SESSION['form_message_type'] = 0;
|
||||||
}
|
|
||||||
|
|
||||||
$betrag_bezahlt = (float) ($old_data['betrag_bezahlt'] ?? 0.00);
|
|
||||||
$new_kat_preis = (float) $preise_kats[$new_kat];
|
|
||||||
|
|
||||||
if ($new_kat_preis > $betrag_bezahlt) {
|
|
||||||
$return_array['bezahlt'] = ($betrag_bezahlt === 0.00) ? 1 : 2;
|
|
||||||
} elseif ($new_kat_preis < $betrag_bezahlt) {
|
|
||||||
$return_array['bezahlt'] = 4;
|
|
||||||
$vereine_plus_array[$verein] = ((float) ($vereine_plus_array[$verein] ?? 0.00)) + $betrag_bezahlt - $new_kat_preis;
|
|
||||||
} else {
|
} else {
|
||||||
$return_array['bezahlt'] = 4;
|
$ids_to_update = array_map('intval', $_POST['turnerin_ids'] ?? []);
|
||||||
|
$new_programm = isset($_POST['bulk_action_programm']) ? trim($_POST['bulk_action_programm']) : '';
|
||||||
|
$bezahlt_update = $_POST['bulk_action_bezahlt'] ?? null;
|
||||||
|
|
||||||
|
if (empty($ids_to_update)) {
|
||||||
|
$_SESSION['form_message'] = 'Keine Einträge ausgewählt.';
|
||||||
|
$_SESSION['form_message_type'] = 0;
|
||||||
|
header("Location: " . $_SERVER['REQUEST_URI']);
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return_array;
|
$set_clauses = [];
|
||||||
}
|
$params = [];
|
||||||
|
$types = '';
|
||||||
|
|
||||||
function update_verein_balances(array $vereine_plus_array_funct) {
|
if ($new_programm !== '') {
|
||||||
global $mysqli;
|
$set_clauses[] = 'programm = ?';
|
||||||
global $db_tabelle_vereine;
|
$params[] = $new_programm;
|
||||||
|
$types .= 's';
|
||||||
if (empty($vereine_plus_array_funct)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmt = $mysqli->prepare("UPDATE $db_tabelle_vereine SET `konto` = `konto` + ? WHERE `verein` = ?");
|
if (in_array($bezahlt_update, ['0', '3', '4', '5'], true)) {
|
||||||
|
$set_clauses[] = 'bezahltoverride = ?';
|
||||||
if ($stmt) {
|
$params[] = (int) $bezahlt_update;
|
||||||
foreach ($vereine_plus_array_funct as $verein => $betrag) {
|
$types .= 'i';
|
||||||
if ($betrag <= 0.00) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmt->bind_param("ds", $betrag, $verein);
|
if (empty($set_clauses)) {
|
||||||
$stmt->execute();
|
$_SESSION['form_message'] = 'Keine gültigen Änderungen gewählt.';
|
||||||
|
$_SESSION['form_message_type'] = 0;
|
||||||
|
header("Location: " . $_SERVER['REQUEST_URI']);
|
||||||
|
exit;
|
||||||
}
|
}
|
||||||
$stmt->close();
|
|
||||||
|
if (strlen($types) !== count($params) || count($params) !== count($set_clauses)) {
|
||||||
|
die('Type/value mismatch: ' . strlen($types) . ' vs ' . count($params));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function remove_from_basket(array $ids_array = []) : bool {
|
/* WHERE id IN (?, ?, ...) */
|
||||||
global $mysqli;
|
$placeholders = implode(',', array_fill(0, count($ids_to_update), '?'));
|
||||||
global $db_tabelle_warenkorb_startgebueren;
|
$sql = "UPDATE $tableTeilnehmende SET " . implode(', ', $set_clauses) . " WHERE id IN ($placeholders)";
|
||||||
|
|
||||||
$tplaceholders = implode(", ", array_fill(0, count($ids_array), "?"));
|
$stmt = $mysqli->prepare($sql);
|
||||||
|
|
||||||
|
/* add ID params */
|
||||||
|
foreach ($ids_to_update as $id) {
|
||||||
|
$params[] = $id;
|
||||||
|
$types .= 'i';
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt->bind_param($types, ...$params);
|
||||||
|
|
||||||
|
if (!$stmt->execute()) {
|
||||||
|
throw new RuntimeException('DB error: ' . $stmt->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
$updated_count = $stmt->affected_rows;
|
||||||
|
|
||||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_warenkorb_startgebueren WHERE `item_id` IN ($tplaceholders)");
|
|
||||||
$stmt->bind_param(str_repeat('i', count($ids_array)), ...$ids_array);
|
|
||||||
$ret = $stmt->execute();
|
|
||||||
$stmt->close();
|
$stmt->close();
|
||||||
|
|
||||||
return $ret;
|
if ($updated_count === -1) {
|
||||||
}
|
$_SESSION['form_message'] = 'Ein Fehler ist bei der Aktualisierung aufgetreten.';
|
||||||
|
$_SESSION['form_message_type'] = 0;
|
||||||
|
} elseif ($updated_count > 0) {
|
||||||
|
$_SESSION['form_message'] = $updated_count . ' Einträge erfolgreich aktualisiert.';
|
||||||
|
$_SESSION['form_message_type'] = 1;
|
||||||
|
} else {
|
||||||
|
$_SESSION['form_message'] = 'Keine Änderungen vorgenommen.';
|
||||||
|
$_SESSION['form_message_type'] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$vereine_plus_array = [];
|
header('Location: ' . $_SERVER['REQUEST_URI']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($_POST['delete_id'])) {
|
if (isset($_POST['delete_id'])) {
|
||||||
verify_csrf();
|
verify_csrf();
|
||||||
$delete_id = intval($_POST['delete_id']);
|
$delete_id = intval($_POST['delete_id']);
|
||||||
|
|
||||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_teilnehmendee where id = ?");
|
$stmt = $mysqli->prepare("DELETE FROM $tableTeilnehmendee where id = ?");
|
||||||
|
|
||||||
$stmt->bind_param('i', $delete_id);
|
$stmt->bind_param('i', $delete_id);
|
||||||
|
|
||||||
@@ -91,21 +109,19 @@ if (isset($_POST['delete_id'])) {
|
|||||||
$edit_row = null;
|
$edit_row = null;
|
||||||
if ($access_granted_trainer && isset($_GET['edit_id']) && is_numeric($_GET['edit_id']) && !isset($_POST['submit_turnerinnen_form'])) {
|
if ($access_granted_trainer && isset($_GET['edit_id']) && is_numeric($_GET['edit_id']) && !isset($_POST['submit_turnerinnen_form'])) {
|
||||||
$edit_id = intval($_GET['edit_id']);
|
$edit_id = intval($_GET['edit_id']);
|
||||||
$edit_rows = db_select($mysqli, $db_tabelle_teilnehmende, "*", 'id = ?', [$edit_id]);
|
$edit_rows = db_select($mysqli, $tableTeilnehmende, "*", 'id = ?', [$edit_id]);
|
||||||
if (!isset($edit_rows) || !is_array($edit_rows) || count($edit_rows) !== 1) {
|
if (!isset($edit_rows) || !is_array($edit_rows) || count($edit_rows) !== 1) {
|
||||||
http_response_code(422);
|
http_response_code(422);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
$edit_row = $edit_rows[0];
|
$edit_row = $edit_rows[0];
|
||||||
if ($edit_row && ($edit_row['verein'] === $selectedverein || $is_admin)) {
|
if ($edit_row && ($edit_row['verein'] === $selectedverein || $isAdmin)) {
|
||||||
$_POST['nachname'] = $edit_row['name'] ?? '';
|
$_POST['nachname'] = $edit_row['name'] ?? '';
|
||||||
$_POST['vorname'] = $edit_row['vorname'] ?? '';
|
$_POST['vorname'] = $edit_row['vorname'] ?? '';
|
||||||
$_POST['geburtsdatum'] = $edit_row['geburtsdatum'] ?? '';
|
$_POST['geburtsdatum'] = $edit_row['geburtsdatum'] ?? '';
|
||||||
$kat = $edit_row['programm'] ?? '';
|
$_POST['programm'] = $edit_row['programm'] ?? '';
|
||||||
$kat_id = db_get_var($mysqli, "SELECT `id` FROM $db_tabelle_kategorien WHERE `programm` = ?", [$kat]) ?: '';
|
|
||||||
$_POST['programm'] = $kat_id;
|
|
||||||
$_POST['edit_id'] = $edit_id;
|
$_POST['edit_id'] = $edit_id;
|
||||||
if ($is_admin) {
|
if ($isAdmin) {
|
||||||
$_POST['verein'] = $edit_row['verein'] ?? '';
|
$_POST['verein'] = $edit_row['verein'] ?? '';
|
||||||
$_POST['bezahltOverride'] = $edit_row['bezahltoverride'] ?? 0;
|
$_POST['bezahltOverride'] = $edit_row['bezahltoverride'] ?? 0;
|
||||||
}
|
}
|
||||||
@@ -125,18 +141,16 @@ if ($access_granted_trainer && isset($_POST['submit_turnerinnen_form'])) {
|
|||||||
$name = htmlspecialchars($_POST['nachname']);
|
$name = htmlspecialchars($_POST['nachname']);
|
||||||
$vorname = htmlspecialchars($_POST['vorname']);
|
$vorname = htmlspecialchars($_POST['vorname']);
|
||||||
$geburtsdatum = trim($_POST['geburtsdatum']);
|
$geburtsdatum = trim($_POST['geburtsdatum']);
|
||||||
$kat_id = (int) ($_POST['programm'] ?? 0);
|
$programm = htmlspecialchars($_POST['programm']);
|
||||||
|
|
||||||
if (!$is_admin) {
|
if (!$isAdmin) {
|
||||||
$verein = $selectedverein;
|
$verein = $selectedverein;
|
||||||
} else {
|
} else {
|
||||||
$verein = htmlspecialchars($_POST['verein']);
|
$verein = htmlspecialchars($_POST['verein']);
|
||||||
$bezahlt = intval($_POST['bezahltOverride']);
|
$bezahlt = intval($_POST['bezahltOverride']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$kat = db_get_var($mysqli, "SELECT `programm` FROM $db_tabelle_kategorien WHERE `id` = ?", [$kat_id]) ?: '';
|
if (empty($name) || empty($vorname) || empty($geburtsdatum) || empty($programm)) {
|
||||||
|
|
||||||
if (empty($name) || empty($vorname) || empty($geburtsdatum) || empty($kat_id) || empty($kat)) {
|
|
||||||
$_SESSION['form_message'] = 'Bitte füllen Sie alle erforderlichen Felder aus.';
|
$_SESSION['form_message'] = 'Bitte füllen Sie alle erforderlichen Felder aus.';
|
||||||
$_SESSION['form_message_type'] = 0;
|
$_SESSION['form_message_type'] = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -145,11 +159,11 @@ if ($access_granted_trainer && isset($_POST['submit_turnerinnen_form'])) {
|
|||||||
'name' => $name,
|
'name' => $name,
|
||||||
'vorname' => $vorname,
|
'vorname' => $vorname,
|
||||||
'geburtsdatum' => $geburtsdatum,
|
'geburtsdatum' => $geburtsdatum,
|
||||||
'programm' => $kat,
|
'programm' => $programm,
|
||||||
'verein' => $verein,
|
'verein' => $verein,
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($is_admin) {
|
if ($isAdmin) {
|
||||||
$data_to_insert['bezahltoverride'] = $bezahlt;
|
$data_to_insert['bezahltoverride'] = $bezahlt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,16 +174,9 @@ if ($access_granted_trainer && isset($_POST['submit_turnerinnen_form'])) {
|
|||||||
if ($is_editing) {
|
if ($is_editing) {
|
||||||
$edit_id = intval($_POST['edit_id']);
|
$edit_id = intval($_POST['edit_id']);
|
||||||
|
|
||||||
$entry = db_select($mysqli, $db_tabelle_teilnehmende, '*', 'id = ?', [$edit_id], '', '1');
|
$entries = db_select($mysqli, $tableTeilnehmende, '*', 'id = ?', [$edit_id], 'rang ASC');
|
||||||
|
|
||||||
if (count($entry) === 1) {
|
$entry = $entries[0]; // since you're fetching by ID, this should return exactly one row
|
||||||
$old_data = $entry[0];
|
|
||||||
$data_to_insert = array_merge($data_to_insert, get_kat_price_diff($old_data, $kat));
|
|
||||||
remove_from_basket([$edit_id]);
|
|
||||||
update_verein_balances($vereine_plus_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
var_dump($data_to_insert);
|
|
||||||
|
|
||||||
$columns = array_keys($data_to_insert);
|
$columns = array_keys($data_to_insert);
|
||||||
|
|
||||||
@@ -178,7 +185,7 @@ if ($access_granted_trainer && isset($_POST['submit_turnerinnen_form'])) {
|
|||||||
array_map(fn($col) => "$col = ?", $columns)
|
array_map(fn($col) => "$col = ?", $columns)
|
||||||
);
|
);
|
||||||
|
|
||||||
$sql = "UPDATE $db_tabelle_teilnehmende SET $set WHERE id = ?";
|
$sql = "UPDATE $tableTeilnehmende SET $set WHERE id = ?";
|
||||||
|
|
||||||
var_dump($sql);
|
var_dump($sql);
|
||||||
$stmt = $mysqli->prepare($sql);
|
$stmt = $mysqli->prepare($sql);
|
||||||
@@ -216,7 +223,7 @@ if ($access_granted_trainer && isset($_POST['submit_turnerinnen_form'])) {
|
|||||||
array_map(fn($col) => "$col = ?", $columns)
|
array_map(fn($col) => "$col = ?", $columns)
|
||||||
);
|
);
|
||||||
|
|
||||||
$sql = "INSERT INTO $db_tabelle_teilnehmende SET $set";
|
$sql = "INSERT INTO $tableTeilnehmende SET $set";
|
||||||
|
|
||||||
$stmt = $mysqli->prepare($sql);
|
$stmt = $mysqli->prepare($sql);
|
||||||
|
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
+3
-3
@@ -9,10 +9,10 @@ const envPath = path.resolve(__dirname, '..', 'config', '.env.redis');
|
|||||||
dotenv.config({ path: envPath });
|
dotenv.config({ path: envPath });
|
||||||
|
|
||||||
const redisClient = createClient({
|
const redisClient = createClient({
|
||||||
password: process.env.REDIS_PASSWORD,
|
password: process.env.REDDIS_PASSWORD,
|
||||||
socket: {
|
socket: {
|
||||||
host: process.env.REDIS_HOST || 'redis',
|
host: process.env.REDDIS_HOST,
|
||||||
port: process.env.REDIS_PORT || 6379
|
port: process.env.REDDIS_PORT
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Generated
-135
@@ -1,135 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "websocket",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"name": "websocket",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"dotenv": "^17.4.1",
|
|
||||||
"redis": "^5.11.0",
|
|
||||||
"ws": "^8.20.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@redis/bloom": {
|
|
||||||
"version": "5.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.11.0.tgz",
|
|
||||||
"integrity": "sha512-KYiVilAhAFN3057afUb/tfYJpsEyTkQB+tQcn5gVVA7DgcNOAj8lLxe4j8ov8BF6I9C1Fe/kwlbuAICcTMX8Lw==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@redis/client": "^5.11.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@redis/client": {
|
|
||||||
"version": "5.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@redis/client/-/client-5.11.0.tgz",
|
|
||||||
"integrity": "sha512-GHoprlNQD51Xq2Ztd94HHV94MdFZQ3CVrpA04Fz8MVoHM0B7SlbmPEVIjwTbcv58z8QyjnrOuikS0rWF03k5dQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"cluster-key-slot": "1.1.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@node-rs/xxhash": "^1.1.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@node-rs/xxhash": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@redis/json": {
|
|
||||||
"version": "5.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@redis/json/-/json-5.11.0.tgz",
|
|
||||||
"integrity": "sha512-1iAy9kAtcD0quB21RbPTbUqqy+T2Uu2JxucwE+B4A+VaDbIRvpZR6DMqV8Iqaws2YxJYB3GC5JVNzPYio2ErUg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@redis/client": "^5.11.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@redis/search": {
|
|
||||||
"version": "5.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@redis/search/-/search-5.11.0.tgz",
|
|
||||||
"integrity": "sha512-g1l7f3Rnyk/xI99oGHIgWHSKFl45Re5YTIcO8j/JE8olz389yUFyz2+A6nqVy/Zi031VgPDWscbbgOk8hlhZ3g==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@redis/client": "^5.11.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@redis/time-series": {
|
|
||||||
"version": "5.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-5.11.0.tgz",
|
|
||||||
"integrity": "sha512-TWFeOcU4xkj0DkndnOyhtxvX1KWD+78UHT3XX3x3XRBUGWeQrKo3jqzDsZwxbggUgf9yLJr/akFHXru66X5UQA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@redis/client": "^5.11.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/cluster-key-slot": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/dotenv": {
|
|
||||||
"version": "17.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.1.tgz",
|
|
||||||
"integrity": "sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://dotenvx.com"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/redis": {
|
|
||||||
"version": "5.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/redis/-/redis-5.11.0.tgz",
|
|
||||||
"integrity": "sha512-YwXjATVDT+AuxcyfOwZn046aml9jMlQPvU1VXIlLDVAExe0u93aTfPYSeRgG4p9Q/Jlkj+LXJ1XEoFV+j2JKcQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@redis/bloom": "5.11.0",
|
|
||||||
"@redis/client": "5.11.0",
|
|
||||||
"@redis/json": "5.11.0",
|
|
||||||
"@redis/search": "5.11.0",
|
|
||||||
"@redis/time-series": "5.11.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ws": {
|
|
||||||
"version": "8.20.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
|
|
||||||
"integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.0.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"bufferutil": "^4.0.1",
|
|
||||||
"utf-8-validate": ">=5.0.2"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"bufferutil": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"utf-8-validate": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "websocket",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"dotenv": "^17.4.1",
|
|
||||||
"redis": "^5.11.0",
|
|
||||||
"ws": "^8.20.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -316,6 +316,7 @@ function initConditionalVisibility() {
|
|||||||
$rows.each((ind, el) => {
|
$rows.each((ind, el) => {
|
||||||
const $row = $(el);
|
const $row = $(el);
|
||||||
$row.find('.singleValueSpan[data-linked-el-uid]').each(function() {
|
$row.find('.singleValueSpan[data-linked-el-uid]').each(function() {
|
||||||
|
console.log('ja');
|
||||||
const linkedUid = $(this).data('linked-el-uid');
|
const linkedUid = $(this).data('linked-el-uid');
|
||||||
|
|
||||||
const $linkedEl = $row.find(`.singleValueSpan[data-uid="${linkedUid}"]`);
|
const $linkedEl = $row.find(`.singleValueSpan[data-uid="${linkedUid}"]`);
|
||||||
@@ -26,7 +26,7 @@ require $baseDir . '/../scripts/db/db-verbindung-script-guest.php';
|
|||||||
require $baseDir . "/../scripts/db/db-tables.php";
|
require $baseDir . "/../scripts/db/db-tables.php";
|
||||||
require $baseDir . "/../scripts/db/db-functions.php";
|
require $baseDir . "/../scripts/db/db-functions.php";
|
||||||
|
|
||||||
$rankLive_public = db_get_variable($guest, $db_tabelle_var, ['rankLivePublic']) ?? 0;
|
$rankLive_public = db_get_variable($guest, $tableVar, ['rankLivePublic']) ?? 0;
|
||||||
|
|
||||||
require $baseDir . '/../scripts/websocket/ws-create-token.php';
|
require $baseDir . '/../scripts/websocket/ws-create-token.php';
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ $is_live = $type === 'live';
|
|||||||
|
|
||||||
if ($slug !== null && !$is_live) {
|
if ($slug !== null && !$is_live) {
|
||||||
|
|
||||||
$alle_programme_db = db_select($guest, $db_tabelle_kategorien, '`programm`', 'aktiv = ?', ['1']);
|
$alle_programme_db = db_select($guest, $tableProgramme, '`programm`', 'aktiv = ?', ['1']);
|
||||||
$raw_programme = array_column($alle_programme_db, 'programm', 'programm');
|
$raw_programme = array_column($alle_programme_db, 'programm', 'programm');
|
||||||
|
|
||||||
$alle_programme = [];
|
$alle_programme = [];
|
||||||
@@ -69,14 +69,20 @@ $selectedFreigabeId = 'A';
|
|||||||
|
|
||||||
$json_type = $is_live ? 'rankLive-geraet' : 'rankLive-overview';
|
$json_type = $is_live ? 'rankLive-geraet' : 'rankLive-overview';
|
||||||
|
|
||||||
$jsonstr = db_select($guest, $db_tabelle_tabellen_konfiguration, 'json', 'type_slug = ?', [$json_type], '', 1);
|
$jsonstr = db_select($guest, $tableRankLiveConfigs, 'json', 'type_slug = ?', [$json_type], '', 1);
|
||||||
|
|
||||||
$data = json_decode($jsonstr[0]['json'], true);
|
$data = json_decode($jsonstr[0]['json'], true);
|
||||||
|
|
||||||
$headers = $data['header'] ?? [];
|
$headers = $data['header'] ?? [];
|
||||||
$bodyColumns = $data['body'] ?? [];
|
$bodyColumns = $data['body'] ?? [];
|
||||||
|
|
||||||
$alle_programme_db = db_select($guest, $db_tabelle_kategorien, '`programm`, `id`', 'aktiv = ?', ['1']);
|
$current_year = date('Y');
|
||||||
|
$monat = date('n');
|
||||||
|
if ($monat > 6) {
|
||||||
|
$current_year = $current_year + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$alle_programme_db = db_select($guest, $tableProgramme, '`programm`, `id`', 'aktiv = ?', ['1']);
|
||||||
$indexedProgrammes = array_column($alle_programme_db, 'programm', 'id');
|
$indexedProgrammes = array_column($alle_programme_db, 'programm', 'id');
|
||||||
|
|
||||||
$personData = [
|
$personData = [
|
||||||
@@ -87,7 +93,7 @@ $personData = [
|
|||||||
'programm' => 'Programm'
|
'programm' => 'Programm'
|
||||||
];
|
];
|
||||||
|
|
||||||
$disciplines = db_select($guest, $db_tabelle_disziplinen, '*', '', [], 'start_index ASC');
|
$disciplines = db_select($guest, $tableGeraete, '*', '', [], 'start_index ASC');
|
||||||
|
|
||||||
$indexedArrayGeraete = array_column($disciplines, 'name', 'id');
|
$indexedArrayGeraete = array_column($disciplines, 'name', 'id');
|
||||||
|
|
||||||
@@ -96,8 +102,8 @@ if ($is_live) {
|
|||||||
|
|
||||||
$indexed_array_geraete_index_id = array_flip($indexed_array_geraete_id_index);
|
$indexed_array_geraete_index_id = array_flip($indexed_array_geraete_id_index);
|
||||||
|
|
||||||
$abt = (int) (db_get_variable($guest, $db_tabelle_var, ['wk_panel_current_abt']) ?? 1);
|
$abt = (int) (db_get_variable($guest, $tableVar, ['wk_panel_current_abt']) ?? 1);
|
||||||
$akt_subabt = (int) (db_get_variable($guest, $db_tabelle_var, ['wk_panel_current_subabt_admin']) ?? 1);
|
$akt_subabt = (int) (db_get_variable($guest, $tableVar, ['wk_panel_current_subabt_admin']) ?? 1);
|
||||||
|
|
||||||
$max_subabt = count($disciplines);
|
$max_subabt = count($disciplines);
|
||||||
|
|
||||||
@@ -112,11 +118,11 @@ if ($is_live) {
|
|||||||
tabt.`turnerin_index` AS start_index,
|
tabt.`turnerin_index` AS start_index,
|
||||||
tabt.`geraet_id` AS startgeraet,
|
tabt.`geraet_id` AS startgeraet,
|
||||||
tabt.`abteilung_id` AS abt_id
|
tabt.`abteilung_id` AS abt_id
|
||||||
FROM $db_tabelle_teilnehmende t
|
FROM $tableTeilnehmende t
|
||||||
LEFT JOIN $db_tabelle_kategorien p ON p.programm = t.programm
|
LEFT JOIN $tableProgramme p ON p.programm = t.programm
|
||||||
INNER JOIN $db_tabelle_teilnehmende_gruppen tabt ON tabt.`turnerin_id` = t.`id`
|
INNER JOIN $tableTeilnehmendeAbt tabt ON tabt.`turnerin_id` = t.`id`
|
||||||
INNER JOIN $db_tabelle_gruppen abt ON abt.`id` = tabt.`abteilung_id`
|
INNER JOIN $tableAbt abt ON abt.`id` = tabt.`abteilung_id`
|
||||||
WHERE (t.bezahlt = 4 OR t.bezahltoverride = 4) AND abt.`order_index` = ?");
|
WHERE (t.bezahlt = 2 OR t.bezahltoverride = 5) AND abt.`order_index` = ?");
|
||||||
|
|
||||||
$stmt->bind_param("i", $abt);
|
$stmt->bind_param("i", $abt);
|
||||||
} elseif ($type === 'programm' && $slug !== null) {
|
} elseif ($type === 'programm' && $slug !== null) {
|
||||||
@@ -128,9 +134,9 @@ if ($is_live) {
|
|||||||
u.verein,
|
u.verein,
|
||||||
u.geburtsdatum,
|
u.geburtsdatum,
|
||||||
p.id AS programm_id
|
p.id AS programm_id
|
||||||
FROM $db_tabelle_teilnehmende u
|
FROM $tableTeilnehmende u
|
||||||
LEFT JOIN $db_tabelle_kategorien p ON p.programm = u.programm
|
LEFT JOIN $tableProgramme p ON p.programm = u.programm
|
||||||
WHERE (u.bezahlt = 4 OR u.bezahltoverride = 4) AND u.programm = ?");
|
WHERE (u.bezahlt = 2 OR u.bezahltoverride = 5) AND u.programm = ?");
|
||||||
|
|
||||||
$stmt->bind_param("s", $validated_programm_name);
|
$stmt->bind_param("s", $validated_programm_name);
|
||||||
} else {
|
} else {
|
||||||
@@ -142,9 +148,9 @@ if ($is_live) {
|
|||||||
u.verein,
|
u.verein,
|
||||||
u.geburtsdatum,
|
u.geburtsdatum,
|
||||||
p.id AS programm_id
|
p.id AS programm_id
|
||||||
FROM $db_tabelle_teilnehmende u
|
FROM $tableTeilnehmende u
|
||||||
LEFT JOIN $db_tabelle_kategorien p ON p.programm = u.programm
|
LEFT JOIN $tableProgramme p ON p.programm = u.programm
|
||||||
WHERE (u.bezahlt = 4 OR u.bezahltoverride = 4)");
|
WHERE (u.bezahlt = 2 OR u.bezahltoverride = 5)");
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
@@ -160,14 +166,12 @@ foreach ($tures as $s_tures) {
|
|||||||
$indexedTures[$s_tures['programm_id']][$s_tures['id']] = $s_tures;
|
$indexedTures[$s_tures['programm_id']][$s_tures['id']] = $s_tures;
|
||||||
}
|
}
|
||||||
|
|
||||||
$current_wk_id = (int) db_get_variable($guest, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
|
||||||
|
|
||||||
$stmt = $guest->prepare("SELECT `note_bezeichnung_id`, `geraet_id`, `person_id`, `run_number`, `public_value`
|
$stmt = $guest->prepare("SELECT `note_bezeichnung_id`, `geraet_id`, `person_id`, `run_number`, `public_value`
|
||||||
FROM $db_tabelle_wertungen
|
FROM $tableNoten
|
||||||
WHERE `is_public` = 1
|
WHERE `is_public` = 1
|
||||||
AND `wk_id` = ?");
|
AND `jahr` = ?");
|
||||||
|
|
||||||
$stmt->bind_param("i", $current_wk_id);
|
$stmt->bind_param("i", $current_year);
|
||||||
|
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
@@ -178,7 +182,7 @@ $stmt->close();
|
|||||||
|
|
||||||
$indexedNoten = [];
|
$indexedNoten = [];
|
||||||
|
|
||||||
$stmt = $guest->prepare("SELECT `id`, `geraete_json`, `pro_geraet`, `anzahl_laeufe_json`, `name`, `default_value` FROM $db_tabelle_wertungstypen");
|
$stmt = $guest->prepare("SELECT `id`, `geraete_json`, `pro_geraet`, `anzahl_laeufe_json`, `name`, `default_value` FROM $tableNotenBezeichnungen");
|
||||||
|
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
@@ -187,13 +191,13 @@ $notenConfig = $result->fetch_all(MYSQLI_ASSOC);
|
|||||||
|
|
||||||
$stmt->close();
|
$stmt->close();
|
||||||
|
|
||||||
$disciplines = db_select($guest, $db_tabelle_disziplinen, '*', '', [], 'start_index ASC');
|
$disciplines = db_select($guest, $tableGeraete, '*', '', [], 'start_index ASC');
|
||||||
|
|
||||||
$indexedNotenConfig = array_column($notenConfig, null, 'id');
|
$indexedNotenConfig = array_column($notenConfig, null, 'id');
|
||||||
|
|
||||||
$rangNote = intval(db_get_var($guest, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['rangNote']));
|
$rangNote = intval(db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['rangNote']));
|
||||||
|
|
||||||
$orderBestRang = db_get_var($guest, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['orderBestRang']);
|
$orderBestRang = db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['orderBestRang']);
|
||||||
|
|
||||||
$okValuesOrderBestRang = ["ASC", "DESC"];
|
$okValuesOrderBestRang = ["ASC", "DESC"];
|
||||||
|
|
||||||
@@ -213,13 +217,12 @@ $disciplinesExtended = array_merge(
|
|||||||
$arrayIndexedNoten = [];
|
$arrayIndexedNoten = [];
|
||||||
|
|
||||||
|
|
||||||
$wkName = db_get_var($guest, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['wkName']);
|
$wkName = db_get_var($guest, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['wkName']);
|
||||||
|
|
||||||
$grouped = [];
|
$grouped = [];
|
||||||
|
|
||||||
function groop_by_key($array, $array_key, bool $int = false): array
|
function groop_by_key($array, $array_key, bool $int = false): array
|
||||||
{
|
{
|
||||||
$grouped = [];
|
|
||||||
if ($int) {
|
if ($int) {
|
||||||
foreach ($array as $entry) {
|
foreach ($array as $entry) {
|
||||||
$key = (int) $entry[$array_key];
|
$key = (int) $entry[$array_key];
|
||||||
@@ -436,30 +439,15 @@ function constructSingleValueSpanPublic($token, $type, $row, $selected_geraet_id
|
|||||||
<link rel="stylesheet" href="/intern/css/custom-msg-display.css">
|
<link rel="stylesheet" href="/intern/css/custom-msg-display.css">
|
||||||
<link href="/files/fonts/fonts.css" rel="stylesheet">
|
<link href="/files/fonts/fonts.css" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="/css/custom-display-editor-required-css.css">
|
<link rel="stylesheet" href="/css/custom-display-editor-required-css.css">
|
||||||
<link rel="stylesheet" href="/css/rank-live.css">
|
|
||||||
<link rel="stylesheet" href="/css/header.css">
|
|
||||||
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
|
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
|
||||||
<script src="/intern/js/custom-msg-display.js"></script>
|
<script src="/intern/js/custom-msg-display.js"></script>
|
||||||
<script src="/js/header.js"></script>
|
|
||||||
<title>RankLive - <?= htmlspecialchars($wkName) ?></title>
|
<title>RankLive - <?= htmlspecialchars($wkName) ?></title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<section class="bgSection">
|
|
||||||
<?php include $baseDir . '/../scripts/public-elements/rankLive-header.php'; ?>
|
|
||||||
<?php if (count($indexedTures) < 1) : ?>
|
<?php if (count($indexedTures) < 1) : ?>
|
||||||
<h3>Noch keine Daten verfügbar</h3>
|
<h3>Noch keine Daten verfügbar</h3>
|
||||||
<?php exit; ?>
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<div class="headerWrapper">
|
|
||||||
<h2 class="headerMain">RankLive</h2>
|
|
||||||
<?php if ($is_live) : ?>
|
|
||||||
<h4>Gruppe: <?= (int) $abt ?></h4>
|
|
||||||
<h4>Rotation: <?= (int) $akt_subabt ?></h4>
|
|
||||||
<?php elseif ($type === 'programm' && $slug !== null) : ?>
|
|
||||||
<h4><?= htmlspecialchars($validated_programm_name) ?></h4>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<div class="allAbtContainer">
|
<div class="allAbtContainer">
|
||||||
<?php foreach ($grouped as $entry_key => $entries_group):
|
<?php foreach ($grouped as $entry_key => $entries_group):
|
||||||
|
|
||||||
@@ -488,7 +476,7 @@ function constructSingleValueSpanPublic($token, $type, $row, $selected_geraet_id
|
|||||||
|
|
||||||
// Hole maxStartIndex (mit Caching-Logik optional)
|
// Hole maxStartIndex (mit Caching-Logik optional)
|
||||||
if (!isset($maxStartIndexCache["$abtId-$old_geraet_id "])) {
|
if (!isset($maxStartIndexCache["$abtId-$old_geraet_id "])) {
|
||||||
$maxStartIndexCache["$abtId-$old_geraet_id"] = db_get_var($guest, "SELECT COUNT(*) FROM `$db_tabelle_teilnehmende_gruppen` WHERE abteilung_id = ? AND geraet_id = ?", [$abtId, $old_geraet_id]);
|
$maxStartIndexCache["$abtId-$old_geraet_id"] = db_get_var($guest, "SELECT COUNT(*) FROM `$tableTeilnehmendeAbt` WHERE abteilung_id = ? AND geraet_id = ?", [$abtId, $old_geraet_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$maxstartindex = $maxStartIndexCache["$abtId-$old_geraet_id"];
|
$maxstartindex = $maxStartIndexCache["$abtId-$old_geraet_id"];
|
||||||
@@ -561,11 +549,13 @@ function constructSingleValueSpanPublic($token, $type, $row, $selected_geraet_id
|
|||||||
endforeach;
|
endforeach;
|
||||||
endforeach; ?>
|
endforeach; ?>
|
||||||
<div class="singleAbtDiv<?= $extra_table_classes ?>" <?= $table_data_geraet_label ?>>
|
<div class="singleAbtDiv<?= $extra_table_classes ?>" <?= $table_data_geraet_label ?>>
|
||||||
<?php if (!($type === 'programm' && $slug !== null)) : ?>
|
<?php if ($is_live) : ?>
|
||||||
<h2 class="headerAbt"><?= ($is_live) ? $indexedArrayGeraete[$shifted_geraet_id] ?? '' : $entry_key ?? '' ?></h2>
|
<h3><?= $indexedArrayGeraete[$shifted_geraet_id] ?? '' ?></h3>
|
||||||
|
<?php else: ?>
|
||||||
|
<h3><?= $entry_key ?? '' ?></h3>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php $geraet_id_for_live_view = $is_live ? $shifted_geraet_id : 0 ?>
|
<?php $geraet_id_for_live_view = $is_live ? $shifted_geraet_id : 0 ?>
|
||||||
<div class="tableWraper">
|
<div class="scoreboard-container">
|
||||||
<table class="customDisplayEditorTable">
|
<table class="customDisplayEditorTable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -635,8 +625,6 @@ function constructSingleValueSpanPublic($token, $type, $row, $selected_geraet_id
|
|||||||
</div>
|
</div>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="tableCutter"></div>
|
|
||||||
</section>
|
|
||||||
<style>
|
<style>
|
||||||
<?php
|
<?php
|
||||||
$unique_display_over_array = array_unique($display_over_array);
|
$unique_display_over_array = array_unique($display_over_array);
|
||||||
@@ -655,7 +643,7 @@ function constructSingleValueSpanPublic($token, $type, $row, $selected_geraet_id
|
|||||||
window.FREIGABE = "<?= $selectedFreigabeId; ?>";
|
window.FREIGABE = "<?= $selectedFreigabeId; ?>";
|
||||||
window.CSDR_TOKEN = "<?= $csrf_token; ?>";
|
window.CSDR_TOKEN = "<?= $csrf_token; ?>";
|
||||||
window.WS_ACCESS_TOKEN = "<?= generateWSReadToken('rankLive', $selectedFreigabeId) ?>";
|
window.WS_ACCESS_TOKEN = "<?= generateWSReadToken('rankLive', $selectedFreigabeId) ?>";
|
||||||
window.AKTUELLES_JAHR = "<?= $current_wk_id ?>";
|
window.AKTUELLES_JAHR = "<?= $current_year ?>";
|
||||||
window.RANG_NOTEN_ARRAY = '<?= json_encode($rangNotenArray, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT); ?>';
|
window.RANG_NOTEN_ARRAY = '<?= json_encode($rangNotenArray, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT); ?>';
|
||||||
window.RANG_SORT = "<?= $orderBestRang ?>";
|
window.RANG_SORT = "<?= $orderBestRang ?>";
|
||||||
window.RANG_NOTE_ID = <?= $rangNote ?>;
|
window.RANG_NOTE_ID = <?= $rangNote ?>;
|
||||||
+12
-39
@@ -1,48 +1,19 @@
|
|||||||
|
|
||||||
:root {
|
:root {
|
||||||
--sb-bg: #f8fafc;
|
--sb-bg: #f8fafc;
|
||||||
--sb-card-bg: #ffffff;
|
--sb-card-bg: #ffffff;
|
||||||
--sb-text-main: #36454F;
|
--sb-text-main: #36454F;
|
||||||
--sb-text-muted: #64748b;
|
--sb-text-muted: #64748b;
|
||||||
|
--sb-primary: #1e40af; /* Deep athletic blue */
|
||||||
|
--sb-accent: #2563eb; /* Vivid score blue */
|
||||||
--sb-border: #e2e8f0;
|
--sb-border: #e2e8f0;
|
||||||
--sb-hover: #f3f3f3;
|
--sb-hover: #f3f3f3;
|
||||||
--sb-radius: 12px;
|
--sb-radius: 12px;
|
||||||
|
--font-numeric: 'Courier New', Courier, monospace; /* Clean alignment for scores */
|
||||||
/* Newly extracted color variables */
|
|
||||||
--sb-th-text: #1e293b;
|
|
||||||
--sb-th-border: #1e293b;
|
|
||||||
--sb-th-bg: #ffffff;
|
|
||||||
--sb-tr-even-bg: #f8f8f860;
|
|
||||||
--sb-changeable-bg: rgba(37, 99, 235, 0.02);
|
|
||||||
--sb-flash-highlight: #00ff99; /* Green flash for updates */
|
|
||||||
|
|
||||||
--font-numeric: 'Courier New', Courier, monospace;
|
|
||||||
--padding-td: clamp(3px, 2.5vh, 12px) clamp(4px, 2vw, 20px);
|
--padding-td: clamp(3px, 2.5vh, 12px) clamp(4px, 2vw, 20px);
|
||||||
--padding-th: clamp(2px, 1.5vh, 6px) clamp(4px, 2vw, 20px);
|
--padding-th: clamp(2px, 1.5vh, 6px) clamp(4px, 2vw, 20px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark){
|
|
||||||
:root {
|
|
||||||
--sb-bg: #121212; /* Dark main background */
|
|
||||||
--sb-card-bg: #1a1a1a; /* Dark card surfaces */
|
|
||||||
--sb-text-main: #f5f5f5; /* Light grey/white text */
|
|
||||||
--sb-text-muted: #a0a0a0; /* Muted secondary text */
|
|
||||||
--sb-border: #2d2d2d; /* Soft dark border line */
|
|
||||||
--sb-hover: #252525; /* Subtle highlight on row hover */
|
|
||||||
--sb-radius: 12px;
|
|
||||||
|
|
||||||
/* Dark mode specific variables */
|
|
||||||
--sb-th-text: #ffffff; /* Crisp white headers */
|
|
||||||
--sb-th-border: #3d3d3d; /* Distinct header separation */
|
|
||||||
--sb-th-bg: #121212; /* Matches dark body background */
|
|
||||||
--sb-tr-even-bg: #1a1a1a40; /* Very soft zebra striping */
|
|
||||||
--sb-changeable-bg: rgba(240, 163, 236, 0.05); /* Soft background using the pink/purple accent */
|
|
||||||
--sb-flash-highlight: #39ff14; /* Vibrant neon green for live updates on dark backgrounds */
|
|
||||||
|
|
||||||
--font-numeric: 'Courier New', Courier, monospace;
|
|
||||||
--padding-td: clamp(3px, 2.5vh, 12px) clamp(4px, 2vw, 20px);
|
|
||||||
--padding-th: clamp(2px, 1.5vh, 6px) clamp(4px, 2vw, 20px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Base Table Styling */
|
/* Base Table Styling */
|
||||||
.customDisplayEditorTable {
|
.customDisplayEditorTable {
|
||||||
@@ -56,15 +27,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.customDisplayEditorTable th {
|
.customDisplayEditorTable th {
|
||||||
color: var(--sb-th-text);
|
color: #1e293b;
|
||||||
border-bottom: solid 1px var(--sb-th-border);
|
border-bottom: solid 1px #1e293b;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
padding: var(--padding-th);
|
padding: var(--padding-th);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
background-color: var(--sb-th-bg);
|
background-color: #fff;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
@@ -83,23 +54,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.customDisplayEditorTable tbody > tr:nth-child(even) td {
|
.customDisplayEditorTable tbody > tr:nth-child(even) td {
|
||||||
background-color: var(--sb-tr-even-bg);
|
background-color: #f8f8f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.customDisplayEditorTable tbody > tr:hover td {
|
.customDisplayEditorTable tbody > tr:hover td {
|
||||||
background-color: var(--sb-hover) !important;
|
background-color: var(--sb-hover) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.customDisplayEditorTable td {
|
.customDisplayEditorTable td {
|
||||||
color: var(--sb-text-main);
|
color: var(--sb-text-main);
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.customDisplayEditorTable td.changebleValue {
|
.customDisplayEditorTable td.changebleValue {
|
||||||
font-family: var(--font-numeric);
|
font-family: var(--font-numeric);
|
||||||
font-size: 1.05rem;
|
font-size: 1.05rem;
|
||||||
color: var(--sb-text-main);
|
color: var(--sb-text-main);
|
||||||
background-color: var(--sb-changeable-bg);
|
background-color: rgb(37 99 235 / 0.02);
|
||||||
}
|
}
|
||||||
|
|
||||||
.customDisplayEditorTable tr:last-child td {
|
.customDisplayEditorTable tr:last-child td {
|
||||||
@@ -111,7 +84,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes flashHighlight {
|
@keyframes flashHighlight {
|
||||||
0% { color: var(--sb-flash-highlight); }
|
0% { color: #00ff99; }
|
||||||
100% { color: var(--sb-text-main); }
|
100% { color: var(--sb-text-main); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ require_once $baseDir . '/../scripts/db/db-verbindung-script-guest.php';
|
|||||||
require_once $baseDir . '/../scripts/db/db-functions.php';
|
require_once $baseDir . '/../scripts/db/db-functions.php';
|
||||||
require_once $baseDir . '/../scripts/db/db-tables.php';
|
require_once $baseDir . '/../scripts/db/db-tables.php';
|
||||||
|
|
||||||
$stmt = $guest->prepare("SELECT `name`, `id` FROM $db_tabelle_disziplinen WHERE `audiofile` = '1' ORDER BY start_index ASC");
|
$stmt = $guest->prepare("SELECT `name`, `id` FROM $tableGeraete WHERE `audiofile` = '1' ORDER BY start_index ASC");
|
||||||
|
|
||||||
if (!$stmt->execute()) {
|
if (!$stmt->execute()) {
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
@@ -34,7 +34,7 @@ require_once $baseDir . '/../scripts/db/db-verbindung-script-guest.php';
|
|||||||
require_once $baseDir . '/../scripts/db/db-functions.php';
|
require_once $baseDir . '/../scripts/db/db-functions.php';
|
||||||
require_once $baseDir . '/../scripts/db/db-tables.php';
|
require_once $baseDir . '/../scripts/db/db-tables.php';
|
||||||
|
|
||||||
$stmt = $guest->prepare("SELECT `name`, `id` FROM $db_tabelle_disziplinen ORDER BY start_index ASC");
|
$stmt = $guest->prepare("SELECT `name`, `id` FROM $tableGeraete ORDER BY start_index ASC");
|
||||||
|
|
||||||
if (!$stmt->execute()) {
|
if (!$stmt->execute()) {
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
@@ -84,7 +84,7 @@ $keysNeeded = [
|
|||||||
|
|
||||||
$placeholders = implode(',', array_fill(0, count($keysNeeded), '?'));
|
$placeholders = implode(',', array_fill(0, count($keysNeeded), '?'));
|
||||||
|
|
||||||
$query = "SELECT `name`, `value` FROM $db_tabelle_var WHERE `name` IN ($placeholders)";
|
$query = "SELECT `name`, `value` FROM $tableVar WHERE `name` IN ($placeholders)";
|
||||||
|
|
||||||
$stmt = $guest->prepare($query);
|
$stmt = $guest->prepare($query);
|
||||||
$params = str_repeat("s", count($keysNeeded));
|
$params = str_repeat("s", count($keysNeeded));
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user