Überarbeitete Version der 1. Version. Es bestehen noch grosse Feher in einzelnen Skripten.

This commit is contained in:
Fabio Herzig
2026-04-18 23:45:17 +02:00
parent a51fd9dbeb
commit 3731183654
85 changed files with 2965 additions and 3371 deletions

2
.gitignore vendored
View File

@@ -11,3 +11,5 @@ private-files/rechnungen/*
.php-ini
.php-version
www/displays/json/*
www/intern/scripts/kampfrichter/ajax/neu.php
www/intern/scripts/kampfrichter/ajax/neu_copy.php

View File

@@ -1,16 +0,0 @@
<?php
function csrf_token() {
if (session_status() === PHP_SESSION_NONE) session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(64));
}
return $_SESSION['csrf_token'];
}
function verify_csrf() {
if (!isset($_POST['csrf_token']) ||
!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
return false;
}
return true;
}

View File

@@ -2,24 +2,6 @@
use Dotenv\Dotenv;
if (!isset($token)){
http_response_code(403);
echo json_encode([
'success' => false,
'message' => 'security check failed: ERROR 01'
]);
exit;
}
if ($token !== 'QQa2UMbEYW8oOL7wz9DjtqECVCikSZsDuSdmzxiadEXFsKyujEUyQOW1AYMD2OqU8VXxClIRweRuWLzvBrZpPYL41e89Rs96tM7Lq1KpjA5E2mg2UfgvztheGRV'){
http_response_code(403);
echo json_encode([
'success' => false,
'message' => 'security check failed: ERROR 02'
]);
exit;
}
require __DIR__ . '/../../composer/vendor/autoload.php';
$envFile = realpath(__DIR__ . '/../../config/.env.db-guest');

View File

@@ -2,7 +2,9 @@
use Dotenv\Dotenv;
if(session_status() !== PHP_SESSION_ACTIVE) session_start();
require_once __DIR__ . '/../session_functions.php';
ini_wkvs_session();
if (!isset($type)){
return [
@@ -12,22 +14,13 @@ if (!isset($type)){
}
if ($type === 'kr'){
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
http_response_code(403);
exit;
}
check_user_permission('kampfrichter');
} elseif ($type === 'tr'){
if (empty($_SESSION['access_granted_trainer']) || $_SESSION['access_granted_trainer'] !== true || empty($_SESSION['passcodetrainer_id']) || $_SESSION['passcodetrainer_id'] < 1) {
http_response_code(403);
exit;
}
check_user_permission('trainer');
} elseif ($type === 'wkl') {
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 1 ) {
http_response_code(403);
exit;
}
check_user_permission('wk_leitung');
} elseif ($type === 'otl') {
if (empty($_SESSION['set_new_password_id_user']) || empty($_SESSION['set_new_password_granted']) || $_SESSION['set_new_password_granted'] !== true || $_SESSION['set_new_password_id_user'] < 1 ) {
if (empty($_SESSION['access_granted_db_otl']) || $_SESSION['access_granted_db_otl'] !== true) {
http_response_code(403);
exit;
}

View File

@@ -1,12 +1,6 @@
<?php
if ( empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || intval($_SESSION['passcodekampfrichter_id']) < 1 ) {
http_response_code(403);
exit;
}
// ========== Access control setup ==========
$userid = intval($_SESSION['passcodekampfrichter_id'] ?? 0);
$userid = intval($_SESSION['user_id_kampfrichter'] ?? 0);
$arrayfreigaben = [];
if ($userid > 0) {

View File

@@ -1,277 +1,11 @@
<?php
if ( empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || intval($_SESSION['passcodekampfrichter_id']) < 1 ) {
http_response_code(403);
exit;
}
// ========== Form handling logic ==========
$form_message = $_SESSION['form_message'] ?? '';
unset($_SESSION['form_message']);
// Handle recalculate all scores action
if ($selecteduser === 'admin' && isset($_POST['recalculate_scores'])) {
if (!verify_csrf()) {
$form_message = 'Sicherheitsproblem bei der Neuberechnung.';
} else {
$disciplines = ['sprung', 'barren', 'balken', 'boden'];
// Build column list
$columns = implode(', ', array_map(fn ($d) => "`note $d`", $disciplines));
$columns_array = array_merge(
['id', 'programm'],
array_map(fn($d) => "note $d", $disciplines)
);
$all_rows = db_select($mysqli, $tableTurnerinnen, $columns_array, 'bezahlt = ? OR bezahltoverride = ?', ['2', '5']);
$success = 0;
// Step 1: Calculate gesamtpunktzahl and update per row
foreach ($all_rows as $row) {
$sum = 0;
foreach ($disciplines as $discipline) {
$value = $row["note $discipline"];
if (is_numeric($value)) {
$sum += floatval($value);
}
}
db_update($mysqli, $tableTurnerinnen, ['gesamtpunktzahl' => $sum], ['id' => $row['id']]);
$success++;
}
// Step 2: Re-fetch rows grouped by programm with updated gesamtpunktzahl
$all_programms = db_get_col($mysqli, "SELECT DISTINCT programm FROM ".$tableTurnerinnen);
foreach ($all_programms as $programm) {
$group = db_select($mysqli, $tableTurnerinnen, ['id', 'gesamtpunktzahl', 'note sprung', 'note barren', 'note balken', 'note boden', 'geburtsdatum'], 'programm = ? AND (bezahlt = ? OR bezahltoverride = ?)', [$programm, '2', '5']);
usort($group, function ($a, $b) {
$scoreA = floatval($a['gesamtpunktzahl']);
$scoreB = floatval($b['gesamtpunktzahl']);
if ($scoreA !== $scoreB) return $scoreB <=> $scoreA;
// Only for top 3 tie-breaking
$scoresA = [
floatval($a['note sprung']),
floatval($a['note barren']),
floatval($a['note balken']),
floatval($a['note boden']),
];
$scoresB = [
floatval($b['note sprung']),
floatval($b['note barren']),
floatval($b['note balken']),
floatval($b['note boden']),
];
rsort($scoresA);
rsort($scoresB);
$sumTop3A = $scoresA[0] + $scoresA[1] + $scoresA[2];
$sumTop3B = $scoresB[0] + $scoresB[1] + $scoresB[2];
if (abs($sumTop3A - $sumTop3B) > 0.001) return $sumTop3B <=> $sumTop3A;
$sumTop2A = $scoresA[0] + $scoresA[1];
$sumTop2B = $scoresB[0] + $scoresB[1];
if (abs($sumTop2A - $sumTop2B) > 0.001) return $sumTop2B <=> $sumTop2A;
if (abs($scoresA[0] - $scoresB[0]) > 0.001) return $scoresB[0] <=> $scoresA[0];
// Younger participant ranks higher in case of full tie
$dateA = strtotime($a['geburtsdatum']);
$dateB = strtotime($b['geburtsdatum']);
return $dateB <=> $dateA; // later birthdate = younger = better
});
// Step 2: Assign ranks
$ranked = [];
$current_rank = 1;
$i = 0;
while ($i < count($group)) {
$current = $group[$i];
$tie_group = [$current];
$j = $i + 1;
while ($j < count($group)) {
$next = $group[$j];
// Tie logic
if ($current_rank <= 3) {
// Top 3: full tie-breaking
$is_tie =
round(floatval($current['gesamtpunktzahl']), 3) === round(floatval($next['gesamtpunktzahl']), 3) &&
round(floatval($current['note sprung']), 3) === round(floatval($next['note sprung']), 3) &&
round(floatval($current['note barren']), 3) === round(floatval($next['note barren']), 3) &&
round(floatval($current['note balken']), 3) === round(floatval($next['note balken']), 3) &&
round(floatval($current['note boden']), 3) === round(floatval($next['note boden']), 3) &&
$current['geburtsdatum'] === $next['geburtsdatum'];
} else {
// Ranks > 3: only check gesamtpunktzahl
$is_tie = round(floatval($current['gesamtpunktzahl']), 3) === round(floatval($next['gesamtpunktzahl']), 3);
}
if ($is_tie) {
$tie_group[] = $next;
$j++;
} else {
break;
}
}
// Assign the same rank for all ties in ranks > 3
foreach ($tie_group as $entry) {
$ranked[] = [
'id' => $entry['id'],
'rang' => $current_rank
];
}
$i += count($tie_group);
$current_rank += count($tie_group);
}
// Step 3: Write all ranks to DB
foreach ($ranked as $r) {
db_update($mysqli, $tableTurnerinnen, ['rang' => $r['rang']], ['id' => $r['id']]);
}
}
$_SESSION['form_message'] =
$success . ' Einträge wurden aktualisiert und neu gerankt.';
header("Location: ". $_SERVER['REQUEST_URI']);
exit;
}
}
if ($selecteduser === 'admin' && isset($_POST['reset_scores'])) {
if (!verify_csrf()) {
$form_message = 'Sicherheitsproblem bei der Neuberechnung.';
} else {
$all_rows = db_select($mysqli, $tableTurnerinnen, 'id');
$success = 0;
foreach ($all_rows as $row) {
db_update($mysqli, $tableTurnerinnen, ['gesamtpunktzahl' => 0, 'rang' => 0], ['id' => $row['id']]);
$success++;
}
$_SESSION['form_message'] = '<div class="success">' . $success . ' Einträge wurden zurückgesetzt.</div>';
header("Location: ". $_SERVER['REQUEST_URI']);
exit;
}
}
// === EDIT MODE: Load existing data if edit_id is present in URL ===
$edit_row = null;
if (isset($_GET['edit_id']) && is_numeric($_GET['edit_id']) && !isset($_POST['submit_turnerinnen_form'])) {
$edit_id = intval($_GET['edit_id']);
$edit_row = db_select($mysqli, $tableTurnerinnen, '*', 'id = ?', [$edit_id]);
foreach ($disciplines as $discipline) {
if ($selecteduser === ucfirst($discipline) || $selecteduser === 'admin') {
$_POST["d-note_{$discipline}"] = $edit_row["d-note {$discipline}"] ??
'';
$_POST["note_{$discipline}"] = $edit_row["note {$discipline}"] ?? '';
}
}
if ($selecteduser === 'admin') {
$gesamt = 0;
foreach ($disciplines as $discipline) {
if (isset($edit_row[0]["note {$discipline}"]) && is_numeric($edit_row[0]["note {$discipline}"])) {
$gesamt += floatval($edit_row[0]["note {$discipline}"]);
}
}
$_POST["gesamtpunktzahl"] = $gesamt;
$rang = isset($_POST['rang']) ? intval($_POST['rang']) : 0; // Safely get and cast to int
$data_to_insert["rang"] = $rang;
$data_formats[] = '%d';
}
$_POST['edit_id'] = $edit_id;
}
if (isset($_POST['submit_turnerinnen_form'])) {
// Check nonce
if (!verify_csrf()) {
$form_message = 'Sicherheitsproblem: Ungültige Formularübermittlung.';
} else {
foreach ($disciplines as $discipline) {
if ($selecteduser === ucfirst($discipline) || $selecteduser === 'admin') {
${"d_note_$discipline"} = floatval($_POST["d-note_{$discipline}"]);
${"note_$discipline"} = floatval($_POST["note_{$discipline}"]);
// Add to data array
$data_to_insert["d-note $discipline"] = ${"d_note_$discipline"};
$data_to_insert["note $discipline"] = ${"note_$discipline"};
$data_formats[] = '%f'; // float format for d-note
$data_formats[] = '%f';
// float format for note
}
}
if ($selecteduser === 'admin') {
$gesamtpunktzahl = isset($_POST['gesamtpunktzahl']) ?
intval($_POST['gesamtpunktzahl']) : 0; // Safely get and cast to int
$data_to_insert["gesamtpunktzahl"] = $gesamtpunktzahl;
$data_formats[] = '%f';
// CORRECTED LINE: Get 'rang' from $_POST
$rang = isset($_POST['rang']) ?
intval($_POST['rang']) : 0; // Safely get and cast to int
$data_to_insert["rang"] = $rang;
$data_formats[] = '%d';
}
// Check if we are editing an existing entry
$is_editing = isset($_POST['edit_id']) && is_numeric($_POST['edit_id']) && $_POST['edit_id'] > 0;
if ($is_editing) {
$edit_id = intval($_POST['edit_id']);
$updated = db_update($mysqli, $tableTurnerinnen, $data_to_insert, ['id' => $edit_id]);
if ($updated === false) {
$form_message = 'Fehler beim Aktualisieren des Eintrags.';
} else if ($updated === 0) {
$form_message = 'Keine Änderungen vorgenommen.';
} else {
$_SESSION['form_message'] = 'Eintrag erfolgreich aktualisiert!';
$_POST = [];
$parsed = parse_url($_SERVER['REQUEST_URI']);
if (!isset($parsed['query'])) {
return $url;
}
parse_str($parsed['query'], $query);
unset($query[$param]); // remove the parameter
$base = $parsed['path'] ?? '';
$new_query = http_build_query($query);
$url = $new_query ? $base . '?' . $new_query : $base;
header("Location: ". $url);
exit;
}
}
}
}
if ((isset($_POST['prev_abt'])) && !empty($_POST['prev_abt_submit'])) {
verify_csrf();
$value = $aktabt;
if ($value > 1){
$value -= 1;
@@ -285,10 +19,11 @@ if ((isset($_POST['prev_abt'])) && !empty($_POST['prev_abt_submit'])) {
$stmt->close();
}
header("Location: /intern/kampfrichter");
exit;
exit;
}
if ((isset($_POST['next_abt'])) && !empty($_POST['next_abt_submit'])) {
verify_csrf();
$value = $aktabt;
$maxvalue = db_get_var($mysqli, "SELECT name FROM $tableAbt ORDER BY name DESC LIMIT 1");
@@ -322,6 +57,7 @@ if ($_SESSION['last_abt'] !== $aktabt){
}
if ((isset($_POST['prev_subabt'])) && !empty($_POST['prev_subabt_submit'])) {
verify_csrf();
$value = $_SESSION['currentsubabt'];
if ($value > 1){
$_SESSION['currentsubabt']--;
@@ -333,6 +69,7 @@ if ((isset($_POST['prev_subabt'])) && !empty($_POST['prev_subabt_submit'])) {
}
if ((isset($_POST['next_subabt'])) && !empty($_POST['next_subabt_submit'])) {
verify_csrf();
$value = $_SESSION['currentsubabt'];
if ($value < $maxsubabt){
$_SESSION['currentsubabt']++;
@@ -343,7 +80,8 @@ if ((isset($_POST['next_subabt'])) && !empty($_POST['next_subabt_submit'])) {
exit;
}
if ( isset($_POST['togle_advanced_mode_admin']) && !empty($_POST['togle_advanced_mode_admin_submit']) ) {
if ( isset($_POST['togle_advanced_mode_admin']) && !empty($_POST['togle_advanced_mode_admin_submit']) && !empty($_POST['csrf_token'])) {
verify_csrf();
$current_value = $focus_view_admin;
$new_value = !$current_value;
@@ -351,31 +89,4 @@ if ( isset($_POST['togle_advanced_mode_admin']) && !empty($_POST['togle_advanced
header("Location: /intern/kampfrichter");
exit;
}
if ((isset($_POST['upload_remove_pdf_for_programm'])) && !empty($_POST['programm_remove_export'])) {
$current_year = date('Y');
$monat = date('n');
if ($monat > 6) $current_year++;
$programm = trim($_POST['programm_remove_export']);
$dir = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/ergebnisse';
if (!file_exists($dir)) {
mkdir($dir, 0755, true);
}
$localPath = $_SERVER['DOCUMENT_ROOT'] . "/wp-content/ergebnisse/KTBB_Ergebnisse_" . $programm . "_" . $current_year . ".pdf";
// --- ADDED CODE START ---
// Check if the file already exists and delete it
if (file_exists($localPath)) {
unlink($localPath);
}
// --- ADDED CODE END ---
$_SESSION['form_message'] = 'PDF wurde gelöscht';
header("Location: ". $_SERVER['REQUEST_URI']);
}

View File

@@ -1,8 +1,8 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
require_once __DIR__ . '/../session_functions.php';
ini_wkvs_session();
if (!isset($error)) {
$error = '';
@@ -24,8 +24,6 @@ if ($_SESSION['lockout_time_'. $logintype] > time()) {
$error = "Zu viele fehlgeschlagene Anmeldeversuche. Bitte warte $minutes Minute(n).";
} elseif (isset($_POST[$logintype.'_login_submit'])) {
$token = "QQa2UMbEYW8oOL7wz9DjtqECVCikSZsDuSdmzxiadEXFsKyujEUyQOW1AYMD2OqU8VXxClIRweRuWLzvBrZpPYL41e89Rs96tM7Lq1KpjA5E2mg2UfgvztheGRV";
require __DIR__ .'/../db/db-verbindung-script-guest.php';
require __DIR__ . "/../db/db-tables.php";
@@ -35,8 +33,9 @@ if ($_SESSION['lockout_time_'. $logintype] > time()) {
$password = trim($_POST['access_passcode']);
// Prepare statement
$stmt = $guest->prepare("SELECT * FROM $tableInternUsers WHERE username = ? LIMIT 1");
$stmt->bind_param("s", $username);
$stmt = $guest->prepare("SELECT * FROM $tableInternUsers WHERE username = ? AND login_active = ? LIMIT 1");
$loginActive = 1;
$stmt->bind_param("ss", $username, $loginActive);
$stmt->execute();
$result = $stmt->get_result();
$user = $result->fetch_assoc();
@@ -60,7 +59,7 @@ if ($_SESSION['lockout_time_'. $logintype] > time()) {
if (password_verify($password, $user['password_hash']) && in_array($logintype, $freigabe_values)) {
foreach ($freigabe_values as $freigabe) {
$_SESSION['access_granted_'. $freigabe] = true;
$_SESSION['passcode'. $freigabe .'_id'] = $user['id'];
$_SESSION['user_id_'. $freigabe] = $user['id'];
$_SESSION['lockout_time_'. $freigabe] = 0;
$_SESSION['login_attempts_'. $freigabe] = 0;
}

View File

@@ -0,0 +1,104 @@
<?php
function deleteSession() {
$_SESSION = array();
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
session_destroy();
}
function ini_wkvs_session(bool $set_csrf = false, bool $regenerate = false) {
if (session_status() === PHP_SESSION_NONE) {
session_name('wkvs_cookie');
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'domain' => '',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
session_start();
}
if ($regenerate) {
session_regenerate_id(true);
}
if ($set_csrf && !isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(64));
}
}
function verify_csrf() {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$token = $_POST['csrf_token'] ?? '';
if (!hash_equals($_SESSION['csrf_token'], $token)) {
http_response_code(403);
die("Access Denied: Invalid CSRF Token.");
}
} else {
http_response_code(403);
die("Access Denied: Invalid Request Type.");
}
}
$allowedUserTypes = ['trainer', 'kampfrichter', 'wk_leitung'];
function check_user_permission(string $type, bool $return = false) {
global $allowedUserTypes;
if (!in_array($type, $allowedUserTypes, true)) {
if ($return) {
return false;
} else {
http_response_code(403);
die("Invalid User Type Configuration");
}
}
$accessKey = "access_granted_{$type}";
$idKey = "user_id_{$type}";
$hasAccess = ($_SESSION[$accessKey] ?? false) === true;
$hasValidId = isset($_SESSION[$idKey]) && intval($_SESSION[$idKey]) > 0;
if (!$hasAccess || !$hasValidId) {
if ($return) {
return false;
} else {
http_response_code(403);
die("Access Denied");
}
}
if ($return) {
return true;
}
}
function check_multiple_allowed_permissions(array $types) {
$authorized = false;
foreach ($types as $type) {
if (check_user_permission($type, true)) {
$authorized = true;
break;
}
}
if (!$authorized) {
http_response_code(403);
die("Access Denied");
}
}

View File

@@ -13,9 +13,14 @@ use ChrisKonnertz\StringCalc\StringCalc;
class NotenRechner {
private $Rfunctions = ["MAXR", "MINR", "AVGR", "SUMR"];
private $RfunctionsSan = [];
public function __construct(
private StringCalc $rechner = new StringCalc()
) {}
) {
$this->RfunctionsSan = implode('|', array_map('preg_quote', $this->Rfunctions));
}
/*
Es wird ein Array mit allen Notentypen pro Gerät, Jahr und Person erwartet, so dass noten_bezeichnung_id als Key verwendet werden kann:
@@ -95,7 +100,7 @@ class NotenRechner {
}
}
private function insertValuesComplex(string $schemaRaw, array $valuesArray, int $currentId)
private function insertValuesComplex(string $schemaRaw, array $valuesArray, int $currentId, int $runNumber)
{
$schema = $this->santinzeString($schemaRaw);
$idsNeededArray = $this->getBenoetigteIdsComplex($schemaRaw);
@@ -104,7 +109,6 @@ class NotenRechner {
foreach ($idsNeededArray as $sina) {
$noteId = $sina['noteId'];
$geraetIdSearch = ($sina['geraetId'] === 'A') ? $currentId : $sina['geraetId'];
$runNumber = $sina['run'] ?? 1;
if (!isset($valuesArray[$geraetIdSearch][$noteId][$runNumber])) {
return ['success' => false, 'value' => "Fehlende Daten für Gerät $geraetIdSearch, Note $noteId, Lauf $runNumber"];
@@ -112,15 +116,13 @@ class NotenRechner {
}
try {
$returnStr = preg_replace_callback('/\{(\d+)(?:\[(\w*)\])?(?:\[(\d+)\])?\}/', function($m) use ($valuesArray, $currentId) {
$returnStr = preg_replace_callback('/\{(\d+)(?:\[(\w*)\])?(?:\[(\d+)\])?\}/', function($m) use ($valuesArray, $currentId, $runNumber) {
$noteId = $m[1];
// Get value inside brackets, default to 'S' if none exists
$rawGeraet = $m[2] ?? 'S';
$geraetId = ($rawGeraet === 'S' || $rawGeraet === '') ? $currentId : $rawGeraet;
$runNumber = isset($m[3]) ? (int)$m[3] : 1;
// Return value from [Device][Note][Run]
return $valuesArray[$geraetId][$noteId][$runNumber] ?? 0;
@@ -160,16 +162,120 @@ class NotenRechner {
return $this->calculate($rechnungArray['value']);
}
public function berechneStringComplex(string $schemaRaw, array $valuesArray = [], int $geraetId = 0) {
public function berechneStringComplex(string $schemaRaw, array $valuesArray = [], int $geraetId = 0, int $run_number = 0) {
if ($schemaRaw === '') { return ['success' => false, 'value' => 'Leeres Schema']; }
if ($geraetId === 0) { return ['success' => false, 'value' => 'Keine Geraet Id angegeben.']; }
if ($run_number === 0) { return ['success' => false, 'value' => 'Keine Run_Number angegeben.']; }
$rechnungArray = $this->insertValuesComplex($schemaRaw, $valuesArray, $geraetId);
$rechnungArray = $this->insertValuesComplex($schemaRaw, $valuesArray, $geraetId, $run_number);
if (!isset($rechnungArray['success']) || !isset($rechnungArray['value']) || !$rechnungArray['success']) {
return ['success' => false, 'value' => $rechnungArray['value'] ?? 'Fehler beim Einsetzen der Werte oder Werte fehlen'];
return ['success' => false, 'value' => $rechnungArray['value'] . " RECHNUNG: " . $schemaRaw ?? 'Fehler beim Einsetzen der Werte oder Werte fehlen'];
}
return $this->calculate($rechnungArray['value']);
}
public function berechneStringComplexRun(string $schemaRaw, array $valuesArray = [], int $geraetId = 0, int $programm = 0, array $arrayRuns = []) {
if ($schemaRaw === '') { return ['success' => false, 'value' => 'Leeres Schema']; }
if ($geraetId === 0) { return ['success' => false, 'value' => 'Keine Geraet Id angegeben.']; }
if ($programm === 0) { return ['success' => false, 'value' => 'Kein Programm angegeben.']; }
if ($arrayRuns === []) { return ['success' => false, 'value' => 'Leeres Array Runs Noten.']; }
$rechnung = $this->insertRunValues($schemaRaw, $valuesArray, $geraetId, $programm, $arrayRuns);
if (!isset($rechnung) || $rechnung === '') {
return ['success' => false, 'value' => 'Fehler beim Einsetzen der Werte oder Werte fehlen'];
}
return $this->calculate($rechnung);
}
private function insertRunValues($schema, $valuesArray, $currentId, $programm, $arrayRuns) {
$pattern = '/(?P<fn_name>' . $this->RfunctionsSan . ')\((?P<content>(?:(?R)|[^()])*)\)/';
return preg_replace_callback($pattern, function($m) use ($valuesArray, $currentId, $programm, $arrayRuns) {
$name = $m['fn_name'];
$content = $m['content'];
// Resolve inner nested functions first
$content = $this->insertRunValues($content, $valuesArray, $currentId, $programm, $arrayRuns);
if (!in_array($name, $this->Rfunctions)) {
return $m[0];
}
$parts = [];
$ids = $this->getBenoetigteIdsComplex($content);
$runCount = 0;
foreach ($ids as $sid) {
$geraetId = ($sid['geraetId'] === 'A') ? $currentId : $sid['geraetId'];
$runCountN = $arrayRuns[$sid['noteId']][$geraetId][$programm] ?? $arrayRuns["default"] ?? 1;
//var_dump($arrayRuns[$sid['noteId']][$geraetId][$programm]);
if ($runCount !== $runCountN && $runCount !== 0) { return; }
$runCount = $runCountN;
}
$string = "";
switch ($name) {
case "AVGR":
case "SUMR":
for ($r = 1; $r <= $runCount; $r++) {
$res = $this->insertValuesComplex($content, $valuesArray, $currentId, $r);
// FIXED: Only bail if success is false
if (!$res['success']) {
return "0"; // Or handle error as needed
}
$parts[] = "(" . $res['value'] . ")";
}
$innerMath = implode(" + ", $parts);
$string = ($name === "AVGR") ? "(($innerMath) / $runCount)" : "($innerMath)";
//var_dump($string);
break;
case "MAXR":
case "MINR":
$arrayRunValues = [];
for ($r = 1; $r <= $runCount; $r++) {
$res = $this->berechneStringComplex($content, $valuesArray, $currentId, $r);
// FIXED: Access the ['value'] key of the returned array
if ($res['success']) {
$arrayRunValues[] = floatval($res['value']);
} else {
$arrayRunValues[] = 0;
}
}
// Safety check for empty arrays to prevent max() errors
if (empty($arrayRunValues)) return "0";
$string = ($name === "MAXR") ? max($arrayRunValues) : min($arrayRunValues);
break;
}
return (string)$string;
}, $schema);
}
public function checkRunFunctions(string $schemaRaw) {
if ($schemaRaw === '') {
return ['success' => false, 'value' => 'Leeres Schema'];
}
$schema = $this->santinzeString($schemaRaw);
$pattern = '/(?P<fn_name>' . $this->RfunctionsSan . ')\((?:(?R)|[^()])*+\)/';
return (bool) preg_match($pattern, $schema);
}
}

View File

@@ -1,16 +1,12 @@
<?php
require $baseDir . '/../composer/vendor/autoload.php';
use Shuchkin\SimpleXLSX;
if (isset($_POST['apply_bulk_action']) ) {
if (!verify_csrf()) {
$_SESSION['form_message'] = 'Sicherheitsüberprüfung fehlgeschlagen.';
$_SESSION['form_message_type'] = 0;
} elseif ( empty($_POST['turnerin_ids']) || !is_array($_POST['turnerin_ids']) ) {
verify_csrf();
if ( empty($_POST['turnerin_ids']) || !is_array($_POST['turnerin_ids']) ) {
$_SESSION['form_message'] = 'Keine Turnerinnen für die Aktion ausgewählt.';
$_SESSION['form_message_type'] = 0;
} elseif (!isset($_POST['bulk_action_programm']) && !isset($_POST['bulk_action_bezahlt'])) {
@@ -93,7 +89,8 @@ if (isset($_POST['apply_bulk_action']) ) {
exit;
}
if (isset($_POST['delete_id']) && verify_csrf()) {
if (isset($_POST['delete_id'])) {
verify_csrf();
$delete_id = intval($_POST['delete_id']);
$stmt = $mysqli->prepare("DELETE FROM $tableTurnerinnen where id = ?");
@@ -113,6 +110,7 @@ if (isset($_POST['delete_id']) && verify_csrf()) {
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['xlsx_file'])) {
verify_csrf();
if ($_FILES['xlsx_file']['error'] === UPLOAD_ERR_OK) {
@@ -240,54 +238,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['xlsx_file'])) {
}
if (!empty($_FILES['music_file']['name']) && isset($_POST['music_id'])) {
echo 'ja';
$edit_id = (int) $_POST['music_id'];
$uploadedFile = $_FILES['music_file'];
// Validate actual MIME type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $uploadedFile['tmp_name']);
finfo_close($finfo);
$allowedTypes = ['audio/mpeg', 'audio/wav', 'audio/ogg'];
if (!in_array($mimeType, $allowedTypes, true)) {
die('Invalid file type.');
}
// Fetch and remove old file
$stmt = $mysqli->prepare("SELECT bodenmusik FROM $tableTurnerinnen WHERE id = ?");
$stmt->bind_param("i", $edit_id);
$stmt->execute();
$stmt->bind_result($oldurl);
$stmt->fetch();
$stmt->close();
if (!empty($oldurl) && is_file($oldurl)) unlink($oldurl);
// Ensure upload directory exists
$uploadDir = $baseDir . '/wk-musik-boden/';
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
// Clean file name
$cleanName = preg_replace("/[^a-zA-Z0-9-_\.]/", "_", $uploadedFile['name']);
$filename = uniqid('music_', true) . '_' . $cleanName;
$targetPath = $uploadDir . $filename;
if (move_uploaded_file($uploadedFile['tmp_name'], $targetPath)) {
$stmt = $mysqli->prepare("UPDATE $tableTurnerinnen SET bodenmusik = ? WHERE id = ?");
$stmt->bind_param("si", $targetPath, $edit_id);
if (!$stmt->execute()) echo 'DB error: ' . $stmt->error;
$stmt->close();
} else {
die('Failed to move uploaded file.');
}
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
$edit_row = null;
if ($access_granted_trainer && isset($_GET['edit_id']) && is_numeric($_GET['edit_id']) && !isset($_POST['submit_turnerinnen_form'])) {
$edit_id = intval($_GET['edit_id']);
@@ -319,121 +269,117 @@ if ($access_granted_trainer && isset($_GET['edit_id']) && is_numeric($_GET['edit
// === INSERT/UPDATE Handler ===
if ( $access_granted_trainer && isset($_POST['submit_turnerinnen_form']) ) {
// Check nonce
if ( !verify_csrf() ) {
$_SESSION['form_message'] = 'Sicherheitsproblem: Ungültige Formularübermittlung.';
verify_csrf();
$name = htmlspecialchars( $_POST['nachname'] );
$vorname = htmlspecialchars( $_POST['vorname'] );
$geburtsdatum = trim($_POST['geburtsdatum'] );
$programm = htmlspecialchars( $_POST['programm'] );
if ($selectedverein !== 'admin'){
$verein = $selectedverein;
} else {$verein = htmlspecialchars( $_POST['verein'] ); $bezahlt = htmlspecialchars( $_POST['bezahlt'] ); }
if ( empty($name) || empty($vorname) || empty($geburtsdatum) || empty($programm)) {
$_SESSION['form_message'] = 'Bitte füllen Sie alle erforderlichen Felder aus.';
$_SESSION['form_message_type'] = 0;
} else {
$name = htmlspecialchars( $_POST['nachname'] );
$vorname = htmlspecialchars( $_POST['vorname'] );
$geburtsdatum = trim($_POST['geburtsdatum'] );
$programm = htmlspecialchars( $_POST['programm'] );
if ($selectedverein !== 'admin'){
$verein = $selectedverein;
} else {$verein = htmlspecialchars( $_POST['verein'] ); $bezahlt = htmlspecialchars( $_POST['bezahlt'] ); }
if ( empty($name) || empty($vorname) || empty($geburtsdatum) || empty($programm)) {
$_SESSION['form_message'] = 'Bitte füllen Sie alle erforderlichen Felder aus.';
$_SESSION['form_message_type'] = 0;
$data_to_insert = [];
$data_to_insert = array(
'name' => $name,
'vorname' => $vorname,
'geburtsdatum' => $geburtsdatum,
'programm' => $programm,
'verein' => $verein,
);
$data_formats = array('%s', '%s', '%s', '%s', '%s');
if ($selectedverein === 'admin') {
$data_to_insert['bezahltoverride'] = $bezahlt;
$data_formats[] = '%d';
}
print_r($data_to_insert);
// Check if we are editing an existing entry
$is_editing = isset($_POST['edit_id']) && is_numeric($_POST['edit_id']) && $_POST['edit_id'] > 0;
if ($is_editing) {
$edit_id = intval($_POST['edit_id']);
$entries = db_select($mysqli, $tableTurnerinnen, '*', 'id = ?', [$edit_id], 'rang ASC');
$entry = $entries[0]; // since you're fetching by ID, this should return exactly one row
$columns = array_keys($data_to_insert);
$set = implode(
', ',
array_map(fn($col) => "$col = ?", $columns)
);
$sql = "UPDATE $tableTurnerinnen SET $set WHERE id = ?";
var_dump($sql);
$stmt = $mysqli->prepare($sql);
$types = str_repeat('s', count($data_to_insert)) . 'i';
$values = array_values($data_to_insert);
$values[] = $edit_id;
$stmt->bind_param($types, ...$values);
$updated = $stmt->execute();
$stmt->close();
if ($updated === false) {
error_log('DB Update Error: ' . $wpdb->last_error);
$_SESSION['form_message'] = 'Fehler beim Aktualisieren des Eintrags.';
$_SESSION['form_message_type'] = 0;
} else if ($updated === 0) {
$_SESSION['form_message'] = 'Keine Änderungen vorgenommen.';
$_SESSION['form_message_type'] = 0;
} else {
$_SESSION['form_message'] = 'Eintrag erfolgreich aktualisiert!';
$_SESSION['form_message_type'] = 1;
$_POST = [];
header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
exit;
}
} else {
$data_to_insert = [];
$data_to_insert = array(
'name' => $name,
'vorname' => $vorname,
'geburtsdatum' => $geburtsdatum,
'programm' => $programm,
'verein' => $verein,
$columns = array_keys($data_to_insert);
$set = implode(
', ',
array_map(fn($col) => "$col = ?", $columns)
);
$data_formats = array('%s', '%s', '%s', '%s', '%s');
$sql = "INSERT INTO $tableTurnerinnen SET $set";
if ($selectedverein === 'admin') {
$data_to_insert['bezahltoverride'] = $bezahlt;
$data_formats[] = '%d';
}
$stmt = $mysqli->prepare($sql);
print_r($data_to_insert);
$types = str_repeat('s', count($data_to_insert));
$values = array_values($data_to_insert);
$stmt->bind_param($types, ...$values);
$inserted = $stmt->execute();
$stmt->close();
// Check if we are editing an existing entry
$is_editing = isset($_POST['edit_id']) && is_numeric($_POST['edit_id']) && $_POST['edit_id'] > 0;
if ($is_editing) {
$edit_id = intval($_POST['edit_id']);
$entries = db_select($mysqli, $tableTurnerinnen, '*', 'id = ?', [$edit_id], 'rang ASC');
$entry = $entries[0]; // since you're fetching by ID, this should return exactly one row
$columns = array_keys($data_to_insert);
$set = implode(
', ',
array_map(fn($col) => "$col = ?", $columns)
);
$sql = "UPDATE $tableTurnerinnen SET $set WHERE id = ?";
var_dump($sql);
$stmt = $mysqli->prepare($sql);
$types = str_repeat('s', count($data_to_insert)) . 'i';
$values = array_values($data_to_insert);
$values[] = $edit_id;
$stmt->bind_param($types, ...$values);
$updated = $stmt->execute();
$stmt->close();
if ($updated === false) {
error_log('DB Update Error: ' . $wpdb->last_error);
$_SESSION['form_message'] = 'Fehler beim Aktualisieren des Eintrags.';
$_SESSION['form_message_type'] = 0;
} else if ($updated === 0) {
$_SESSION['form_message'] = 'Keine Änderungen vorgenommen.';
$_SESSION['form_message_type'] = 0;
} else {
$_SESSION['form_message'] = 'Eintrag erfolgreich aktualisiert!';
$_SESSION['form_message_type'] = 1;
$_POST = [];
header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
exit;
}
if ( $inserted ) {
$_SESSION['form_message'] = 'Daten erfolgreich gespeichert!';
$_SESSION['form_message_type'] = 1;
header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
exit;
} else {
$columns = array_keys($data_to_insert);
$set = implode(
', ',
array_map(fn($col) => "$col = ?", $columns)
);
$sql = "INSERT INTO $tableTurnerinnen SET $set";
$stmt = $mysqli->prepare($sql);
$types = str_repeat('s', count($data_to_insert));
$values = array_values($data_to_insert);
$stmt->bind_param($types, ...$values);
$inserted = $stmt->execute();
$stmt->close();
if ( $inserted ) {
$_SESSION['form_message'] = 'Daten erfolgreich gespeichert!';
$_SESSION['form_message_type'] = 1;
header('Location: ' . strtok($_SERVER['REQUEST_URI'], '?'));
exit;
} else {
$_SESSION['form_message'] = 'Fehler beim Speichern der Daten. Bitte versuchen Sie es später erneut.';
$_SESSION['form_message_type'] = 0;
}
$_SESSION['form_message'] = 'Fehler beim Speichern der Daten. Bitte versuchen Sie es später erneut.';
$_SESSION['form_message_type'] = 0;
}
}
}

View File

@@ -7,8 +7,6 @@ $lastSegment = strtolower($_GET['geraet']) ?? '';
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$token = "QQa2UMbEYW8oOL7wz9DjtqECVCikSZsDuSdmzxiadEXFsKyujEUyQOW1AYMD2OqU8VXxClIRweRuWLzvBrZpPYL41e89Rs96tM7Lq1KpjA5E2mg2UfgvztheGRV";
require_once $baseDir . '/../scripts/db/db-verbindung-script-guest.php';
require_once $baseDir . '/../scripts/db/db-functions.php';
require_once $baseDir . '/../scripts/db/db-tables.php';

View File

@@ -1,16 +1,18 @@
:root {
--paddingSite: 40px;
--card-radius: 20px;
--card-radius: 24px;
--card-bg: #ffffff;
--bg: #FDFDFD;
--card-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
--accent: #2d73ac;
--bg: #F4F3EF;
--card-shadow: 0 12px 40px rgba(0, 0, 0, 0.04);
--accent: #FF5A5F;
/* Soft energetic pink/red from Dribbble */
--accent-secondary: #FF8A65;
--bg-top: rgb(54, 137, 13);
--bg-top-raw: 54 137 13;
--accent-soft: #f0f5ff;
--border-subtle: #d4d7e1;
--text-main: #191919;
--text-muted: #5e5e5e;
--border-subtle: #eaeaea;
--text-main: #1b1b1b;
--text-muted: #8A8A8A;
--disabled-bg: #f3f4f6;
--disabled-border: #cbd5f5;
}
@@ -21,15 +23,6 @@
*::after,
*::before {
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
font-family: "Google Sans Flex", sans-serif;
font-optical-sizing: auto;
font-style: normal;
font-variation-settings:
"slnt" 0,
"wdth" 100,
"GRAD" 0,
"ROND" 0;
}
html,
@@ -43,6 +36,7 @@ body {
margin: 0;
width: 100vw;
background: var(--bg);
overflow-x: hidden;
}
::selection {
@@ -80,7 +74,7 @@ input {
background: none;
}
@media (min-width: 1000px) {
@media (min-width: 1081px) {
.bgSection.open {
width: calc(100vw - 380px);
/* - 2 * var(--paddingSite) */
@@ -91,20 +85,44 @@ input {
.headerDivTrainer {
padding: var(--paddingSite);
background-color: var(--bg-top);
margin-bottom: var(--paddingSite);
padding-bottom: 10px;
background: transparent;
margin-bottom: 20px;
position: relative;
z-index: 3;
}
.dashboardGrid {
padding: 0 var(--paddingSite) var(--paddingSite);
display: grid;
grid-template-columns: 1fr;
gap: 30px;
align-items: start;
width: 100%;
}
.twoColumDiv {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
align-items: start;
width: 100%;
}
@media (max-width: 1080px) {
.twoColumDiv {
grid-template-columns: 1fr;
}
}
/* headings */
.containerHeading {
margin-top: 0;
font-weight: 400;
margin-bottom: 20px;
font-weight: 600;
font-size: 20px;
margin-bottom: 24px;
color: var(--text-main);
}
.divLiveSyncronisation {
@@ -156,13 +174,15 @@ input {
}
.headingPanelDiv>* {
color: var(--bg);
color: var(--text-main);
}
.headingPanel {
margin-top: 0;
margin-bottom: 10px;
font-weight: 200;
font-size: 38px;
font-weight: 700;
letter-spacing: -0.02em;
}
.headingPanelUser {
@@ -227,18 +247,21 @@ table {
}
.wkvsTabelle th {
color: #424242;
border-bottom: solid 1px #0000007d;
color: var(--text-muted);
border-bottom: solid 1px var(--border-subtle);
font-weight: 600;
padding: 14px 15px;
font-size: 16px;
padding: 16px 15px;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 0.05em;
background: transparent;
}
.wkvsTabelle td {
background-color: #ffffff;
color: #191919;
font-weight: 400;
padding: 14px 15px;
background-color: transparent;
color: var(--text-main);
font-weight: 500;
padding: 16px 15px;
background: none;
text-align: center;
}
@@ -248,7 +271,11 @@ table {
}
.wkvsTabelle td:not(.totalTd, .totalValue) {
border-bottom: solid 1px #6262624d;
border-bottom: solid 1px var(--border-subtle);
}
.wkvsTabelle tr:last-child td {
border-bottom: none;
}
/*.wkvsTabelle .totalValue {
@@ -290,14 +317,20 @@ table {
/* Panel with inputs (new style, light) */
.containerDiv {
background: var(--card-bg);
border-radius: var(--card-radius);
padding: 32px;
box-shadow: var(--card-shadow);
color: var(--text-main);
display: flex;
flex-direction: column;
min-width: 0;
/* Critical for grid item content overflow */
}
.settingsGrid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
grid-template-columns: 1fr;
gap: 20px;
margin-bottom: 30px;
}
@@ -309,38 +342,100 @@ table {
}
.settingsRow span {
font-size: 13px;
font-size: 16px;
color: var(--text-muted);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
font-weight: 500;
margin-bottom: 2px;
}
.settingsRow input {
padding: 10px 14px;
border: 1px solid var(--border-subtle);
border-radius: 10px;
.settingsRow input,
.settingsRow select {
padding: 14px 18px;
border: none;
background: #F8F9FA;
border-radius: 12px;
font-size: 15px;
transition: all 0.2s ease;
background: #ffffff;
color: var(--text-main);
width: 100%;
}
.settingsRow input:hover {
border-color: #adb5bd;
.settingsRow input:hover,
.settingsRow select:hover {
background: #F1F3F5;
}
.settingsRow input:focus {
border-color: var(--bg-top);
.settingsRow input:focus,
.settingsRow select:focus {
background: #FFFFFF;
box-shadow: 0 0 0 4px rgba(var(--bg-top-raw), 0.1);
outline: none;
}
.settingsRow input[type="color"] {
height: 42px;
padding: 4px;
height: 48px;
padding: 0px;
cursor: pointer;
border-radius: 10px;
border-radius: 12px;
border: 1px solid #cacaca;
-webkit-appearance: none;
appearance: none;
/* Removes default Chrome/Safari styles */
cursor: pointer;
background: none;
}
/* Container for the color swatch (Chrome/Safari) */
input[type="color"]::-webkit-color-swatch-wrapper {
padding: 0;
}
/* The actual color area (Chrome/Safari) */
input[type="color"]::-webkit-color-swatch {
border: none;
/* Makes the picker a circle */
}
/* The actual color area (Firefox) */
input[type="color"]::-moz-color-swatch {
border: none;
}
.containerImages {
display: flex;
flex-direction: column;
gap: 15px;
}
.containerImages span {
position: absolute;
bottom: 4px;
padding: 12px;
width: 100%;
text-align: center;
background-color: #00000063;
backdrop-filter: blur(2px);
border-radius: 0 0 7px 7px;
border-top: 1px solid #fff;
color: #fff;
}
.containerImages>div {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.containerImages>div:last-child {
border-bottom: none;
}
.containerImages img {
width: 100%;
border-radius: 8px;
object-fit: cover;
}
.editContainerDivInner>form {
@@ -593,16 +688,19 @@ input[type="number"]::-webkit-outer-spin-button {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
width: 44px;
height: 44px;
background: #FFFFFF;
border-radius: 50%;
cursor: pointer;
z-index: 99;
color: var(--bg);
color: var(--text-main);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
}
.trainerBurgerMenuDiv svg {
width: 100%;
height: 100%;
width: 24px;
height: 24px;
stroke: currentColor;
transition: transform 0.3s ease;
}
@@ -975,8 +1073,8 @@ tr.rowStartgebuer::after {
}
.containerImages {
display: flex;
flex-wrap: wrap;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
align-items: flex-start;
gap: 24px;
}
@@ -984,11 +1082,9 @@ tr.rowStartgebuer::after {
.containerImages div {
display: flex;
flex-direction: column;
padding: 16px;
border-radius: 16px;
border: 1px solid #1f1f1f;
gap: 8px;
align-items: flex-start;
position: relative;
}
.containerImages div input {
@@ -996,15 +1092,15 @@ tr.rowStartgebuer::after {
}
.containerImages div img {
max-height: 200px;
max-width: 200px;
object-fit: contain;
border-radius: 6px;
border: 1px solid var(--bg-top);
border: 1px solid #000000;
}
div.tableWraperOverflowY {
width: 100%;
overflow-x: auto;
display: block;
/* Prevent scroll chaining to body */
overscroll-behavior-x: contain;
@@ -1039,4 +1135,42 @@ select {
select:open {
background-image: url("data:image/svg+xml;utf8,\<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'>\<path d='M18 15L12 9L6 15' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/>\</svg>");
}
.firstDiv {
background: #ff9cde;
background: linear-gradient(151deg, rgba(255, 156, 222, 1) 0%, rgb(255 110 110) 50%, rgba(255, 182, 130, 1) 100%);
}
.firstDiv span {
color: #fff1fa !important;
}
.firstDiv h3 {
color: #ffffff !important;
}
.secondDiv {
background: #e0f7ff;
background: linear-gradient(150deg,rgba(224, 247, 255, 1) 0%, rgba(158, 226, 255, 1) 50%, rgba(182, 207, 252, 1) 100%);
}
.secondDiv span {
color: #171797 !important;
}
.secondDiv h3 {
color: #0f0f61 !important;
}
.settingsRowGroup {
display: grid;
gap: 18px;
}
span.light {
font-weight: 300;
}
.tableNoten input {
width: fit-content !important;
}

View File

@@ -444,6 +444,7 @@ input[type="number"]::-webkit-outer-spin-button {
display: inline-flex;
align-items: center;
justify-content: center;
align-self: baseline;
}
/* Variants */
@@ -460,13 +461,14 @@ input[type="number"]::-webkit-outer-spin-button {
color: #781467;
}
.submit-display-start,
.submit-display-start.start,
.submit-musik-start {
background: #ecfdf3;
color: #15803d;
border: 1px solid #4ade80;
}
.submit-display-start.stopp,
.submit-musik-stopp {
background: #fef2f2;
color: #b91c1c;
@@ -921,7 +923,27 @@ table.widefat {
justify-content: space-around;
}
.editUserButtons {
display: flex;
}
.div-submit-display-result, .div-submit-display-start {
display: flex;
flex-direction: column;
}
.allNotentable {
display: flex;
flex-direction: row;
gap: 3rem;
}
.singleNotentable {
display: flex;
flex-direction: column;
gap: 1rem;
}
select {
appearance: none;

View File

@@ -32,6 +32,10 @@
"ROND" 0;
}
.hidden {
display: none !important;
}
html,
body,
section {
@@ -121,6 +125,7 @@ input {
font-size: 0.95rem;
font-weight: 500;
cursor: pointer;
height: 39px;
transition: all 0.25s ease;
}
@@ -155,7 +160,8 @@ h3.benutzer {
/* ── User / Verein card ───────────────────────────────── */
.single_pwedit {
.single_pwedit,
.newUserLink {
background: var(--card-bg);
border-radius: var(--card-radius);
box-shadow: var(--card-shadow);
@@ -163,24 +169,28 @@ h3.benutzer {
transition: box-shadow 0.25s ease;
}
.single_pwedit:hover {
.single_pwedit:hover,
.newUserLink:hover {
box-shadow: 0 14px 40px rgba(15, 23, 42, 0.12);
}
.single_pwedit.verein {
.single_pwedit.verein,
.newUserLink.verein {
border-left: 4px solid var(--bg-top);
}
/* ── Form fields inside user card ─────────────────────── */
.single_pwedit form {
.single_pwedit form,
.newUserLink form {
display: flex;
flex-wrap: wrap;
gap: 14px 24px;
align-items: flex-end;
}
.single_pwedit label {
.single_pwedit label,
.newUserLink label {
display: block;
font-size: 0.8rem;
font-weight: 500;
@@ -190,12 +200,14 @@ h3.benutzer {
margin-bottom: 5px;
}
.single_pwedit .field-group {
.single_pwedit .field-group,
.newUserLink .field-group {
flex: 1 1 200px;
min-width: 0;
}
.single_pwedit input[type="text"] {
.single_pwedit input[type="text"],
.newUserLink input[type="text"] {
width: 100%;
padding: 9px 12px;
border: 1px dashed #999;
@@ -207,20 +219,23 @@ h3.benutzer {
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.single_pwedit input[type="text"]:focus {
.single_pwedit input[type="text"]:focus,
.newUserLink input[type="text"]:focus {
outline: none;
border: 1px solid var(--bg-top);
box-shadow: 0 0 0 3px rgba(var(--bg-top-raw) / 0.12);
}
.single_pwedit input[type="text"]::placeholder {
.single_pwedit input[type="text"]::placeholder,
.newUserLink input[type="text"]::placeholder {
color: #b0b0b0;
font-style: italic;
}
/* ── Buttons inside cards ─────────────────────────────── */
.single_pwedit button[type="submit"] {
.single_pwedit button[type="submit"],
.newUserLink button[type="submit"] {
appearance: none;
border: 1px solid #7777778e;
background: #7777778e;
@@ -234,7 +249,8 @@ h3.benutzer {
white-space: nowrap;
}
.single_pwedit button[type="submit"]:hover {
.single_pwedit button[type="submit"]:hover,
.newUserLink button[type="submit"]:hover {
background: var(--bg-top);
border-color: var(--bg-top);
color: #fff;
@@ -284,6 +300,26 @@ h3.benutzer {
color: var(--bg-top);
}
.bgNewUserLink {
position: fixed;
top: 0;
left: 0;
height: 100dvh;
width: 100dvw;
display: flex;
align-items: center;
justify-content: center;
background-color: #39393941;
backdrop-filter: blur(2px);
}
.newUserLink {
max-width: 600px;
max-height: 500px;
overflow-y: auto;
z-index: 9999;
}
/* ── Permission dropdown ──────────────────────────────── */
.perm-section {

120
www/intern/css/otl.css Normal file
View File

@@ -0,0 +1,120 @@
body{
overflow: hidden;
}
.page-secure-login{
display: flex;
}
.bg-picture-secure-login{
width: calc(100vw - 450px);
height: 100vh;
position: absolute;
left: 0px;
top: 0px;
}
.bg-picture-secure-login img{
width: 100%;
height: 100vh;
object-fit: cover;
}
.bg-secure-login{
display: flex;
width: 100vw;
max-width: 450px;
height: 100vh;
background-color: #fff;
position: absolute;
right: 0px;
top: 0px;
align-items: center;
padding: 30px;
}
.bg-secure-login-form > h1{
color: #000 !important;
font-size: 32px;
}
.bg-secure-login-form input[type=password], .bg-secure-login-form input[type=text]{
padding: 5px;
width: 100%;
max-width: 300px;
border-top: none !important;
border-left: none !important;
border-right: none !important;
font-size: 16px;
border-bottom: 1px solid #000 !important;
border-radius: 0px !important;
}
.divShowPw:not(#lastDivShowPw) {
margin-bottom: 20px;
}
.bg-secure-login-form input[type=password]:focus, .bg-secure-login-form input[type=text]:focus{
outline: none;
border-bottom: 1px solid #000 !important;
}
.bg-secure-login-form input[type=password]::placeholder, .bg-secure-login-form input[type=text]::placeholder {
color: #ccc !important;
}
.bg-secure-login-form input[type=submit]{
background-color: #fff !important;
padding: 10px 20px !important;
margin-top: 25px !important;
border: 1px solid #000 !important;
color: #000 !important;
transition: all 0.3s ease-out !important;
border-radius: 0px !important;
}
body {
color: #000 !important;
}
* {
box-sizing: border-box;
}
.bg-secure-login-form input[type=submit]:hover{
background-color: #000 !important;
color: #fff !important;
}
.bg-secure-login-form > p{
margin-bottom: 30px;
}
.seclog_home_link{
position: fixed;
z-index: 1000;
top: 30px;
right: 30px;
}
.divShowPw {
margin-top: 10px;
position: relative;
display: inline-block;
width: 100%;
max-width: 300px;
}
.togglePassword {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
cursor: pointer;
transition: all 0.5s ease;
}
.togglePassword:hover {
transform: translateY(-50%) scale(1.15);
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 1000px #ffffff inset !important;
box-shadow: 0 0 0 1000px #ffffff inset !important;
-webkit-text-fill-color: #000000 !important;
transition: background-color 5000s ease-in-out 0s;
}

View File

@@ -1,10 +1,13 @@
/* ─── Sidebar Navigation ─── */
:root {
--sidebar-width: 280px;
--sidebar-bg: #fafafa;
--sidebar-text: #363636;
--sidebar-hover: rgb(var(--bg-top-raw) / 0.2);
--sidebar-active: rgb(var(--bg-top-raw) / 0.35);
--sidebar-bg: #111218;
/* Dark navy / charcoal */
--sidebar-text: #A0A0A0;
/* Soft grey text */
--sidebar-hover: rgba(255, 255, 255, 0.05);
/* Subtile hover effect */
--sidebar-active: rgba(255, 255, 255, 0.1);
--sidebar-transition: 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
@@ -18,15 +21,16 @@
background: var(--sidebar-bg);
z-index: 10000;
transform: translateX(-100%);
transition: transform var(--sidebar-transition);
transition: transform var(--sidebar-transition), box-shadow var(--sidebar-transition);
display: flex;
flex-direction: column;
overflow-y: auto;
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.25);
box-shadow: none;
}
.sidebar-nav.open {
transform: translateX(0);
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.25);
}
/* Sidebar Header */
@@ -42,7 +46,7 @@
margin: 0;
font-size: 16px;
font-weight: 600;
color: #111;
color: #FFFFFF;
letter-spacing: 0.5px;
}
@@ -69,7 +73,7 @@
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1.2px;
color: rgba(45, 45, 45, 0.35);
color: rgba(255, 255, 255, 0.35);
}
/* Links */
@@ -95,13 +99,13 @@
.sidebar-links a:hover {
background: var(--sidebar-hover);
color: #222;
color: #FFFFFF;
}
.sidebar-links a.active {
background: var(--sidebar-active);
color: #111;
border-left-color: var(--bg-top);
color: #FFFFFF;
border-left-color: var(--accent);
}
.sidebar-links a svg {
@@ -134,18 +138,18 @@
/* Hamburger Toggle */
.sidebar-toggle {
background: var(--sidebar-bg);
background: #FFFFFF;
border: none;
border-radius: 10px;
width: 44px;
height: 44px;
border-radius: 50%;
width: 48px;
height: 48px;
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 5px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
transition: all var(--sidebar-transition);
padding: 0;
}
@@ -174,9 +178,9 @@
/* Footer */
.sidebar-footer {
padding: 16px 24px;
border-top: 1px solid rgba(42, 42, 42, 0.222);
border-top: 1px solid rgba(255, 255, 255, 0.08);
font-size: 11px;
color: rgba(42, 42, 42, 0.485);
color: rgba(255, 255, 255, 0.4);
}
.menuWrapper {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -54,8 +54,9 @@ function changeFreigabe(freigabe) {
const params = new URLSearchParams();
params.append('freigabe', freigabe);
params.append('type', siteType);
params.append('csrf_token', window.CSRF_TOKEN);
fetch('/intern/scripts/kampfrichter/ajax/ajax-update_selected_kampfrichter.php', {
fetch('/intern/scripts/ajax-update_selected_freigabe.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params

View File

@@ -53,11 +53,13 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
$reldirbase = "/../";
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
require_once $baseDir . '/../scripts/session_functions.php';
$access_granted_kampfrichter = $_SESSION['access_granted_kampfrichter'] ?? false;
ini_wkvs_session(true);
$csrf_token = $_SESSION['csrf_token'] ?? '';
$access_granted_kampfrichter = check_user_permission('kampfrichter', true) ?? false;
if (!$access_granted_kampfrichter) :
@@ -72,7 +74,6 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
require $baseDir . '/../scripts/websocket/ws-create-token.php';
@@ -106,7 +107,9 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
$sortprio = ['ep', 'p1', 'p1 kader', 'p2', 'p2 kader'];
$programmes = db_select($mysqli, $tableProgramme, 'programm', 'aktiv = ?', ['1']);
$programmes = db_select($mysqli, $tableProgramme, 'programm, `id`', 'aktiv = ?', ['1']);
$indexedProgrammes = array_column($programmes, 'id', 'programm');
$focus_view_admin = $_SESSION['abtViewAdmin'] ?? false;
$aktabtdb = db_get_var($mysqli, "SELECT value FROM $tableVar WHERE name = ?", ['wk_panel_current_abt']);
@@ -117,6 +120,8 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
$notenConfig = $res->fetch_all(MYSQLI_ASSOC);
$indexedNotenNames = array_column($notenConfig, 'name', 'id');
// var_dump($notenConfig);
//$dbprogramme = db_select($mysqli, $tableTurnerinnen, '*', 'abteilung = ? AND (bezahlt = ? OR bezahlt = ?)', [$aktabt, '2', '5'], 'id ASC');
@@ -223,26 +228,20 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
<div class="gruppennav">
<p>Aktuelle Abt. </p>
<form action="/intern/kampfrichter" method="post" >
<input type="hidden" name="csrf_token" id="prev_abt_nonce" value="<?= $csrf_token ?>">
<input type="hidden" name="prev_abt" value="-1">
<input type="submit" style="<?php echo $minstyle; ?>" name="prev_abt_submit" class="button_gruppe" value="<">
</form>
<p><?php echo $aktabt;?></p>
<form action="/intern/kampfrichter" method="post">
<input type="hidden" name="csrf_token" id="next_abt_nonce" value="<?= $csrf_token ?>">
<input type="hidden" name="next_abt" value="1">
<input type="submit" style="<?php echo $maxstyle; ?>" name="next_abt_submit" class="button_gruppe" value=">">
</form>
<p> / <?php echo $maxvalue; ?></p>
</div>
<?php
/*<form method="post" style="margin-bottom: 1em;">
<input type="hidden" name="csrf_token" id="toggle_advanced_mode_nonce" value="<?php echo csrf_token(); ?>">
<?php //wp_nonce_field('toggle_advanced_mode_action', 'toggle_advanced_mode_nonce'); ?>
<input type="hidden" name="togle_advanced_mode" value="-1">
<input class="buttonNewAdminStyle" type="submit" style="<?php echo $styletogglemode; ?>" name="togle_advanced_mode_submit" class="button button-secondary" value="<?php echo $valuetogglemode;?>">
</form>*/
} else {
<?php } else {
$aktsubabt = $_SESSION['currentsubabt'];
$maxstyle = ($aktsubabt == $maxsubabt) ? 'background-color: rgba(68, 68, 68, 0.27) !important; pointer-events:none !important;': '';
$minstyle = ($aktsubabt == 1) ? 'background-color: rgba(68, 68, 68, 0.27) !important; pointer-events:none !important;': '';
@@ -252,11 +251,13 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
echo '<p>Aktuelle Gruppe </p>';
?>
<form action="/intern/kampfrichter" method="post" >
<input type="hidden" name="csrf_token" id="prev_subabt_nonce" value="<?= $csrf_token ?>">
<input type="hidden" name="prev_subabt" value="-1">
<input type="submit" style="<?php echo $minstyle; ?>" name="prev_subabt_submit" class="button_gruppe" value="<">
</form>
<p><?php echo $aktsubabt;?></p>
<form action="/intern/kampfrichter" method="post">
<input type="hidden" name="csrf_token" id="next_subabt_nonce" value="<?= $csrf_token ?>">
<input type="hidden" name="next_subabt" value="1">
<input type="submit" style="<?php echo $maxstyle; ?>" name="next_subabt_submit" class="button_gruppe" value=">">
</form>
@@ -309,7 +310,7 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
}
}
$kampfrichter = db_select($mysqli, $tableInternUsers, 'id, username, freigabe', '', [], 'username ASC' );
$kampfrichter = db_select($mysqli, $tableInternUsers, 'id, name_person, freigabe', '', [], 'name_person ASC' );
$filteredKampfrichter = [];
@@ -340,11 +341,11 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
data-user="' . $selecteduser . '">';
echo '<option hidden selected>---</option>';
foreach ($filteredKampfrichter as $person) {
$selected = $selectedKampfrichter[$i] === $person['username']
$selected = $selectedKampfrichter[$i] === $person['name_person']
? 'selected'
: '';
echo '<option id="'.$selectedKampfrichter[$i].'" value="'.$person['username'].'" '.$selected.'>'.$person['username'].'</option>';
echo '<option id="'.$selectedKampfrichter[$i].'" value="'.$person['name_person'].'" '.$selected.'>'.$person['name_person'].'</option>';
}
echo '</select>';
@@ -356,13 +357,16 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
if ($selecteduser === 'admin'){
$valuetogglemodeadmin = ($focus_view_admin == true) ? 'nach Programmen sortieren (Admin)' : 'nach Abteilungen sortieren (Admin)';
$styletoggleadmin = ($focus_view_admin == true) ? 'background-color: #003;' : 'background-color: #030;';
?>
echo '<form method="post" style="margin-bottom: 1em;">';
echo '<input type="hidden" name="csrf_token" id="toggle_advanced_mode_admin_nonce" value="'.csrf_token().'">';
//wp_nonce_field('toggle_advanced_mode_admin_action', 'toggle_advanced_mode_admin_nonce');
echo '<input type="hidden" name="togle_advanced_mode_admin" value="-1">';
echo '<input type="submit" style="'.$styletoggleadmin.'" name="togle_advanced_mode_admin_submit" class="buttonNewAdminStyle" value="'.$valuetogglemodeadmin.'">';
echo '</form>';
<form method="post" style="margin-bottom: 1em;">
<input type="hidden" name="csrf_token" id="toggle_advanced_mode_admin_nonce" value="<?= $csrf_token ?>">
<input type="hidden" name="togle_advanced_mode_admin" value="-1">
<input type="submit" style="<?= $styletoggleadmin ?>" name="togle_advanced_mode_admin_submit" class="buttonNewAdminStyle" value="<?= $valuetogglemodeadmin ?>">
</form>
<?php
}
if ($selecteduser !== 'admin'){
echo '<p class="text_akt_abt">Aktuelle Abteilung '.$aktabt.' von '.$maxvalue.' ('.htmlspecialchars(strtoupper($allprogrammeabtstrcleared)).')</p><a class="text_akt_abt" href="https://www.gymnastics.sport/publicdir/rules/files/en_1.1.%20WAG%20Code%20of%20Points%202025-2028.pdf" target="_blank">CoP 2025-2028</a><a class="text_akt_abt" href="https://www.stv-fsg.ch/fileadmin/user_upload/Wettkampfprogramm_2025-2028_13.11.2025.pdf" target="_blank">STV 2025-2028</a>';
@@ -630,12 +634,13 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
$arrayNameMap = array_change_key_case(array_column($disciplines, 'id', 'name'), CASE_LOWER);
$itemsToLoop[] = ['name' => $selecteduser, 'id' => $arrayNameMap[$selecteduser] ?? null];
}
// var_dump($itemsToLoop);
$indexedDisciplines = array_column($disciplines, 'name', 'id');
?>
<div class="div_edit_values_user_outer">
<div class="div_edit_values_user" style="display: none;">
<h3 class="heading_fv_selturnerin">
<h3 class="heading_fv_selturnerin" tabindex="-1">
Aktuelle Turnerin:
<span class="current-turnerin-name"></span>
</h3>
@@ -647,38 +652,40 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
<?php if (isAdmin()) : ?>
<h4><?= $d['name'] ?></h4>
<?php endif; ?>
<?php foreach ($notenConfig as $nc) :
$isProGeraet = (intval($nc['pro_geraet']) === 1);
$allowedGeraete = !empty($nc['geraete_json']) ? json_decode($nc['geraete_json'], true) : [];
if (!$isProGeraet && !in_array($d['id'], $allowedGeraete)) { continue; }
$disabled = ($nc['type'] === 'berechnung') ? 'disabled' : '';
?>
<div class="allNotentable">
<div class="singleNotentable">
<?php foreach ($notenConfig as $nc) :
$isProGeraet = (intval($nc['pro_geraet']) === 1);
$allowedGeraete = !empty($nc['geraete_json']) ? json_decode($nc['geraete_json'], true) : [];
if (!$isProGeraet && !in_array($d['id'], $allowedGeraete)) { continue; }
$disabled = ($nc['type'] === 'berechnung') ? 'disabled' : '';
?>
<table class="titleWidthNormalInput editkampfrichter_user note-container" data-note-id="<?= $nc['id'] ?>" data-runs-config='<?= htmlspecialchars($nc['anzahl_laeufe_json'] ?? '{"default":1}') ?>'>
<thead>
<tr>
<th class="<?= $nc['id'] ?>-field-th note-name-header"><?= $nc['name'] ?></th>
</tr>
</thead>
<tbody>
<tr class="inputs-row">
<td class="nopadding input-cell-run-1">
<input type="number" class="ajax-input fullinput changebleValue"
data-person-id=""
data-field-type-id="<?= $nc['id'] ?>"
data-geraet-id="<?= $d['id'] ?>"
data-run="1"
value=""
min="0" max="20" step="0.005" <?= $disabled ?>>
</td>
</tr>
</tbody>
</table>
<?php endforeach ?>
<table class="titleWidthNormalInput editkampfrichter_user note-container" data-note-id="<?= $nc['id'] ?>" data-runs-config='<?= htmlspecialchars($nc['anzahl_laeufe_json'] ?? '{"default":1}') ?>'>
<thead>
<tr>
<th class="<?= $nc['id'] ?>-field-th note-name-header"><?= $nc['name'] ?></th>
</tr>
</thead>
<tbody>
<tr class="inputs-row">
<td class="nopadding input-cell-run-1">
<input type="number" class="ajax-input fullinput changebleValue"
data-person-id=""
data-field-type-id="<?= $nc['id'] ?>"
data-geraet-id="<?= $d['id'] ?>"
data-run="1"
value=""
min="0" max="20" step="0.005" <?= $disabled ?>>
</td>
</tr>
</tbody>
</table>
<?php endforeach ?>
</div>
</div>
<?php if (!isAdmin()) : ?>
<p class="editkampfrichter_user_text">Die Endnote wird wie folgt automatisch berrechnet: Endnote <?= $d['name'] ?> = 10 - E<sub>Ø</sub> Note + D Note - Neutrale Abzüge</p>
<?php endif; ?>
@@ -687,13 +694,27 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
data-person-id=""
data-geraet-id="<?= $d['id'] ?>"
value="Turnerin anzeigen">
<input type="button" class="submit-display-start"
data-geraet-id="<?= $d['id'] ?>"
value="Start freigeben">
<input type="button" class="submit-display-result"
data-person-id=""
data-geraet-id="<?= $d['id'] ?>"
value="Ergebnis anzeigen">
<div class="div-submit-display-start">
<input type="button" class="submit-display-start start"
data-person-id=""
data-geraet-id="<?= $d['id'] ?>"
data-type="1"
value="Startfreigabe erteilen">
<input type="button" class="submit-display-start stopp"
data-person-id=""
data-geraet-id="<?= $d['id'] ?>"
data-type="0"
value="Startfreigabe enziehen">
</div>
<div class="div-submit-display-result">
<input type="button" class="submit-display-result"
data-person-id=""
data-geraet-id="<?= $d['id'] ?>"
data-run="1"
value="Ergebnis anzeigen">
</div>
<?php if (strtolower($d["name"]) === 'boden') : ?>
<div class="playcontrolDiv">
@@ -761,6 +782,14 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
}
$stmt->close();
// Extended Disciplines, contains the 0 disc
$disciplinesExtended = array_merge(
[["id" => 0, "name" => "None"]],
$disciplines
);
foreach ($grouped as $abteilung => $entries_group) :
// ... (PDF path and H3 tag)
@@ -822,6 +851,56 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
$entries_to_display = $entries_group;
}
// Table Header creator with run columns
$arrayIndexedNoten = [];
$arrayIndexedNotenHeader = [];
$uidN = 0;
foreach ($entries_group as $row) :
foreach ($disciplinesExtended as $discipline) :
// Check if the current user/admin is allowed to see this specific discipline
if ($discipline['id'] === 0 || $selecteduser === strtolower($discipline['name']) || $selecteduser === 'admin') :
// 2. Now iterate through the scoring configurations for this discipline
foreach ($notenConfig as $snC) {
$showAdmin = isAdmin() && intval($snC['zeige_in_tabelle_admin']) === 1;
$showPublic = !isAdmin() && intval($snC['zeige_in_tabelle']) === 1;
if (!($showAdmin || $showPublic)) { continue; }
if (intval($snC['pro_geraet']) === 1 && intval($discipline['id']) === 0) { continue; }
if (intval($snC['pro_geraet']) !== 1) {
$allowedGeraete = !empty($snC['geraete_json']) ? json_decode($snC['geraete_json'], true) : [];
if (!in_array($discipline['id'], $allowedGeraete)) { continue; }
}
$mobile = (intval($snC['zeige_in_tabelle_mobile']) === 1) ? "" : "notMobile";
// Logic to fetch and format the value
$defaultValue = $snC['default_value'] ?? 0;
$runsJSON = !empty($snC['anzahl_laeufe_json']) ? json_decode($snC['anzahl_laeufe_json'], true) : [];
$runs = $runsJSON[$discipline['id']][$indexedProgrammes[$row['programm'] ?? ''] ?? ''] ?? $runsJSON["default"] ?? 1;
for ($r = 1; $r <= $runs; $r++) :
$note = $notenIndexed[$row['id']][$discipline['id']][$snC['id']][$r] ?? $defaultValue;
$normalizedNote = number_format($note, $snC['nullstellen'] ?? 2);
$arrayIndexedNoten[intval($row['id'])][intval($discipline['id'])][intval($snC['id'])][intval($r)] = ["value" => $normalizedNote, "mobile" => $mobile];
$arrayIndexedNotenHeader[intval($discipline['id'])][intval($snC['id'])][intval($r)] = ["mobile" => $mobile];
$uidN++;
endfor;
}
endif;
endforeach;
endforeach;
$localPath = $_SERVER['DOCUMENT_ROOT'] . "/wp-content/ergebnisse/KTBB_Ergebnisse_" . $abteilung . "_" . $current_year . ".pdf";
echo '<div class="singleAbtDiv">';
if ($selecteduser === 'admin') echo '<h2 class="titleSingleAbt">'. strtoupper($abteilung);
@@ -835,12 +914,9 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
echo '<th>'.$textheadingrang.'</th>';
}
if ($focus_view_admin == true){
if (!isAdmin() || $focus_view_admin == true){
echo '<th>RF</th>';
}
if ($selecteduser !== 'admin'){
echo '<th></th>';
} ?>
}?>
<th>Name</th>
<?php if ($selecteduser === 'admin') { echo '<th>Jg.</th>'; } ?>
<th class="notMobile">Verein</th>
@@ -848,7 +924,23 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
<?php if ($selecteduser === 'admin' || $selecteduser === 'boden'){ ?>
<th class="notMobile">Musik Boden</th>
<?php }
// 1. Iterate through disciplines first
foreach ($arrayIndexedNotenHeader as $dis => $aNtypes) :
foreach ($aNtypes as $nType => $aRuns) :
$displayRunType = count($aRuns) > 1;
foreach ($aRuns as $run => $cArray) :
$displayRunString = $displayRunType ? '<sup>' . $run . '</sup>' : '';
$displayDisciplinesString = isset($indexedDisciplines[$dis]) ? ' ' . $indexedDisciplines[$dis] : '';
?>
<th class="<?= $cArray["mobile"] ?>">
<?= $indexedNotenNames[$nType] ?><?= $displayRunString ?><?= $displayDisciplinesString ?>
</th>
<?php endforeach;
endforeach;
endforeach;
/*// 1. Iterate through disciplines first
foreach ($disciplines as $discipline) {
$lowdiscipline = strtolower($discipline['name']);
@@ -864,14 +956,35 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
if (intval($snC['pro_geraet']) !== 1) {
$allowedGeraete = !empty($snC['geraete_json']) ? json_decode($snC['geraete_json'], true) : [];
if (!in_array($discipline['id'], $allowedGeraete)) { continue; }
}
}
$runsJSON = !empty($snC['anzahl_laeufe_json']) ? json_decode($snC['anzahl_laeufe_json'], true) : [];
if (isset($runsJSON[$discipline['id']])) {
$runs = $runsJSON[$discipline['id']];
foreach ($runs as $r) : ?>
<th class="<?= $mobile ?>">
<?= $snC['name'] . ' ' . ucfirst($lowdiscipline) ?>
</th>
<?php endforeach;
} else {
$runs = $runsJSON["default"] ?? 1;
for ($r = 1; $r <= $runs; $r++) : ?>
<th class="<?= $mobile ?>">
<?= $snC['name'] . ' ' . ucfirst($lowdiscipline) ?>
</th>
<?php endfor;
}
$mobile = (intval($snC['zeige_in_tabelle_mobile']) === 1) ? "" : "notMobile";
?>
<th class="<?= $mobile ?>">
<?= $snC['name'] . ' ' . ucfirst($lowdiscipline) ?>
</th>
<?php
}
endif;
}
@@ -887,13 +1000,34 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
$allowedGeraete = !empty($snC['geraete_json']) ? json_decode($snC['geraete_json'], true) : [];
if (!in_array(0, $allowedGeraete)) { continue; }
$mobile = (intval($snC['zeige_in_tabelle_mobile']) === 1) ? "" : "notMobile";
$runsJSON = !empty($snC['anzahl_laeufe_json']) ? json_decode($snC['anzahl_laeufe_json'], true) : [];
if (isset($runsJSON[0][$snC['id']])) {
$runs = $runsJSON[0][$snC['id']];
foreach ($runs as $r) : ?>
<th class="<?= $mobile ?>">
<?= $snC['name'] ?>
</th>
<?php endforeach;
} else {
$runs = $runsJSON["default"] ?? 1;
for ($r = 1; $r <= $runs; $r++) : ?>
<th class="<?= $mobile ?>">
<?= $snC['name'] ?>
</th>
<?php endfor;
}
?>
<th class="<?= $mobile ?>">
<?= $snC['name'] ?>
</th>
<?php
}
}
}*/
?>
<th>Edit</th>
@@ -938,7 +1072,29 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
$notMobileNotAdmin = ($selecteduser !== 'admin') ? 'notMobile' : '';
foreach ($disciplines as $discipline) {
foreach ($arrayIndexedNotenHeader as $dis => $aNtypes) :
foreach ($aNtypes as $nType => $aRuns) :
foreach ($aRuns as $run => $cArray) :
if (isset($arrayIndexedNoten[intval($row['id'])][intval($dis)][intval($nType)][intval($run)])) : ?>
<td class="<?= $cArray["mobile"] ?> changebleValue"
data-field-type-id="<?= $nType ?>"
data-geraet-id="<?= $dis ?>"
data-person-id="<?= $row["id"] ?>"
data-run="<?= $run ?>">
<?= $arrayIndexedNoten[intval($row['id'])][intval($dis)][intval($nType)][intval($run)]["value"] ?>
</td>
<?php else: ?>
<td class="<?= $cArray["mobile"] ?>">
---
</td>
<?php endif;
endforeach;
endforeach;
endforeach;
/*foreach ($disciplines as $discipline) {
$lowdiscipline = strtolower($discipline['name']);
// Check if the current user/admin is allowed to see this specific discipline
@@ -960,18 +1116,26 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
// Logic to fetch and format the value
$defaultValue = $snC['default_value'] ?? 0;
$note = $notenIndexed[$row['id']][$discipline['id']][$snC['id']][1] ?? $defaultValue;
$normalizedNote = number_format($note, $snC['nullstellen'] ?? 2);
?>
<td class="<?= $mobile ?> changebleValue"
data-field-type-id="<?= intval($snC['id']) ?>"
data-geraet-id="<?= intval($discipline['id']) ?>"
data-person-id="<?= intval($row['id']) ?>">
<?= $normalizedNote ?>
</td>
$runsJSON = !empty($snC['anzahl_laeufe_json']) ? json_decode($snC['anzahl_laeufe_json'], true) : [];
<?php
$runs = $runsJSON[$discipline['id']][$indexedProgrammes[$row['programm'] ?? ''] ?? ''] ?? $runsJSON["default"] ?? 1;
for ($r = 1; $r <= $runs; $r++) :
$note = $notenIndexed[$row['id']][$discipline['id']][$snC['id']][$r] ?? $defaultValue;
$normalizedNote = number_format($note, $snC['nullstellen'] ?? 2);
?>
<td class="<?= $mobile ?> changebleValue"
data-field-type-id="<?= intval($snC['id']) ?>"
data-geraet-id="<?= intval($discipline['id']) ?>"
data-person-id="<?= intval($row['id']) ?>"
data-run="<?= intval($r) ?>">
<?= $normalizedNote ?>
</td>
<?php endfor;
}
endif;
}
@@ -988,19 +1152,27 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
// Logic to fetch and format the value
$defaultValue = $snC['default_value'] ?? 0;
$note = $notenIndexed[$row['id']][0][$snC['id']][1] ?? $defaultValue;
$normalizedNote = number_format($note, $snC['nullstellen'] ?? 2);
?>
<td class="<?= $mobile ?> changebleValue"
data-field-type-id="<?= intval($snC['id']) ?>"
data-geraet-id="0"
data-person-id="<?= intval($row['id']) ?>">
<?= $normalizedNote ?>
</td>
<?php
$runsJSON = !empty($snC['anzahl_laeufe_json']) ? json_decode($snC['anzahl_laeufe_json'], true) : [];
$runs = $runsJSON[0][$indexedProgrammes[$row['programm'] ?? ''] ?? ''] ?? $runsJSON["default"] ?? 1;
for ($r = 1; $r <= $runs; $r++) :
$note = $notenIndexed[$row['id']][0][$snC['id']][1] ?? $defaultValue;
$normalizedNote = number_format($note, $snC['nullstellen'] ?? 2);
?>
<td class="<?= $mobile ?> changebleValue"
data-field-type-id="<?= intval($snC['id']) ?>"
data-geraet-id="0"
data-person-id="<?= intval($row['id']) ?>"
data-run="<?= intval($r) ?>">
<?= $normalizedNote ?>
</td>
<?php endfor;
}
}
}*/
/*if ($selecteduser === 'admin') {
@@ -1072,22 +1244,7 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
if ($selecteduser === 'admin'){
echo '<p style="font-weight:600; margin: 0px;">Gesamt: '.$total_count.' '.$mehrzahl.'</p>';
}
if ($selecteduser === 'admin' && $focus_view_admin == false) : ?>
<div class="admin-kampfrichter-berechnung-container">
<form method="post" style="margin-top:20px;">
<?php //wp_nonce_field('recalculate_all_scores', 'recalculate_nonce');
echo '<input type="hidden" name="csrf_token" id="recalculate_nonce" value="'.csrf_token().'">';
?>
<input class="admin-kampfrichter-berechnung-button buttonNewAdminStyle" type="submit" name="recalculate_scores" value="Gesamtpunktzahl für alle Einträge berechnen">
</form>
<form method="post" style="margin-top:20px;">
<?php //wp_nonce_field('reset_all_scores', 'reset_nonce');
echo '<input type="hidden" name="csrf_token" id="reset_nonce" value="'.csrf_token().'">';
?>
<input class="admin-kampfrichter-berechnung-reset-button buttonNewAdminStyle" type="submit" name="reset_scores" value="Ränge Zurücksetzten">
</form>
</div>
<?php endif; ?>
?>
</div>
<div class="noKampfrichterDiv"><h1>Keine Kampfrichterinnen ausgewählt</h1></div>
<?php else : ?>
@@ -1095,7 +1252,6 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
<?php endif;?>
<div class="divLiveSyncronisation"><h2 class="heading-pannel flexRow" id="wsInfo">Live Synchronsation: <span class="fullHeightRectangle" id="wsInfoRectangle"></span></h2></div>
</section>
<div class="msgDiv"></div>
<?php
$topBg = '#424242';
@@ -1147,7 +1303,7 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
<script>
window.FREIGABE = "<?php echo $selectedfreigabe; ?>";
window.CSDR_TOKEN = "<?php echo $_SESSION['csrf_token'] ?? csrf_token(); ?>";
window.CSDR_TOKEN = "<?= $csrf_token; ?>";
window.WS_ACCESS_TOKEN = "<?= generateWSToken('kampfrichter') ?>";
window.AKTUELLES_JAHR = "<?= $current_year ?>";
</script>

View File

@@ -6,190 +6,317 @@ error_reporting(E_ALL);
use Dotenv\Dotenv;
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session(true);
$oturl = $_GET['otl'] ?? '';
if (!$oturl) {
http_response_code(403);
http_response_code(404);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
$error = '';
function logIn() {
class otl {
global $baseDir;
private function connectToDB() {
$iduser = intval($_POST['user_id']);
global $mysqli, $baseDir;
if (isset($mysqli)) { return $mysqli; }
// security: user must have passed one-time-login first
if (empty($_SESSION['set_new_password_id_user']) || empty($_SESSION['set_new_password_granted']) || $_SESSION['set_new_password_id_user'] !== $iduser || $_SESSION['set_new_password_granted'] !== true) {
http_response_code(403);
exit;
$_SESSION['access_granted_db_otl'] = true;
$type = 'otl';
// DB
$dbconnection = require $baseDir .'/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true){
return "DB Error";
}
$_SESSION['access_granted_db_otl'] = false;
return $mysqli;
}
$type = 'otl';
// DB
$dbconnection = require $baseDir .'/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true){
return "DB Error";
}
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../composer/vendor/autoload.php';
$envFile = realpath($baseDir . '/../config/.env.pw-encryption-key');
if ($envFile === false) {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => "Environment file not found"
]);
exit;
}
try {
$envDir = dirname($envFile);
private function pwProcessing() {
$dotenv = Dotenv::createImmutable($envDir, '.env.pw-encryption-key');
$dotenv->load();
} catch (Throwable $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => "Dotenv error"
]);
global $baseDir;
require $baseDir . '/../composer/vendor/autoload.php';
$envFile = realpath($baseDir . '/../config/.env.pw-encryption-key');
if ($envFile === false) {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => "Environment file not found"
]);
exit;
}
try {
$envDir = dirname($envFile);
$dotenv = Dotenv::createImmutable($envDir, '.env.pw-encryption-key');
$dotenv->load();
} catch (Throwable $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => "Dotenv error"
]);
}
$password = trim($_POST['password1']);
$passwordRep = trim($_POST['password2']);
if ($password === '' || $passwordRep === '') {
return 'Beide Felder müssen ausgefüllt sein';
}
if ($password !== $passwordRep) {
return 'Beide Passwörter müssen identisch sein';
}
$hash = password_hash($password, PASSWORD_ARGON2ID);
$iv_length = openssl_cipher_iv_length('aes-256-cbc');
$iv = random_bytes($iv_length);
$encrypted = openssl_encrypt(
'SET_BY_OTL',
'aes-256-cbc',
$_ENV['PW_ENCRYPTION_KEY'],
0,
$iv
);
$cipher_store = base64_encode($iv . $encrypted);
return ['success' => true, 'hash' => $hash, 'encpw' => $cipher_store];
}
public function logIn(int $id) {
$password = trim($_POST['password1']);
$password2 = trim($_POST['password2']);
if ($password === '' || $password2 === '') {
return 'Beide Felder müssen ausgefüllt sein';
global $baseDir;
$mysqli = $this->connectToDB();
require $baseDir . '/../scripts/db/db-tables.php';
// delete the one-time token
if (!isset($_SESSION['otl_dbid'])) {
return 'Interner Fehler';
}
$dbid = intval($_SESSION['otl_dbid']);
$stmt = $mysqli->prepare("DELETE FROM $tableOTL WHERE id = ?");
$stmt->bind_param("i", $dbid);
if (!$stmt->execute()) {
return "DB Error";
}
$stmt->close();
$sql = "SELECT freigabe FROM $tableInternUsers WHERE id = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
$freigabe = $row['freigabe'];
$stmt->close();
$mysqli->close();
unset($_SESSION['set_new_password_id_user'], $_SESSION['set_new_password_granted'], $_SESSION['otl_dbid']);
$freigabenArray = json_decode($freigabe, true) ?? [];
$freigabenTypeArray = $freigabenArray['types'] ?? [];
if (count($freigabenTypeArray) > 0) {
$_SESSION = array();
session_destroy();
session_start();
}
foreach ($freigabenTypeArray as $freigabeType){
$_SESSION['access_granted_'.$freigabeType] = true;
$_SESSION['user_id_'.$freigabeType] = $id;
}
var_dump($_SESSION);
if (in_array('wk_leitung', $freigabenTypeArray)) {
header("Location: /intern/wk-leitung/logindata");
exit;
} elseif (in_array('trainer', $freigabenTypeArray)) {
header("Location: /intern/trainer");
exit;
} elseif (in_array('kampfrichter', $freigabenTypeArray)) {
header("Location: /intern/kampfrichter");
exit;
} else {
return 'Dieser Benutzer hat keine Berechtigungen.';
}
}
if ($password !== $password2) {
return 'Beide Passwörter müssen identisch sein';
}
public function resetPW() {
$hash = password_hash($password, PASSWORD_ARGON2ID);
global $baseDir;
$iv_length = openssl_cipher_iv_length('aes-256-cbc');
$iv = random_bytes($iv_length);
$iduser = intval($_POST['user_id']);
$encrypted = openssl_encrypt(
'SET_BY_OTL',
'aes-256-cbc',
$_ENV['PW_ENCRYPTION_KEY'],
0,
$iv
);
$cipher_store = base64_encode($iv . $encrypted);
// security: user must have passed one-time-login first
if (empty($_SESSION['set_new_password_id_user']) || empty($_SESSION['set_new_password_granted']) || $_SESSION['set_new_password_id_user'] !== $iduser || $_SESSION['set_new_password_granted'] !== true) {
http_response_code(403);
exit;
}
// update password
$updateResult = db_update($mysqli, $tableInternUsers, ['password_hash' => $hash, 'password_cipher' => $cipher_store, 'edited_by' => 'otlogin'], ['id' => $iduser]);
if ($updateResult === false) {
return 'Passwork konnte nicht neu gesetzt werden';
require $baseDir . '/../scripts/db/db-tables.php';
$mysqli = $this->connectToDB();
$pwArray = $this->pwProcessing();
if (!isset($pwArray['success']) || !$pwArray['success']) {
return 'Passwort konnte nicht verarbeitet werden';
}
// update password
$updateResult = db_update($mysqli, $tableInternUsers, ['password_hash' => $pwArray['hash'] ?? '', 'password_cipher' => $pwArray['encpw'] ?? '', 'edited_by' => 'otlogin'], ['id' => $iduser]);
if ($updateResult === false) {
return 'Passwork konnte nicht neu gesetzt werden';
}
// delete the one-time token
if (!isset($_SESSION['otl_dbid'])) {
return 'Interner Fehler';
}
$dbid = intval($_SESSION['otl_dbid']);
$stmt = $mysqli->prepare("DELETE FROM $tableOTL WHERE id = ?");
$stmt->bind_param("i", $dbid);
if (!$stmt->execute()) {
return "DB Error";
}
$stmt->close();
$this->logIn($iduser);
}
// delete the one-time token
if (!isset($_SESSION['otl_dbid'])) {
return 'Interner Fehler';
}
public function createUser() {
$dbid = intval($_SESSION['otl_dbid']);
global $baseDir;
$stmt = $mysqli->prepare("DELETE FROM $tableOTL WHERE id = ?");
$stmt->bind_param("i", $dbid);
$iduser = intval($_POST['user_id']);
if (!$stmt->execute()) {
return "DB Error";
}
if (empty($_SESSION['set_new_user_id_user']) || empty($_SESSION['set_new_user_granted']) || $_SESSION['set_new_user_id_user'] !== $iduser || $_SESSION['set_new_user_granted'] !== true) {
http_response_code(403);
exit;
}
$stmt->close();
require $baseDir . '/../scripts/db/db-tables.php';
$sql = "SELECT freigabe FROM $tableInternUsers WHERE id = ?";
$mysqli = $this->connectToDB();
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("i", $iduser);
$stmt->execute();
$arrayDB = [];
$result = $stmt->get_result();
$row = $result->fetch_assoc();
if (isset($_POST['password1'], $_POST['password2'])) {
$pwArray = $this->pwProcessing();
$freigabe = $row['freigabe'];
$stmt->close();
if (!isset($pwArray['success']) || !$pwArray['success']) {
return 'Passwort konnte nicht verarbeitet werden';
}
$mysqli->close();
$arrayDB[] = ["name" => 'password_hash', "value" => $pwArray['hash']];
$arrayDB[] = ["name" => 'password_cipher', "value" => $pwArray['encpw']];
}
unset($_SESSION['set_new_password_id_user'], $_SESSION['set_new_password_granted'], $_SESSION['otl_dbid']);
if (isset($_POST['username'])) {
$arrayDB[] = ["name" => 'username', "value" => htmlspecialchars(trim($_POST['username']))];
}
$freigabenArray = json_decode($freigabe, true) ?? [];
$freigabenTypeArray = $freigabenArray['types'] ?? [];
if (isset($_POST['name_person'])) {
$arrayDB[] = ["name" => 'name_person', "value" => htmlspecialchars(trim($_POST['name_person']))];
}
if (count($freigabenTypeArray) > 0) {
$_SESSION = array();
session_destroy();
session_start();
}
// --- NEW LOGIC TO UTILIZE $arrayDB ---
foreach ($freigabenTypeArray as $freigabeType){
$_SESSION['access_granted_'.$freigabeType] = true;
$_SESSION['passcode'.$freigabeType.'_id'] = $iduser;
}
$updateData = [
'edited_by' => 'otlogin',
'login_active' => 1
];
if (in_array('wk_leitung', $freigabenTypeArray)) {
header("Location: /intern/wk-leitung/logindata");
exit;
} elseif (in_array('trainer', $freigabenTypeArray)) {
header("Location: /intern/trainer");
exit;
} elseif (in_array('kampfrichter', $freigabenTypeArray)) {
header("Location: /intern/kampfrichter");
exit;
} else {
return 'Dieser Benutzer hat keine Berechtigungen.';
// Convert the $arrayDB list into a flat associative array
if (!empty($arrayDB)) {
foreach ($arrayDB as $entry) {
$updateData[$entry['name']] = $entry['value'];
}
}
// Execute update using the dynamically built array
$updateResult = db_update(
$mysqli,
$tableInternUsers,
$updateData,
['id' => $iduser]
);
if ($updateResult === false) {
return 'Nutzer konnte nicht aktualisiert werden';
}
$this->logIn($iduser);
}
}
$pwClass = New otl();
/* ============================================================
PASSWORD SET ON POST
============================================================ */
if (isset($_POST['password1'], $_POST['password2'], $_POST['setpasswordbtn'], $_POST['user_id'])) { $error = logIn() ?? ''; }
/* ============================================================
ONE-TIME-LOGIN VALIDATION (GET)
============================================================ */
$token = "QQa2UMbEYW8oOL7wz9DjtqECVCikSZsDuSdmzxiadEXFsKyujEUyQOW1AYMD2OqU8VXxClIRweRuWLzvBrZpPYL41e89Rs96tM7Lq1KpjA5E2mg2UfgvztheGRV";
require $baseDir .'/../scripts/db/db-verbindung-script-guest.php';
// fetch one-time login record
$result = db_select(
$guest,
$tableOTL,
'id, user_id',
'id, user_id, `type`',
'url = ? AND timestamp >= NOW() - INTERVAL 24 HOUR',
[$oturl]
);
if (!$result || count($result) !== 1) {
echo 'forbidden';
http_response_code(403);
exit;
}
@@ -197,26 +324,56 @@ if (!$result || count($result) !== 1) {
$dbid = intval($result[0]['id']);
$iduser = intval($result[0]['user_id']);
if (isset($_POST['password1'], $_POST['password2'], $_POST['setpasswordbtn'], $_POST['user_id']) && $result[0]['type'] === 'pwreset') { $error = $pwClass->resetPW() ?? ''; }
elseif (isset($_POST['setpasswordbtn'], $_POST['user_id']) && $result[0]['type'] === 'create_profile') { $error = $pwClass->createUser() ?? ''; }
// store dbid for later deletion
$_SESSION['otl_dbid'] = $dbid;
$tableusers = 'wp_secure_lock';
// fetch user
$userinfo = db_select($guest, $tableInternUsers, 'username', 'id = ?', [$iduser]);
$guest->close();
if (!$userinfo || count($userinfo) !== 1) {
echo 'Ungültige Benutzerinformationen';
exit;
if ($result[0]['type'] === 'login') {
$pwClass->logIn($iduser);
}
$username = $userinfo[0]['username'];
if ($result[0]['type'] === 'pwreset') {
$userinfo = db_select($guest, $tableInternUsers, 'username', 'id = ?', [$iduser]);
$username = $userinfo[0]['username'];
if (!$userinfo || count($userinfo) !== 1) {
echo 'Ungültige Benutzerinformationen';
exit;
}
// set session token that grants password reset
$_SESSION['set_new_password_id_user'] = $iduser;
$_SESSION['set_new_password_granted'] = true;
$hasUsername = true;
$hasName = true;
// set session token that grants password reset
$_SESSION['set_new_password_id_user'] = $iduser;
$_SESSION['set_new_password_granted'] = true;
} elseif ($result[0]['type'] === 'create_profile') {
$userinfo = db_select($guest, $tableInternUsers, 'username, `password_hash`, `name_person`', 'id = ?', [$iduser]);
if (!$userinfo || count($userinfo) !== 1) {
echo 'Ungültige Benutzerinformationen';
exit;
}
$hasPW = $userinfo[0]['password_hash'] !== null;
$hasUsername = $userinfo[0]['username'] !== '';
$username = $userinfo[0]['username'];
$hasName = $userinfo[0]['name_person'] !== '';
unset($userinfo);
// set session token that grants password reset
$_SESSION['set_new_user_id_user'] = $iduser;
$_SESSION['set_new_user_granted'] = true;
}
// fetch user
$guest->close();
?>
@@ -230,6 +387,7 @@ $_SESSION['set_new_password_granted'] = true;
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
<link href="/files/fonts/fonts.css" rel="stylesheet">
<link href="/intern/css/otl.css" rel="stylesheet">
<script src="/intern/js/custom-msg-display.js"></script>
</head>
@@ -244,6 +402,18 @@ $_SESSION['set_new_password_granted'] = true;
<p style="font-weight:400; line-height: 1.5; margin-bottom: 50px;">
</p>
<form method="post">
<?php if (!$hasUsername) : ?>
<label for="username">Benutzername</label><br>
<div class="divShowPw">
<input type="text" name="username" id="username" placeholder="Benutzername" required>
</div><br>
<?php endif; ?>
<?php if (!$hasName) : ?>
<label for="name_person">Name</label><br>
<div class="divShowPw">
<input type="text" name="name_person" id="name_person" placeholder="Max Muster" required>
</div><br>
<?php endif; ?>
<label for="password1">Neues Passwort eingeben</label><br>
<div class="divShowPw">
<input type="password" name="password1" id="password1" placeholder="Passwort" required>
@@ -277,129 +447,6 @@ $_SESSION['set_new_password_granted'] = true;
<a class="seclog_home_link" href="/"><img src="/intern/img/logo-normal.png" width="64" height="64"></a>
<style>
body{
overflow: hidden;
}
.page-secure-login{
display: flex;
}
.bg-picture-secure-login{
width: calc(100vw - 450px);
height: 100vh;
position: absolute;
left: 0px;
top: 0px;
}
.bg-picture-secure-login img{
width: 100%;
height: 100vh;
object-fit: cover;
}
.bg-secure-login{
display: flex;
width: 100vw;
max-width: 450px;
height: 100vh;
background-color: #fff;
position: absolute;
right: 0px;
top: 0px;
align-items: center;
padding: 30px;
}
.bg-secure-login-form > h1{
color: #000 !important;
font-size: 32px;
}
.bg-secure-login-form input[type=password], .bg-secure-login-form input[type=text]{
padding: 5px;
width: 100%;
max-width: 300px;
border-top: none !important;
border-left: none !important;
border-right: none !important;
font-size: 16px;
border-bottom: 1px solid #000 !important;
border-radius: 0px !important;
}
.divShowPw:not(#lastDivShowPw) {
margin-bottom: 20px;
}
.bg-secure-login-form input[type=password]:focus, .bg-secure-login-form input[type=text]:focus{
outline: none;
border-bottom: 1px solid #000 !important;
}
.bg-secure-login-form input[type=password]::placeholder, .bg-secure-login-form input[type=text]::placeholder {
color: #ccc !important;
}
.bg-secure-login-form input[type=submit]{
background-color: #fff !important;
padding: 10px 20px !important;
margin-top: 25px !important;
border: 1px solid #000 !important;
color: #000 !important;
transition: all 0.3s ease-out !important;
border-radius: 0px !important;
}
body {
color: #000 !important;
}
* {
box-sizing: border-box;
}
.bg-secure-login-form input[type=submit]:hover{
background-color: #000 !important;
color: #fff !important;
}
.bg-secure-login-form > p{
margin-bottom: 30px;
}
.seclog_home_link{
position: fixed;
z-index: 1000;
top: 30px;
right: 30px;
}
.divShowPw {
margin-top: 10px;
position: relative;
display: inline-block;
width: 100%;
max-width: 300px;
}
.togglePassword {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
cursor: pointer;
transition: all 0.5s ease;
}
.togglePassword:hover {
transform: translateY(-50%) scale(1.15);
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 1000px #ffffff inset !important;
box-shadow: 0 0 0 1000px #ffffff inset !important;
-webkit-text-fill-color: #000000 !important;
transition: background-color 5000s ease-in-out 0s;
}
</style>
<script>
const toggleButtons = document.querySelectorAll('.togglePassword');

View File

@@ -1,94 +0,0 @@
<?php
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
http_response_code(403);
exit;
}
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https://" : "http://";
$domain = $_SERVER['HTTP_HOST'];
$url = $protocol . $domain;
if ((isset($_POST['prev_abt'])) && !empty($_POST['prev_abt_submit'])) {
$value = get_option('wk_panel_current_abt', 1);
if ($value > 1){
$value -= 1;
update_option('wk_panel_current_abt', $value);
}
header("Location: ".$url."/intern/kampfrichter".$_SERVER['REQUEST_URI']);
exit;
}
if ((isset($_POST['next_abt'])) && !empty($_POST['next_abt_submit'])) {
$value = get_option('wk_panel_current_abt', 1);
$maxvalue = $wpdb->get_var( "SELECT abteilung FROM $table_name ORDER BY abteilung DESC LIMIT 1" );
if ($value < $maxvalue){
$value += 1;
update_option('wk_panel_current_abt', $value);
}
header("Location: ".$url."/intern/kampfrichter".$_SERVER['REQUEST_URI']);
exit;
}
if (!isset($_SESSION['currentsubabt'])){
$_SESSION['currentsubabt'] = 0;
}
if (!isset($_SESSION['last_abt'])){
$_SESSION['last_abt'] = get_option('wk_panel_current_abt', 1);
}
if ($_SESSION['last_abt'] !== get_option('wk_panel_current_abt', 1)){
$_SESSION['currentsubabt'] = 0;
$_SESSION['last_abt'] = get_option('wk_panel_current_abt', 1);
}
if ((isset($_POST['prev_subabt'])) && !empty($_POST['prev_subabt_submit'])) {
$value = $_SESSION['currentsubabt'];
if ($value > 0){
$_SESSION['currentsubabt']--;
$_SESSION['last_abt'] = get_option('wk_panel_current_abt', 1);
}
header("Location: ".$url."/intern/kampfrichter");
exit;
}
if ((isset($_POST['next_subabt'])) && !empty($_POST['next_subabt_submit'])) {
$value = $_SESSION['currentsubabt'];
if ($value < 4){
$_SESSION['currentsubabt']++;
$_SESSION['last_abt'] = get_option('wk_panel_current_abt', 1);
}
header("Location: ".$url."/intern/kampfrichter");
exit;
}
if (
isset($_POST['togle_advanced_mode']) &&
!empty($_POST['togle_advanced_mode_submit']) &&
check_admin_referer('toggle_advanced_mode_action', 'toggle_advanced_mode_nonce')
) {
$current_value = get_option('option_advanced_mode', false);
$new_value = !$current_value;
update_option('option_advanced_mode', $new_value);
hheader("Location: ".$url."/intern/kampfrichter".$_SERVER['REQUEST_URI']);
exit;
}
if (
isset($_POST['togle_advanced_mode_admin']) &&
!empty($_POST['togle_advanced_mode_admin_submit']) &&
check_admin_referer('toggle_advanced_mode_admin_action', 'toggle_advanced_mode_admin_nonce')
) {
$current_value = get_option('option_advanced_mode_admin', false);
$new_value = !$current_value;
update_option('option_advanced_mode_admin', $new_value);
header("Location: ".$url."/intern/kampfrichter".$_SERVER['REQUEST_URI']);
exit;
}

View File

@@ -1,15 +1,18 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (
!((isset($_SESSION['access_granted_wk_leitung']) && $_SESSION['access_granted_wk_leitung'] === true) ||
(isset($_SESSION['access_granted_kampfrichter']) && $_SESSION['access_granted_kampfrichter'] === true))
) {
http_response_code(403);
exit;
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
verify_csrf();
check_multiple_allowed_permissions(['kampfrichter', 'wk_leitung']);
if (!isset($_POST['access'])) {
http_response_code(400);
exit;
@@ -17,8 +20,6 @@ if (!isset($_POST['access'])) {
$access = preg_replace("/[\W]/", "", trim($_POST['access']));
$baseDir = $_SERVER['DOCUMENT_ROOT'];
require $baseDir . "/../scripts/websocket/ws-create-token.php";
$token = generateWSToken($access);

View File

@@ -1,10 +1,15 @@
<?php
session_start();
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
verify_csrf();
$new_value = $_POST['freigabe'] ?? '';
$type = $_POST['type'] ?? 'nan';
@@ -12,22 +17,7 @@ $type = $_POST['type'] ?? 'nan';
$allowedTypes = ['kampfrichter', 'trainer'];
if (in_array($type, $allowedTypes)) {
$accessKey = "access_granted_" . $type;
$idKey = "passcode" . $type . "_id";
// 3. Check if they have access
$hasAccess = isset($_SESSION[$accessKey]) &&
$_SESSION[$accessKey] === true &&
!empty($_SESSION[$idKey]) &&
$_SESSION[$idKey] > 0;
if (!$hasAccess) {
echo json_encode(['success' => false, 'message' => 'no permissions']);
exit;
}
check_user_permission($type);
} else {
echo json_encode(['success' => false, 'message' => 'no permissions']);
exit;

View File

@@ -1,31 +1,20 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
$isTrainer =
isset($_SESSION['access_granted_trainer'], $_SESSION['passcodetrainer_id']) &&
$_SESSION['access_granted_trainer'] === true &&
(int)$_SESSION['passcodetrainer_id'] > 0;
require_once $baseDir . '/../scripts/session_functions.php';
$isWkLeitung =
isset($_SESSION['access_granted_wk_leitung'], $_SESSION['passcodewk_leitung_id']) &&
$_SESSION['access_granted_wk_leitung'] === true &&
(int)$_SESSION['passcodewk_leitung_id'] > 0;
ini_wkvs_session();
if (!$isTrainer && !$isWkLeitung) {
http_response_code(403);
exit;
}
check_multiple_allowed_permissions(['trainer', 'wk_leitung']);
verify_csrf();
// Allow large uploads and enough memory for GD processing
ini_set('memory_limit', '256M');
ini_set('max_execution_time', '120');
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
if (!isset($_FILES['music_file']) || $_FILES['music_file']['error'] !== UPLOAD_ERR_OK) {
echo json_encode([
'success' => false,

View File

@@ -1,10 +0,0 @@
-- 1. Update the Noten table to include run_number
-- NOTE: We also update the PRIMARY KEY to include this new column
ALTER TABLE `a4b9577448d6_noten`
ADD COLUMN `run_number` TINYINT(3) UNSIGNED NOT NULL DEFAULT 1 AFTER `jahr`,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`person_id`, `note_bezeichnung_id`, `geraet_id`, `jahr`, `run_number`);
-- 2. Update the configuration table to support program-specific run counts
ALTER TABLE `a4b9577448d6_noten_bezeichnungen`
ADD COLUMN `anzahl_laeufe_json` TEXT NULL DEFAULT NULL AFTER `pro_geraet`;

View File

@@ -4,8 +4,17 @@ 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();
// ---------- Get and sanitize input ----------
$type = isset($_GET['type']) ? preg_replace('/[^a-zA-Z0-9 _-]/', '', $_GET['type']) : '';
$type = isset($_POST['type']) ? preg_replace('/[^a-zA-Z0-9 _-]/', '', $_POST['type']) : '';
$allowed_types = ['logo','scoring','ctext'];
if (!in_array($type, $allowed_types)) {
@@ -14,7 +23,7 @@ if (!in_array($type, $allowed_types)) {
}
if ($type === 'ctext'){
$ctext = isset($_GET['ctext']) ? $_GET['ctext'] : '';
$ctext = isset($_POST['ctext']) ? $_POST['ctext'] : '';
}
$folder = realpath($baseDir.'/displays/json');

View File

@@ -0,0 +1,4 @@
upload_max_filesize = 50M
post_max_size = 55M
max_execution_time = 120
max_input_time = 120

View File

@@ -6,17 +6,18 @@ error_reporting(E_ALL);
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 1 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$type = 'wkl';
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -1,20 +1,21 @@
<?php
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 1 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -1,22 +1,21 @@
<?php
header('Content-Type: application/json');
ini_set("display_errors", 1);
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 1 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -20,16 +20,17 @@ $baseDir = $_SERVER['DOCUMENT_ROOT'];
header('Content-Type: application/json');
session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
$baseDir = $_SERVER['DOCUMENT_ROOT'];
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
// Only accept POST

View File

@@ -2,26 +2,19 @@
header('Content-Type: application/json');
ini_set('display_errors', 1);
error_reporting(E_ALL);
session_start();
if (
empty($_SESSION['access_granted_kampfrichter']) ||
$_SESSION['access_granted_kampfrichter'] !== true ||
empty($_SESSION['passcodekampfrichter_id']) ||
intval($_SESSION['passcodekampfrichter_id']) < 1
) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require $baseDir . '/../scripts/csrf_functions.php';
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('kampfrichter');
verify_csrf();
if (!verify_csrf()) {
echo json_encode(['success' => false, 'message' => 'Forbidden']);
@@ -158,6 +151,14 @@ $notenConfig = $result->fetch_all(MYSQLI_ASSOC);
$stmt->close();
$displayIdNoteL = intval(db_get_var($mysqli, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayIdNoteL'])) ?? 0;
$displayIdNoteR = intval(db_get_var($mysqli, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayIdNoteR'])) ?? 0;
if ($displayIdNoteL !== 0 && $displayIdNoteR !== 0) {
$displayNoten = [$displayIdNoteR => 0, $displayIdNoteL => 0];
}
$noten = [];
$row = $dbresult[0];
@@ -176,15 +177,25 @@ foreach ($disciplines as $d) {
// Determine number of runs for this program
$anzRunsConfig = !empty($snC['anzahl_laeufe_json']) ? json_decode($snC['anzahl_laeufe_json'], true) : [];
$runs = $anzRunsConfig[$programm_id] ?? $anzRunsConfig['default'] ?? 1;
$runs = $anzRunsConfig[$d][$programm_id] ?? $anzRunsConfig['default'] ?? 1;
if (isset($displayNoten) && array_key_exists($snC['id'], $displayNoten)) {
$displayNoten[$snC['id']] = $runs;
}
for ($r = 1; $r <= $runs; $r++) {
$value = $indexedNotenDB[$d][$snC['id']][$r] ?? $snC['default_value'] ?? 0;
$noten[$d][$snC['id']][$r] = number_format($value, $snC['nullstellen'] ?? 2);
$noten[$d][$r][$snC['id']] = number_format($value, $snC['nullstellen'] ?? 2);
}
}
}
$countBtn = 1;
if (isset($displayNoten)) {
$countBtn = min($displayNoten);
}
$titel = $row['vorname'].' '.$row['name'].', '.$row['programm'];
@@ -305,7 +316,8 @@ if ($isAdmin) {
'id' => $editId,
'programm_id' => $programm_id,
'titel' => $titel,
'noten' => $noten
'noten' => $noten,
'countBtn' => $countBtn
]);
} else {
echo json_encode([
@@ -314,7 +326,8 @@ if ($isAdmin) {
'programm_id' => $programm_id,
'titel' => $titel,
'noten' => $noten,
'nturnerin' => $nturnerin
'nturnerin' => $nturnerin,
'countBtn' => $countBtn
]);
}

View File

@@ -8,16 +8,18 @@ ini_set('display_startup_errors', 1);
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);*/
// Start session if not already started
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
// Check access
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true ||
empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
http_response_code(403);
exit;
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('kampfrichter');
verify_csrf();
// Validate POST input
if (!isset($_POST['abteilung'])) {

View File

@@ -2,24 +2,17 @@
use TCPDF;
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
// Show all errors except deprecation notices (these come from vendor libraries
// that aren't yet typed for newer PHP versions). Long-term fix: update
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
// Start session if not already started
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
// Check access
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true ||
empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
http_response_code(403);
exit;
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('kampfrichter');
verify_csrf();
// Validate POST input
/*

View File

@@ -1,19 +1,17 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
// Show all errors except deprecation notices (these come from vendor libraries
// that aren't yet typed for newer PHP versions). Long-term fix: update
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
header('Content-Type: application/json');
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('kampfrichter');
verify_csrf();
$type = 'kr';
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
@@ -26,8 +24,8 @@ if ($data['success'] === false){
require $baseDir . '/../scripts/db/db-tables.php';
// ---------- Get and sanitize input ----------
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$discipline = isset($_GET['discipline']) ? preg_replace('/[^a-zA-Z0-9 _-]/', '', $_GET['discipline']) : '';
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
$discipline = isset($_POST['discipline']) ? preg_replace('/[^a-zA-Z0-9 _-]/', '', $_POST['discipline']) : '';
if ($discipline !== 'boden') {
echo json_encode(['success' => false, 'message' => 'Invalid discipline']);

View File

@@ -2,9 +2,17 @@
header('Content-Type: application/json');
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('kampfrichter');
verify_csrf();
$discipline = 'boden';
$folder = realpath($baseDir . '/displays/json');

View File

@@ -2,21 +2,18 @@
header('Content-Type: application/json');
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
session_start();
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('kampfrichter');
verify_csrf();
$type = 'kr';
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -1,21 +1,17 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
session_start();
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
http_response_code(403);
exit;
}
header('Content-Type: application/json');
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('kampfrichter');
verify_csrf();
$type = 'kr';
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
@@ -120,6 +116,10 @@ try {
$geraete = db_select($mysqli, $tableGeraete, "id");
$programmName = db_get_var($mysqli, "SELECT `programm` FROM $tableTurnerinnen WHERE `id` = ?", [$person_id]);
$programmId = db_get_var($mysqli, "SELECT `id` FROM $tableProgramme WHERE `programm` = ?", [$programmName]);
// Alle Werte werden von der Datenbank geholt und werden, wenn nicht vorhanden, durch den Standartwert ersetzt.
$alleNoten = db_select($mysqli, $tableNotenBezeichnungen, "id, berechnung, default_value, nullstellen, pro_geraet, geraete_json, anzahl_laeufe_json");
@@ -132,9 +132,20 @@ $ascArrayGeraeteJSON = array_column($alleNoten, 'geraete_json', 'id');
$ascArrayAnzahlLaeufeJSON = array_column($alleNoten, 'anzahl_laeufe_json', 'id');
$ascArrayRechnungen = array_column($alleNoten, 'berechnung', 'id');
// $proGeraet = intval($calc['pro_geraet']) !== 1;
$mRunFunctions = [];
foreach ($abhaenigeRechnungen as $saRechnung) {
$sRechnung = $ascArrayRechnungen[$saRechnung[0]] ?? 0;
//var_dump($sRechnung);
$mRunCalc = $notenRechner->checkRunFunctions($sRechnung) ?? false;
if ($mRunCalc) {
$mRunFunctions[] = $saRechnung[0];
break;
}
}
$indexedNotenArray = [];
@@ -158,22 +169,72 @@ foreach ($noten as $sn) {
$alleNotenIds = array_column($alleNoten, 'id') ?? [];
foreach ($indexedNotenArray as $sG => $siNA) {
$existierendeNotenIds = array_keys($siNA) ?? [];
$nichtExistierendeNotenIds = array_diff($alleNotenIds, $existierendeNotenIds) ?? [];
foreach ($nichtExistierendeNotenIds as $neni) {
if (!isset($ascArrayDefaultValues[$neni])) { continue; }
if (intval($ascArrayProGeraet[$neni]) === 1 && intval($sG) === 0) { continue; }
if (intval($ascArrayProGeraet[$neni]) !== 1 && (!is_array($ascArrayGeraeteJSON[$neni]) || !in_array($sG, $ascArrayGeraeteJSON[$neni]))) { continue; }
// For non-existent notes, we fill all runs with default value
// We set Run 1 by default, and if more are configured, also those
$indexedNotenArray[$sG][$neni][1] = $ascArrayDefaultValues[$neni];
if (count($mRunFunctions) > 0) {
foreach ($indexedNotenArray as $sG => $siNA) {
// Check for more runs in config? (Actually, this might be overkill for defaults,
// but the calculator might need them)
foreach ($alleNotenIds as $neni) { // Use $neni as the ID
// 1. Skip if no default value is defined
if (!isset($ascArrayDefaultValues[$neni])) {
continue;
}
// 2. Logic Check: Is this note assigned to this device?
$isProGeraet = (int)($ascArrayProGeraet[$neni] ?? 0);
if ($isProGeraet === 1 && (int)$sG === 0) {
continue;
}
if ($isProGeraet !== 1) {
$allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
if (!is_array($allowedGeraete) || !in_array($sG, $allowedGeraete)) {
continue;
}
}
$runs = $ascArrayAnzahlLaeufeJSON[$neni][$sG][$programmId] ?? $ascArrayAnzahlLaeufeJSON[$neni]["default"] ?? 1;
for ($r = 1; $r <= $runs; $r++) {
if (isset($indexedNotenArray[$sG][$neni][$r])) {
continue;
}
$indexedNotenArray[$sG][$neni][$r] = $ascArrayDefaultValues[$neni];
}
}
}
} else {
foreach ($indexedNotenArray as $sG => $siNA) {
foreach ($alleNotenIds as $neni) { // Use $neni as the ID
// 1. Skip if value already exists for this specific run
if (isset($indexedNotenArray[$sG][$neni][$run_number])) {
continue;
}
// 2. Skip if no default value is defined
if (!isset($ascArrayDefaultValues[$neni])) {
continue;
}
// 3. Logic Check: Is this note assigned to this device?
$isProGeraet = (int)($ascArrayProGeraet[$neni] ?? 0);
if ($isProGeraet === 1 && (int)$sG === 0) {
continue;
}
if ($isProGeraet !== 1) {
$allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
if (!is_array($allowedGeraete) || !in_array($sG, $allowedGeraete)) {
continue;
}
}
// 4. Assign the default value
$indexedNotenArray[$sG][$neni][$run_number] = $ascArrayDefaultValues[$neni];
}
}
}
@@ -181,44 +242,51 @@ foreach ($indexedNotenArray as $sG => $siNA) {
$idsToSave = [];
foreach ($abhaenigeRechnungen as $sRechnung) {
if ($sRechnung[1] !== "A" && intval($sRechnung[1]) !== $gereat_id) { continue; }
$rechnung = $ascArrayRechnungen[$sRechnung[0]] ?? null;
$gereadIdArrays = ($sRechnung[1] === "A") ? $gereat_id : $sRechnung[1];
$targetNoteId = $sRechnung[0];
$isProGeraet = (intval($ascArrayProGeraet[$targetNoteId]) === 1);
$rechnungType = $sRechnung[1];
// 1. Initial Filter
if ($rechnungType !== "A" && intval($rechnungType) !== $gereat_id) continue;
$rechnung = $ascArrayRechnungen[$targetNoteId] ?? null;
if ($rechnung === null) {
echo json_encode(['success' => true, 'message' => "Fehler: Rechnung $targetNoteId nicht gefunden"]);
exit;
}
// 2. Determine Target Device ID
$isProGeraet = (intval($ascArrayProGeraet[$targetNoteId] ?? 0) === 1);
$allowedGeraete = $ascArrayGeraeteJSON[$targetNoteId] ?? [];
if ($isProGeraet) {
$gereadIdArrays = $gereat_id;
} elseif (in_array($gereat_id, $allowedGeraete)) {
$gereadIdArrays = $gereat_id;
if ($rechnungType === "A" || $isProGeraet || in_array($gereat_id, $allowedGeraete)) {
$targetGeraetKey = $gereat_id;
} else {
$gereadIdArrays = 0;
$targetGeraetKey = 0;
}
if ($rechnung === null) {
echo json_encode(['success' => true, 'message' => "Wert aktualisiert, Fehler: Rechnung" . $sRechnung[0] . "nicht gefunden"]);
// 3. Calculation Logic
$runsConfig = $ascArrayAnzahlLaeufeJSON[$targetNoteId] ?? [];
$runs = $runsConfig[$gereat_id][$programmId] ?? $runsConfig["default"] ?? 1;
$acrun = min($runs, $run_number);
if (in_array($targetNoteId, $mRunFunctions)) {
$calcResult = $notenRechner->berechneStringComplexRun($rechnung, $indexedNotenArray, $gereat_id, $programmId, $ascArrayAnzahlLaeufeJSON);
} else {
$calcResult = $notenRechner->berechneStringComplex($rechnung, $indexedNotenArray, $gereat_id, $acrun);
}
if (!($calcResult['success'] ?? false)) {
echo json_encode(['success' => true, 'message' => "Rechenfehler in $targetNoteId: " . ($calcResult['value'] ?? '')]);
exit;
}
$calcResult = $notenRechner->berechneStringComplex($rechnung, $indexedNotenArray, $gereat_id);
if ($calcResult['success'] !== true) {
echo json_encode(['success' => true, 'message' => "Wert aktualisiert, Rechenfehler: " . ($calcResult['value'] ?? '')]);
exit;
}
// Update the local array (Always Run 1 for calculations for now, UNLESS we want calculated runs?)
// Most calculations are "Total" points which have run_number = 1
$indexedNotenArray[$gereadIdArrays][$sRechnung[0]][1] = $calcResult['value'];
// Track that this ID needs to be written to the database (Target run is 1)
$updatedValues[$gereadIdArrays][$sRechnung[0]][1] = $calcResult['value'];
// 4. Update State
$val = $calcResult['value'];
$indexedNotenArray[$targetGeraetKey][$targetNoteId][$acrun] = $val;
$updatedValues[$targetGeraetKey][$targetNoteId][$acrun] = $val;
}
// Prepare the statement once
$sql = "INSERT INTO $tableNoten (`value`, `person_id`, `note_bezeichnung_id`, `geraet_id`, `jahr`, `run_number`)
VALUES (?, ?, ?, ?, ?, ?)

View File

@@ -1,93 +0,0 @@
<?php
session_start();
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1 || !isset($_SESSION['selectedFreigabeKampfrichter']) || $_SESSION['selectedFreigabeKampfrichter'] !== 'admin') {
http_response_code(403);
exit;
}
header('Content-Type: application/json');
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
$type = 'kr';
$data = require $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';
// ---------- Get and sanitize input ----------
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
$fieldType = isset($_POST['field_type']) ? preg_replace('/[^a-zA-Z0-9 _-]/', '', $_POST['field_type']) : '';
$discipline = isset($_POST['discipline']) ? preg_replace('/[^a-zA-Z0-9 _-]/', '', $_POST['discipline']) : '';
$value = isset($_POST['value']) ? floatval($_POST['value']) : 0;
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid ID']);
exit;
}
if (!isset($value) || floatval($value) < 0 || !isset($discipline) || $discipline === ''|| !isset($fieldType) || $fieldType === '') {
http_response_code(422);
exit;
}
if ($discipline === 'all') {
$column = $fieldType;
} else {
$column = $fieldType . ' ' . $discipline;
}
$excluded_columns = [
'id',
'name',
'vorname',
'bezahlt',
'bezahltoverride',
'geburtsdatum',
'programm',
'verein',
'bodenmusik'
];
$sql = "SHOW COLUMNS FROM `$tableTurnerinnen`";
$result = $mysqli->query($sql);
$all_columns = [];
while ($row = $result->fetch_assoc()) {
$all_columns[] = $row['Field'];
}
$allowed_columns = array_values(
array_diff($all_columns, $excluded_columns)
);
if (!in_array($column, $allowed_columns, true)) {
http_response_code(422);
exit;
}
$stmt = $mysqli->prepare("UPDATE `$tableTurnerinnen` SET `$column` = ? WHERE id = ?");
$stmt->bind_param("di", $value, $id);
if (!$stmt->execute()) {
http_response_code(500);
exit;
}
$stmt->close();
$mysqli->close();
http_response_code(200);
echo json_encode([
'success' => true,
'message' => 'Updated successfully'
]);
exit;

View File

@@ -1,20 +1,23 @@
<?php
header('Content-Type: application/json');
session_start();
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('kampfrichter');
verify_csrf();
// ---------- Get and sanitize input ----------
$id = intval($_POST['personId']) ?? 0;
$run = intval($_POST['run']) ?? 0;
$geraetId = intval($_POST['geraetId']) ?? 0;
$dataType = intval($_POST['dataType']) ?? 0;
$jahr = isset($_POST['jahr']) ? preg_replace('/[^0-9]/', '', $_POST['jahr']) : '';
$anfrageType = $_POST['type'] ?? '';
@@ -123,20 +126,28 @@ switch ($anfrageType) {
$jsonData = json_encode($data);
break;
case "start":
if (array_key_exists("start", $oldjson)) {
$oldjson["start"] = true;
$jsonData = json_encode($oldjson);
} else {
echo json_encode(['success' => false, 'message' => 'Turnerin nicht auf Display '.json_encode($oldjson).'; '.$jsonString]);
if (!array_key_exists("id", $oldjson) || intval($oldjson["id"]) !== $id || !array_key_exists("start", $oldjson)) {
echo json_encode(['success' => false, 'message' => 'Person nicht auf Display!']);
exit;
}
$oldjson["start"] = (bool) $dataType;
$jsonData = json_encode($oldjson);
break;
case "result":
// 1. Get IDs and filter out empty values
$noteLinksId = db_get_var($mysqli, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayIdNoteL']);
$noteRechtsId = db_get_var($mysqli, "SELECT `value` FROM $tableVar WHERE `name` = ?", ['displayIdNoteR']);
$stmt = $mysqli->prepare("UPDATE $tableNoten SET `is_public` = 1, `public_value` = `value` WHERE `person_id` = ? AND `jahr` = ? AND `geraet_id` = ? AND `run_number` = ?");
$stmt->bind_param("ssss", $id, $jahr, $geraetId, $run);
$stmt->execute();
$stmt->close();
// Create an array of IDs that actually exist
$validIds = array_filter([$noteLinksId, $noteRechtsId]);
@@ -148,12 +159,12 @@ switch ($anfrageType) {
$placeholders = implode(',', array_fill(0, count($validIds), '?'));
$sqlNoten = "SELECT `value`, `note_bezeichnung_id` FROM $tableNoten
WHERE person_id = ? AND `jahr` = ? AND `geraet_id` = ?
WHERE person_id = ? AND `jahr` = ? AND `geraet_id` = ? AND run_number = ?
AND `note_bezeichnung_id` IN ($placeholders)";
$stmt = $mysqli->prepare($sqlNoten);
// Combine standard params with our dynamic ID list
$params = array_merge([$id, $jahr, $geraetId], $validIds);
$params = array_merge([$id, $jahr, $geraetId, $run], $validIds);
$types = str_repeat('s', count($params));
$stmt->bind_param($types, ...$params);
$stmt->execute();

View File

@@ -1,115 +0,0 @@
<?php
header('Content-Type: application/json');
session_start();
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
$type = 'kr';
$data = require $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';
// ---------- Get and sanitize input ----------
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
$discipline = isset($_POST['discipline']) ? preg_replace('/[^a-zA-Z0-9 _-]/', '', $_POST['discipline']) : '';
$stmt = $mysqli->prepare("SELECT `name` FROM $tableGeraete ORDER BY start_index ASC");
if (!$stmt->execute()) {
http_response_code(500);
exit;
}
$result = $stmt->get_result();
$allowed_disciplines = array_map(
'strtolower',
array_column($result->fetch_all(MYSQLI_ASSOC), 'name')
);
$stmt->close();
if (!in_array($discipline, $allowed_disciplines)) {
echo json_encode(['success' => false, 'message' => 'Invalid discipline']);
exit;
}
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid ID']);
exit;
}
// ---------- Step 2: Get values from DB ----------
$result = $mysqli->query("SELECT * FROM `$tableTurnerinnen` WHERE id = $id");
$row = $result->fetch_assoc();
if (!$row) {
echo json_encode(['success' => false, 'message' => 'Row fetch failed']);
exit;
}
$folder = realpath($baseDir . '/displays/json');
if ($folder === false) {
echo json_encode([
'success' => false,
'message' => 'Could not find displays folder.'
]);
exit;
}
$filename = 'display_' . $discipline . '.json';
$filepath = $folder . '/' . $filename;
if (!is_writable($folder)) {
echo json_encode(['success' => false, 'message' => 'Folder not writable: ' . $folder]);
exit;
}
$jsonString = file_get_contents($filepath);
// decode JSON, fallback to empty array if invalid
$oldjson = json_decode($jsonString, true) ?? [];
if (array_key_exists("note", $oldjson) && array_key_exists("dnote", $oldjson)) {
$oldjson["note"] = (float)$row['note '.$discipline];
$oldjson["dnote"] = (float)$row['d-note '.$discipline];
} else {
echo json_encode([
'success' => false,
'message' => 'ERROR: JSON keys "note" or "dnote" do not exist'
]);
exit;
}
$jsonData = json_encode($oldjson);
// Write file
if (file_put_contents($filepath, $jsonData) === false) {
echo json_encode([
'success' => false,
'message' => 'Failed to write JSON file: ' . $filepath
]);
exit;
}
// ---------- Return JSON ----------
echo json_encode([
'success' => true,
'message' => 'JSON updated successfully for '.$discipline,
]);
exit;

View File

@@ -1,97 +0,0 @@
<?php
header('Content-Type: application/json');
session_start();
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
// ---------- Get and sanitize input ----------
$discipline = isset($_GET['discipline']) ? preg_replace('/[^a-zA-Z0-9 _-]/', '', $_GET['discipline']) : '';
$type = 'kr';
$data = require $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';
$stmt = $mysqli->prepare("SELECT `name` FROM $tableGeraete ORDER BY start_index ASC");
if (!$stmt->execute()) {
http_response_code(500);
exit;
}
$result = $stmt->get_result();
$allowed_disciplines = array_map(
'strtolower',
array_column($result->fetch_all(MYSQLI_ASSOC), 'name')
);
$stmt->close();
if (!in_array($discipline, $allowed_disciplines)) {
echo json_encode(['success' => false, 'message' => 'Invalid discipline']);
exit;
}
$folder = realpath($baseDir . '/displays/json');
if ($folder === false) {
echo json_encode([
'success' => false,
'message' => 'Could not find displays folder.'
]);
exit;
}
$filename = 'display_' . $discipline . '.json';
$filepath = $folder . '/' . $filename;
if (!is_writable($folder)) {
echo json_encode(['success' => false, 'message' => 'Folder not writable']);
exit;
}
$jsonString = file_get_contents($filepath);
// decode JSON, fallback to empty array if invalid
$oldjson = json_decode($jsonString, true) ?? [];
if (array_key_exists("start", $oldjson)) {
$oldjson["start"] = true;
$jsonData = json_encode($oldjson);
} else {
echo json_encode(['success' => false, 'message' => 'Turnerin nicht auf Display '.json_encode($oldjson).'; '.$jsonString]);
exit;
}
// Write file
if (file_put_contents($filepath, $jsonData) === false) {
echo json_encode([
'success' => false,
'message' => 'Failed to write JSON file'
]);
exit;
}
// ---------- Return JSON ----------
echo json_encode([
'success' => true,
'message' => 'JSON updated successfully for '.$discipline,
'disable_start_button' => true
]);
exit;

View File

@@ -1,122 +0,0 @@
<?php
header('Content-Type: application/json');
session_start();
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
$type = 'kr';
$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';
// ---------- Get and sanitize input ----------
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$discipline = isset($_GET['discipline']) ? preg_replace('/[^a-zA-Z0-9 _-]/', '', $_GET['discipline']) : '';
$stmt = $mysqli->prepare("SELECT `name` FROM $tableGeraete ORDER BY start_index ASC");
if (!$stmt->execute()) {
http_response_code(500);
exit;
}
$result = $stmt->get_result();
$allowed_disciplines = array_map(
'strtolower',
array_column($result->fetch_all(MYSQLI_ASSOC), 'name')
);
$stmt->close();
if (!in_array($discipline, $allowed_disciplines)) {
echo json_encode(['success' => false, 'message' => 'Invalid discipline']);
exit;
}
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid ID']);
exit;
}
// ---------- Step 2: Get values from DB ----------
$result = $mysqli->query("SELECT name, vorname, verein, programm FROM `$tableTurnerinnen` WHERE id = $id");
$row = $result->fetch_assoc();
if (!$row) {
echo json_encode(['success' => false, 'message' => 'Row fetch failed']);
exit;
}
$folder = realpath($baseDir . '/displays/json');
if ($folder === false) {
echo json_encode([
'success' => false,
'message' => 'Could not find displays folder. Tried: ' . __DIR__ . '/../displays'
]);
exit;
}
$filename = 'display_' . $discipline . '.json';
$filepath = $folder . '/' . $filename;
if (!is_writable($folder)) {
echo json_encode(['success' => false, 'message' => 'Folder not writable: ' . $folder]);
exit;
}
if (file_put_contents($filepath, $jsonData) === false) {
echo json_encode(['success' => false, 'message' => 'Failed to write file: ' . $filepath]);
exit;
}
$jsonString = file_get_contents($folder . $filename);
// decode JSON, fallback to empty array if invalid
$oldjson = json_decode($jsonString, true) ?? [];
// safely get value, default 0 if missing
$olduniqueid = $oldjson['uniqueid'] ?? 0;
$uniqueid = $olduniqueid + 1;
$data = ["note" => 'nan',
"dnote" => 'nan',
"id" => $id,
"name" => $row['name'],
"vorname" => $row['vorname'],
"programm" => $row['programm'],
"verein" => $row['verein'],
"start" => false,
"musik" => 'nan',
"uniqueid" => $uniqueid];
$jsonData = json_encode($data);
// Encode JSON with readable formatting
$jsonData = json_encode($data);
// Write file
if (file_put_contents($filepath, $jsonData) === false) {
echo json_encode([
'success' => false,
'message' => 'Failed to write JSON file: ' . $filepath
]);
exit;
}
// ---------- Return JSON ----------
echo json_encode([
'success' => true,
'message' => 'JSON updated successfully for '.$discipline,
'disable_turnerin_button' => true,
'enable_result_button' => true
]);
exit;

View File

@@ -1,160 +0,0 @@
<?php
session_start();
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
http_response_code(403);
exit;
}
//ini_set('display_errors', 1);
//ini_set('display_startup_errors', 1);
header('Content-Type: application/json');
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
$type = 'kr';
$data = require $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-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
$noten = db_select($mysqli, $tableNotenBezeichnungen, "id, berechnung, type");
// 1. Re-index the array so the keys match the database IDs
$notenById = array_column($noten, null, 'id');
$berechnungen = [];
foreach ($notenById as $id => $sn) {
if ($sn['type'] === 'berechnung') {
$berechnungen[] = $sn;
}
}
if (empty($berechnungen)) {
echo json_encode(['success' => true, 'message' => "Keine Berechnungen ausgewählt"]);
exit;
}
require $baseDir . "/../scripts/string-calculator/string-calculator-functions.php";
$notenRechner = new NotenRechner();
// 1. Build the direct map
// Format: [ Changed_Note_ID => [ "CalcId|GeraetId" => [CalcId, GeraetId] ] ]
$dependencyMap = [];
foreach ($berechnungen as $calc) {
$neededIdsArray = $notenRechner->getBenoetigteIdsComplex($calc['berechnung']);
if (empty($neededIdsArray)) {
continue;
}
$calcId = (int)$calc['id'];
foreach ($neededIdsArray as $needed) {
$nId = (int)$needed['noteId'];
// Keep geraetId as integer if it's a number (e.g., 3), otherwise string ('S')
$gId = is_numeric($needed['geraetId']) ? (int)$needed['geraetId'] : $needed['geraetId'];
// Create a unique string key so we don't store exact duplicates
$nodeKey = $calcId . '|' . $gId;
if (!isset($dependencyMap[$nId])) {
$dependencyMap[$nId] = [];
}
// Store it as the "little array" you requested: [DependentCalcId, GeraetId]
$dependencyMap[$nId][$nodeKey] = [$calcId, $gId];
}
}
// 2. Our recursive helper function (Updated for complex nodes)
function getCompleteDependencyChain($id, $directMap, $visited = [])
{
// If this ID doesn't have anything depending on it, return empty
if (!isset($directMap[$id])) {
return [];
}
$allDependencies = [];
foreach ($directMap[$id] as $nodeKey => $complexNode) {
// CIRCULAR DEPENDENCY CHECK:
// We check against the string key (e.g., "10|S") to prevent infinite loops
if (isset($visited[$nodeKey])) {
continue;
}
// 1. Mark this specific node as visited
$visited[$nodeKey] = true;
// 2. Add the little array [CalcId, GeraetId] to our master list
$allDependencies[$nodeKey] = $complexNode;
// 3. Recursively find everything that depends on THIS calculation ID
// $complexNode[0] is the dependent Calc ID
$childDependencies = getCompleteDependencyChain($complexNode[0], $directMap, $visited);
// 4. Merge the child results into our master list safely
foreach ($childDependencies as $childKey => $childNode) {
$allDependencies[$childKey] = $childNode;
$visited[$childKey] = true; // Ensure the parent loop knows this was visited
}
}
return $allDependencies;
}
// 3. Create the final flattened map for ALL IDs
$flatDependencyMap = [];
foreach (array_keys($notenById) as $id) {
$chain = getCompleteDependencyChain($id, $dependencyMap);
// Only add it if dependencies exist
if (!empty($chain)) {
// array_values() removes the "10|S" string keys, turning it into a perfect
// 0-indexed array for clean JSON encoding: [[10, "S"], [12, 3]]
$flatDependencyMap[$id] = array_values($chain);
}
}
// 4. Database Updates
// Step 1: Reset all rows to NULL in a single query
$resetSql = "UPDATE $tableNotenBezeichnungen SET `berechnung_json` = NULL";
$mysqli->query($resetSql);
// Step 2: Prepare the statement
$updateSql = "UPDATE $tableNotenBezeichnungen SET `berechnung_json` = ? WHERE id = ?";
$stmt = $mysqli->prepare($updateSql);
foreach ($flatDependencyMap as $id => $completeDependencyArray) {
if (empty($completeDependencyArray)) {
continue;
}
$jsonString = json_encode($completeDependencyArray);
// Bind parameters: 's' for string (JSON), 'i' for integer (ID)
$stmt->bind_param("si", $jsonString, $id);
$stmt->execute();
}
$stmt->close();
echo json_encode(['success' => true, 'message' => "Abhaengigkeiten berechnet"]);
exit;

View File

@@ -5,7 +5,7 @@ ini_set('display_startup_errors', 1);
session_start();
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['passcodekampfrichter_id']) || $_SESSION['passcodekampfrichter_id'] < 1) {
if (empty($_SESSION['access_granted_kampfrichter']) || $_SESSION['access_granted_kampfrichter'] !== true || empty($_SESSION['user_id_kampfrichter']) || $_SESSION['user_id_kampfrichter'] < 1) {
http_response_code(403);
exit;
}

View File

@@ -20,6 +20,7 @@ function toggleFullscreen() {
}
let messagePosArray = [];
const csrf_token = window.CSDR_TOKEN;
function displayMsg(type, msg) {
const colors = ["#900000ff", "#00b200ff"];
@@ -75,9 +76,15 @@ async function fetchNewWSToken(freigabe) {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({ access: freigabe })
body: new URLSearchParams({ access: freigabe, csrf_token })
});
if (response.status === 403) {
console.warn("Please Re-Autenithicate. Reloading page...");
location.reload();
return null;
}
if (!response.ok) return null;
const data = await response.json();
@@ -152,7 +159,39 @@ function scheduleRetry() {
// Start the initial connection attempt safely
startWebSocket();
function updateRunButtons(targetCount, personId, $container) {
if (targetCount === 0) { return; }
const geraetId = $container.find('.submit-display-result').first().data('geraet-id') || "";
const currentCount = $container.find('.submit-display-result').length;
if (targetCount > currentCount) {
for (let i = currentCount + 1; i <= targetCount; i++) {
const buttonHtml = `
<input type="button" class="submit-display-result"
data-person-id="${personId}"
data-geraet-id="${geraetId}"
data-run="${i}"
value="Ergebnis anzeigen (Run ${i})">`;
$container.append(buttonHtml);
}
$container.find('.submit-display-result[data-run="1"]').val('Ergebnis anzeigen (Run 1)');
} else if (targetCount < currentCount) {
for (let i = currentCount; i > targetCount; i--) {
$container.find(`.submit-display-result[data-run="${i}"]`).remove();
}
if (targetCount === 1 && $container.find('.submit-display-result').length === 1) {
$container.find('.submit-display-result').val('Ergebnis anzeigen');
}
}
$container.find('.submit-display-result').each(function() {
$(this).attr('data-person-id', personId);
});
}
$.fn.updateCurrentEdit = function() {
return this.each(function() {
@@ -183,7 +222,7 @@ $.fn.updateCurrentEdit = function() {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token: window.CSDR_TOKEN,
csrf_token,
editId: $input.attr('data-person-id'),
geraet: $input.attr('data-geraet-id') ?? null
})
@@ -196,10 +235,13 @@ $.fn.updateCurrentEdit = function() {
'color': '#209200ff',
'transition': 'all 0.3s ease-out'
});
setTimeout(() => $(".current-turnerin-name").css({
'color': ''
}), 2000);
$(".heading_fv_selturnerin").focus();
$(".div_edit_values_user").css("display", "flex");
$(".current-turnerin-name").text(response.titel);
@@ -212,86 +254,93 @@ $.fn.updateCurrentEdit = function() {
$(".submit-display-result").css("opacity", "1");
const $editAllDiv = $('.div_edit_values_all_gereate');
const noten = response.noten;
const programmId = response.programm_id;
const noten = response.noten;
const personId = response.id;
// First, reset all containers to a single input state and clear values
$editAllDiv.find('.note-container').each(function() {
const $container = $(this);
const $tbody = $container.find('tbody');
const $headerRow = $container.find('thead tr');
// 1. Loop directly through the 'noten' object
for (const [geraetId, disciplineData] of Object.entries(noten)) {
// Reset header
$headerRow.find('.run-num-header').remove();
// Find the specific DOM wrapper for this Geraet using the outer div
// Assuming your PHP renders the tables with the correct geraetId on the button
const $disciplineWrapper = $editAllDiv.find(`.submit-display-turnerin[data-geraet-id="${geraetId}"]`).closest('.all_vaules_div');
// Remove extra inputs beyond run 1
$tbody.find('.inputs-row').each(function() {
$(this).find('td:not(.input-cell-run-1)').remove();
if ($disciplineWrapper.length === 0) continue;
// --- UPDATE GENERAL BUTTONS FOR THIS GERAET ---
$disciplineWrapper.find(".submit-display-turnerin, .submit-display-start").attr({
'data-person-id': personId,
'data-geraet-id': geraetId
});
// Clear value of run 1
$container.find('input[data-run="1"]').val('').attr('data-person-id', response.id);
});
$disciplineWrapper.find(".submit-musik-start, .submit-musik-stopp").attr({
'data-id': personId,
'data-geraet': geraetId
});
// Now loop through the data and populate/expand
for (const [geraetId, noteGroup] of Object.entries(noten)) {
for (const [noteId, runGroup] of Object.entries(noteGroup)) {
const $container = $editAllDiv.find(`.note-container[data-note-id="${noteId}"]`);
if ($container.length === 0) continue;
// 2. Identify master containers for this specific discipline
const $masterContainer = $disciplineWrapper.find('.singleNotentable').first();
const $displayresultDiv = $disciplineWrapper.find('.div-submit-display-result');
// 3. CLEANUP: Remove previously generated runs and buttons
$disciplineWrapper.find('.singleNotentable').not(':first').remove();
$displayresultDiv.find('.submit-display-result').not(':first').remove();
const $tbody = $container.find('tbody');
const $headerRow = $container.find('thead tr');
const $inputsRow = $tbody.find('.inputs-row');
const runCount = Object.keys(runGroup).length;
const $originalResultBtn = $displayresultDiv.find('.submit-display-result').first();
const runKeys = Object.keys(disciplineData).sort((a, b) => a - b);
const totalRuns = runKeys.length;
$headerRow.find('.note-name-header .rm').remove();
console.log(totalRuns);
const originalText = $headerRow.find('.note-name-header').text().trim();
// 4. Process each Run in the data
runKeys.forEach(runNum => {
const runInt = parseInt(runNum);
let $currentRunContainer;
// If more than 1 run, add headers if not already present
if (runCount > 1 && $headerRow.find('.run-num-header').length === 0) {
$headerRow.find('.note-name-header').html(originalText + ' <span class="rm">(R1)</span>');
for (let r = 2; r <= runCount; r++) {
$headerRow.append(`<th class="run-num-header">${originalText} <span class="rm">(R${r})</span></th>`);
}
if (runInt === 1) {
$currentRunContainer = $masterContainer;
} else {
// CLONE the entire container for Run 2, 3, etc.
$currentRunContainer = $masterContainer.clone();
$currentRunContainer.addClass(`run-container-block run-${runNum}`);
$currentRunContainer.insertAfter($disciplineWrapper.find('.singleNotentable').last());
}
for (const [runNum, val] of Object.entries(runGroup)) {
let $input = $inputsRow.find(`input[data-run="${runNum}"][data-geraet-id="${geraetId}"]`);
// 5. Update all Tables and Inputs inside this Run Container
for (const [noteId, value] of Object.entries(disciplineData[runNum])) {
const $table = $currentRunContainer.find(`.note-container[data-note-id="${noteId}"]`);
// If input doesn't exist yet (for Run 2+), clone it
if ($input.length === 0) {
const $cell1 = $inputsRow.find('.input-cell-run-1');
const $newCell = $cell1.clone();
$newCell.removeClass('input-cell-run-1').addClass(`input-cell-run-${runNum}`);
$input = $newCell.find('input');
$input.attr('data-run', runNum).val(val ?? '');
$inputsRow.append($newCell);
// Re-bind change event to new input
//bindAjaxInput($input);
} else {
$input.val(val ?? '').attr('data-person-id', response.id);
// Update Header to show Run Number
if (runInt > 1) {
const $header = $table.find('.note-name-header');
if (!$header.find('.rm-tag').length) {
$header.append(` <span class="rm-tag" style="font-size: 0.8em;">(R${runNum})</span>`);
}
}
// Update Input attributes and value
const $input = $table.find('input');
$input.attr({
'data-run': runNum,
'data-person-id': personId,
'data-geraet-id': geraetId
}).val(value ?? '');
}
}
// 6. Remove tables cloned from Run 1 that don't exist in Run 2+
if (runInt > 1) {
$currentRunContainer.find('input[data-run="1"]').closest('.note-container').remove();
}
});
// Ensure the UI script tracking the buttons is updated last
updateRunButtons(totalRuns, personId, $displayresultDiv);
}
$(".submit-display-turnerin").attr('data-person-id', response.id);
$(".submit-display-start").attr('data-person-id', response.id);
const submitMusikStart = $(".submit-musik-start");
const submitMusikStopp = $(".submit-musik-stopp");
if (submitMusikStart.length > 0 && submitMusikStopp.length > 0){
submitMusikStart.attr('data-id', response.id);
submitMusikStopp.attr('data-id', response.id);
}
$(".submit-display-result").attr('data-person-id', response.id);
//$(".submit-display-result").attr('data-person-id', response.id);
} else {
displayMsg(0, response.message);
@@ -320,60 +369,63 @@ jQuery(document).ready(function($) {
$(this).updateCurrentEdit();
});
const $ajaxInputDiv = $('.div_edit_values_all_gereate');
$ajaxInputDiv.on('change', '.ajax-input', function(e) {
const start = performance.now();
const $input = $(this);
const url = `/intern/scripts/kampfrichter/ajax/ajax-update_value_kampfrichter.php`;
function bindAjaxInput($el) {
$el.on('change', function() {
const start = performance.now();
const $input = $(this);
const url = `/intern/scripts/kampfrichter/ajax/ajax-update_value_kampfrichter.php`;
personId = $input.data('person-id');
fieldTypeId = $input.data('field-type-id');
gereatId = $input.data('geraet-id');
runNum = $input.attr('data-run') || 1;
jahr = window.AKTUELLES_JAHR;
value = $input.val();
personId = $input.data('person-id');
fieldTypeId = $input.data('field-type-id');
gereatId = $input.data('geraet-id');
runNum = $input.attr('data-run') || 1;
jahr = window.AKTUELLES_JAHR;
value = $input.val();
fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
personId: personId,
fieldTypeId: fieldTypeId,
gereatId: gereatId,
run: runNum,
jahr: jahr,
value: value
})
fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
personId: personId,
fieldTypeId: fieldTypeId,
gereatId: gereatId,
run: runNum,
jahr: jahr,
value: value
})
.then(res => res.json())
.then(response => {
const end = performance.now();
console.log(`Total AJAX time: ${(end - start).toFixed(3)} ms`);
if (response.success) {
})
.then(res => res.json())
.then(response => {
const end = performance.now();
console.log(`Total AJAX time: ${(end - start).toFixed(3)} ms`);
if (response.success) {
let objValues = [];
const rowId = $input.attr('data-id');
$input.css({"color": "#0e670d", "font-weight": "600"});
setTimeout(() => $input.css({'color': '', "font-weight": ""}), 2000);
const noten = response.noten;
for (const [keyN, noteGroup] of Object.entries(noten)) {
for (const [key, runGroup] of Object.entries(noteGroup)) {
if (key == fieldTypeId && keyN == gereatId) { continue; }
for (const [run, value] of Object.entries(runGroup)) {
$(`input.changebleValue[data-field-type-id="${key}"][data-geraet-id="${keyN}"][data-person-id="${personId}"][data-run="${run}"]`)
const selectorBase = `[data-field-type-id="${key}"][data-geraet-id="${keyN}"][data-person-id="${personId}"][data-run="${run}"]`;
// Handle Inputs (excluding current one)
$(`input.changebleValue${selectorBase}`)
.not(this)
.val(value ?? '');
$(`.changebleValue:not(input)[data-field-type-id="${key}"][data-geraet-id="${keyN}"][data-person-id="${personId}"][data-run="${run}"]`)
// Handle Display elements (Spans/Divs)
$(`.changebleValue:not(input)${selectorBase}`)
.text(value ?? '');
}
}
@@ -389,101 +441,20 @@ jQuery(document).ready(function($) {
noten: noten
}
}));
} else {
// Flash red on error
$input.css({'color': '#ff6a76ff'});
displayMsg(0, response.message || 'Unknown error');
console.error(response.message || 'Unknown error');
}
})
.catch(err => {
$input.css({'color': '#670d0d'});
console.error('AJAX fetch error:', err);
});
});
}
$('.ajax-input').each(function() {
bindAjaxInput($(this));
} else {
// Flash red on error
$input.css({'color': '#ff6a76ff'});
displayMsg(0, response.message || 'Unknown error');
console.error(response.message || 'Unknown error');
}
})
.catch(err => {
$input.css({'color': '#670d0d'});
console.error('AJAX fetch error:', err);
});
});
/*$('.ranglisteExport').on('click', function(e) {
const $input = $(this);
if ($input.data('field_type') !== 'upload_programm') {e.preventDefault();}
// Build the data to send
const data = new URLSearchParams();
data.append('prog', $input.data('id'));
data.append('type', $input.data('field_type'));
// Record start time
const start = performance.now();
const url = '/intern/scripts/kampfrichter/ajax/ajax-neu_rangliste.php';
fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
prog: $input.data('id'),
type: $input.data('field_type')
})
})
.then(res => res.blob())
.then(blob => {
if ($input.data('field_type') !== 'upload_programm'){
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = "KTBB_Ergebnisse.pdf"; // optional
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
} else {
alert('PDF auf Webseite geladen!');
}
});
});
$('.protokollExport').on('click', function() {
console.log('ok');
const $input = $(this);
// Build the data to send
const data = new URLSearchParams();
data.append('abteilung', $input.data('abteilung'));
// Record start time
const start = performance.now();
const url = '/intern/scripts/kampfrichter/ajax/ajax-neu_protokoll.php';
fetch(url, {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
abteilung: $input.data('abteilung')
})
})
.then(res => res.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = "KTBB_Protokoll.pdf"; // optional
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
});
});*/
$('.inputnamekr').on('change', function() {
const $input = $(this);
@@ -494,6 +465,7 @@ jQuery(document).ready(function($) {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
aufgabe: $input.data('id'),
abteilung: $input.data('abt'),
geraet: $input.data('user'),
@@ -534,50 +506,6 @@ jQuery(document).ready(function($) {
});
/**
* Handle namekr input updates
$('.ajax-input-namekr').on('change', function() {
let $input = $(this);
$.post(ajax_object.ajaxurl, {
action: 'save_namekr_input',
id: $input.data('id'),
abt: $input.data('abt'),
user: $input.data('user'),
value: $input.val()
}, function(response) {
if (response.success) {
console.log(response.data.message);
$input.css({
'background-color': '#a4bf4a',
'color': '#fff',
'transition': 'all 0.3s ease-out'
});
setTimeout(() => $input.css({
'background-color': '',
'color': ''
}), 2000);
} else {
console.error(response.data.message);
$input.css({
'background-color': '#f8d7da',
'color': '#fff',
'transition': 'all 0.3s ease-out'
});
setTimeout(() => $input.css({
'background-color': '',
'color': ''
}), 2000);
}
}, 'json');
}); */
/**
* Handle display JSON updates
*/
$('.submit-display-turnerin').on('click', function() {
const $input = $(this);
@@ -588,6 +516,7 @@ jQuery(document).ready(function($) {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
personId: $input.attr('data-person-id'),
geraetId: $input.attr('data-geraet-id'),
jahr: window.AKTUELLES_JAHR,
@@ -623,12 +552,16 @@ jQuery(document).ready(function($) {
const $input = $(this);
const url = '/intern/scripts/kampfrichter/ajax/displays/ajax-display-functions.php';
const dataType = $input.attr('data-type');
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
geraetId: $input.attr('data-geraet-id'),
personId: $input.attr('data-person-id'),
dataType: dataType,
type: "start"
})
})
@@ -643,11 +576,16 @@ jQuery(document).ready(function($) {
data: response.data
}
}));
displayMsg(1, 'Start freigegeben');
$input.css('opacity', 0.5);
if (dataType == 1) {
displayMsg(1, 'Start freigegeben');
} else if (dataType == 0) {
displayMsg(1, 'Startfreigabe entzogen');
}
} else {
alert('Error: ' + response.message);
displayMsg(0, response.message);
}
})
.catch(err => {
@@ -656,48 +594,23 @@ jQuery(document).ready(function($) {
console.error('AJAX fetch error:', err);
});
});
/*$('.submit-display-start').on('click', function() {
let discipline = $(this).data('discipline');
$.post(ajax_object.ajaxurl, {
action: 'write_discipline_json_start',
discipline: discipline
}, function(response) {
if (response.success) {
alert('Start freigegeben');
if (response.data.disable_start_button) {
$('.submit-display-start').css({
'border': '1px solid #aaa',
'background-color': '#aaa',
'color': '#555',
'pointer-events': 'none'
});
$('.submit-musik-start').css({
'background-color': '#077',
'border': '1px solid #077',
'color': '#fff',
'cursor': 'pointer',
'pointer-events': 'auto'
});
}
} else {
alert('Error: ' + response.data.message);
}
}, 'json');
});*/
$('.submit-musik-start').on('click', function() {
const $input = $(this);
// Build the URL with GET parameters safely
const url = `/intern/scripts/kampfrichter/ajax/ajax-update_kampfrichter_start_musik.php` +
`?id=${$input.attr('data-id')}` +
`&discipline=${encodeURIComponent($input.data('geraet'))}`;
const url = `/intern/scripts/kampfrichter/ajax/ajax-update_kampfrichter_start_musik.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
id: $input.attr('data-id'),
discipline: $input.data('geraet')
})
})
.then(res => res.json())
.then(response => {
const end = performance.now();
@@ -725,7 +638,13 @@ jQuery(document).ready(function($) {
// Build the URL with GET parameters safely
const url = `/intern/scripts/kampfrichter/ajax/ajax-update_kampfrichter_stopp_musik.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token
})
})
.then(res => res.json())
.then(response => {
if (response.success) {
@@ -745,7 +664,7 @@ jQuery(document).ready(function($) {
});
});
$('.submit-display-result').on('click', function() {
$('.div-submit-display-result').on('click', '.submit-display-result', function() {
$input = $(this);
// Build the URL with GET parameters safely
@@ -755,8 +674,10 @@ jQuery(document).ready(function($) {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
personId: $input.attr('data-person-id'),
geraetId: $input.attr('data-geraet-id'),
run: $input.attr("data-run"),
jahr: window.AKTUELLES_JAHR,
type: "result"
})
@@ -843,34 +764,3 @@ ws.addEventListener("message", event => { // Use 'event' as it's more standard t
}
}
});
/*document.getElementById('freigabe-select').addEventListener('change', function() {
const freigabe = this.value;
const user_id = document.getElementById('user_id').value;
const nonce = document.getElementById('freigabe_nonce').value;
const type = document.getElementById('type_freigabe').value;
const params = new URLSearchParams();
params.append('action', 'save_freigabe');
params.append('freigabe', freigabe);
params.append('user_id', user_id);
params.append('type', type);
fetch('/intern/scripts/kampfrichter/ajax/ajax-update_selected_kampfrichter.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params
})
.then(res => res.json())
.then(data => {
if (data.success) {
window.location.reload();
} else {
alert('Error: ' + data.data);
}
})
.catch(err => {
console.error(err);
displayMsg(0, 'AJAX fetch error:' + err);
});
});*/

View File

@@ -0,0 +1,167 @@
<?php
use Dotenv\Dotenv;
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();
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 json_encode(['success' => false, 'message' => 'Critical DB Error.']);
exit;
}
$editor_id = $_SESSION['user_id_wk_leitung'];
$plain = trim($_POST['password'] ?? null);
$username = trim($_POST['username'] ?? null);
$namePerson = htmlspecialchars(trim($_POST['namePerson'] ?? null));
$freigaben = $_POST['freigaben'] ?? [];
$freigabenTrainer = $_POST['freigabenTrainer'] ?? [];
$freigabenKampfrichter = $_POST['freigabenKampfrichter'] ?? [];
if (!is_array($freigaben)) {
$freigaben = [];
}
if (!is_array($freigabenTrainer)) {
$freigabenTrainer = [];
}
if (!is_array($freigabenKampfrichter)) {
$freigabenKampfrichter = [];
}
$array = [
'types' => $freigaben,
'freigabenTrainer' => $freigabenTrainer,
'freigabenKampfrichter' => $freigabenKampfrichter
];
// Store as proper JSON string
$freigabe_store = json_encode($array);
$hash = null;
$cipher_store = null;
if ($plain != null) {
// Hash for login
$hash = password_hash($plain, PASSWORD_ARGON2ID);
require $baseDir . '/../composer/vendor/autoload.php';
$envFile = realpath($baseDir . '/../config/.env.pw-encryption-key');
if ($envFile === false) {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => "Environment file not found"
]);
exit;
}
try {
$envDir = dirname($envFile);
$dotenv = Dotenv::createImmutable($envDir, '.env.pw-encryption-key');
$dotenv->load();
} catch (Throwable $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => "Dotenv error"
]);
}
// Encrypt for display
$iv_length = openssl_cipher_iv_length('aes-256-cbc');
$iv = random_bytes($iv_length);
$encrypted = openssl_encrypt($plain, 'aes-256-cbc', $_ENV['PW_ENCRYPTION_KEY'], 0, $iv);
$cipher_store = base64_encode($iv . $encrypted);
}
$created_at = date('Y-m-d H:i:s');
$updated_at = $created_at;
$stmt = $mysqli->prepare(
"INSERT INTO {$tableInternUsers}
(username, name_person, password_hash, password_cipher, freigabe, created_at, updated_at, edited_by)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
);
$stmt->bind_param(
"sssssssi",
$username,
$namePerson,
$hash,
$cipher_store,
$freigabe_store,
$created_at,
$updated_at,
$editor_id
);
$updated = $stmt->execute();
if (!$updated) {
echo json_encode(['success' => false, 'message' => 'DB Error']);
exit;
}
$new_id = $mysqli->insert_id;
// Delete old OTL links for this user (recommended)
db_delete($mysqli, $tableOTL, ['user_id' => $new_id]);
// Insert the row — url + timestamp are auto-generated by MySQL
$typeOp = "create_profile";
$stmt = $mysqli->prepare("INSERT INTO {$tableOTL} (user_id, `type`) VALUES (?, ?)");
$stmt->bind_param("is", $new_id, $typeOp);
if (!$stmt->execute()) {
echo json_encode(['success' => false, 'message' => 'Failed to create OTL record']);
exit;
}
$row_id = $stmt->insert_id;
$stmt->close();
// Now fetch the auto-generated URL
$url = db_get_var($mysqli, "SELECT url FROM $tableOTL WHERE id = ? LIMIT 1", [$row_id]);
if (!$url) {
echo json_encode(['success' => false, 'message' => 'Could not fetch generated URL']);
exit;
}
echo json_encode(['success' => true, 'url' => $url]);

View File

@@ -1,20 +1,21 @@
<?php
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 1 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'wkl';
@@ -27,6 +28,15 @@ if ($dbconnection['success'] !== true){
}
$id = intval($_POST['user_id'] ?? 0);
$typeOp = trim($_POST['type'] ?? '');
$allowedTypesOp = ['login', 'pwreset'];
if (!in_array($typeOp, $allowedTypesOp)) {
echo json_encode(['success' => false, 'message' => 'Operation nicht gestattet']);
exit;
}
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'No valid ID']);
exit;
@@ -37,8 +47,8 @@ db_delete($mysqli, $tableOTL, ['user_id' => $id]);
// Insert the row — url + timestamp are auto-generated by MySQL
$stmt = $mysqli->prepare("INSERT INTO {$tableOTL} (user_id) VALUES (?)");
$stmt->bind_param("i", $id);
$stmt = $mysqli->prepare("INSERT INTO {$tableOTL} (user_id, `type`) VALUES (?, ?)");
$stmt->bind_param("is", $id, $typeOp);
if (!$stmt->execute()) {

View File

@@ -0,0 +1,39 @@
<?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();
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 json_encode(['success' => false, 'message' => 'Critical DB Error.']);
exit;
}
$id = intval($_POST['field_id'] ?? 0);
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid Input.']);
exit;
}
db_delete($mysqli, $tableInternUsers, ['id' => $id]);
echo json_encode(['success' => true, 'message' => "Benutzer $id erfolgreich gelöscht.", 'id' => $id]);
exit;

View File

@@ -0,0 +1,36 @@
<?php
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 = intval($_POST['field_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;
}
db_delete($mysqli, $tableVereine, ['id' => $id]);
echo json_encode(['success' => true, 'message' => 'Verein gelöscht']);

View File

@@ -1,24 +1,18 @@
<?php
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
}
$token = isset($_GET['token']) ? $_GET['token'] : '';
if ($token !== 'sWZ4GxbsoVhUPk5zhjH0uU9hets3zV2KsV8CZUvAWCCRk4uuuDr9vfFVgxWqr5FtDttbtm50EdWK9YxuMPswGZBQZFHAUAET1aG1'){
echo json_encode(['success' => false, 'message' => '500 Error - Critical Server Error']);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$type = 'wkl';
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
@@ -30,7 +24,7 @@ if ($data['success'] === false){
require $baseDir . '/../scripts/db/db-tables.php';
$value = isset($_GET['value']) ? preg_replace('/[^a-zA-Z0-9\s\-"]/u', '', $_GET['value']) : '';
$value = isset($_POST['value']) ? preg_replace('/[^a-zA-Z0-9\s\-"]/u', '', $_POST['value']) : '';
if (!$value || $value === ''){
echo json_encode(['success' => false, 'message' => 'No input']);

View File

@@ -5,24 +5,18 @@ ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
}
$token = isset($_GET['token']) ? $_GET['token'] : '';
if ($token !== 'bKqBAPjwojZdarJaE7jwvRrIEf2WzJUlFlufQadfLJ98qJcrWZK5pRlGoUQOHp1L06urGRbEdE9v5oIRirPiUCjm93wATghO4qx'){
echo json_encode(['success' => false, 'message' => '500 Error - Critical Server Error']);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$type = 'wkl';
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
@@ -34,7 +28,7 @@ if ($data['success'] === false){
require $baseDir . '/../scripts/db/db-tables.php';
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid ID']);

View File

@@ -4,21 +4,20 @@ use Dotenv\Dotenv;
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 1 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'wkl';
@@ -36,7 +35,7 @@ if (isset($_POST['field_id'])){
exit;
}
$editor_id = $_SESSION['passcodewk_leitung_id'];
$editor_id = $_SESSION['user_id_wk_leitung'];
$plain = trim($_POST['password'] ?? '');
if (!$plain) {
@@ -51,6 +50,7 @@ if (!$username) {
exit;
}
$namePerson = htmlspecialchars(trim($_POST['namePerson'] ?? ''));
$freigaben = $_POST['freigaben'] ?? [];
$freigabenTrainer = $_POST['freigabenTrainer'] ?? [];
@@ -118,6 +118,7 @@ if ($id > 0) {
'password_hash' => $hash,
'password_cipher' => $cipher_store,
'username' => $username,
'name_person' => $namePerson,
'freigabe' => $freigabe_store,
'updated_at' => date('Y-m-d H:i:s'),
'edited_by' => $editor_id
@@ -125,19 +126,23 @@ if ($id > 0) {
} else {
$stmt = $mysqli->prepare(
"INSERT INTO {$tableInternUsers}
(username, password_hash, password_cipher, freigabe, created_at, updated_at, edited_by)
VALUES (?, ?, ?, ?, ?, ?, ?)"
(username, name_person, password_hash, password_cipher, freigabe, created_at, updated_at, edited_by, login_active)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
$loginActive = 1;
$stmt->bind_param(
"ssssssi",
"sssssssis",
$username,
$namePerson,
$hash,
$cipher_store,
$freigabe_store,
$created_at,
$updated_at,
$editor_id
$editor_id,
$loginActive
);
$created_at = date('Y-m-d H:i:s');

View File

@@ -1,25 +1,18 @@
<?php
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 1 ) {
http_response_code(403);
exit;
}
$token = isset($_GET['token']) ? $_GET['token'] : '';
if ($token !== '0UgBVHutbxTRTYsB04ujFKMjMRA8GgdqRJjVh3DKU1LRJfwtcDfrpDc7jpMxcrg9rYurAEwYPy5gu15R77MsgKsDMkFZEykx0A67'){
echo json_encode(['success' => false, 'message' => '500 Error - Critical Server Error']);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$type = 'wkl';
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
@@ -32,8 +25,8 @@ if ($data['success'] === false){
require $baseDir . '/../scripts/db/db-tables.php';
// ---------- Get and sanitize input ----------
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$value = isset($_GET['value']) ? floatval($_GET['value']) : 0;
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
$value = isset($_POST['value']) ? floatval($_POST['value']) : 0;
if ($id < 0) {

View File

@@ -1,25 +1,18 @@
<?php
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
}
$token = isset($_GET['token']) ? $_GET['token'] : '';
if ($token !== 'k7uweziEUWZiJhwe7687UWIQZ28SQIH2ug74pINKyxHxPerB6wUZ'){
echo json_encode(['success' => false, 'message' => '500 Error - Critical Server Error']);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$type = 'wkl';
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
@@ -32,8 +25,8 @@ if ($data['success'] === false){
require $baseDir . '/../scripts/db/db-tables.php';
// ---------- Get and sanitize input ----------
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$value = isset($_GET['value']) ? round(floatval($_GET['value']), 2) : 0;
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
$value = isset($_POST['value']) ? round(floatval($_POST['value']), 2) : 0;
if ($id < 0) {

View File

@@ -2,20 +2,20 @@
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 1 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'wkl';

View File

@@ -1,46 +0,0 @@
<?php
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 1 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true){
echo json_encode(['success' => false, 'message' => 'Critical DB Error.']);
exit;
}
$id = intval($_POST['field_id'] ?? 0);
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'Invalid Input.']);
exit;
}
$deleted = db_delete($mysqli, $tableInternUsers, ['id' => $id]);
if ($deleted !== true) {
// DB query failed (syntax/connection issue)
echo json_encode(['success' => false, 'message' => 'DB Error.']);
exit;
} else {
// Success
echo json_encode(['success' => true, 'message' => "Benutzer $id erfolgreich gelöscht.", 'id' => $id]);
exit;
}

View File

@@ -1,36 +0,0 @@
<?php
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
}
$id = intval($_POST['field_id'] ?? 0);
if ($id <= 0) {
echo json_encode(['success' => false, 'message' => 'No valid ID']);
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true){
echo 'Critical DB Error.';
exit;
}
if (!db_delete($mysqli, $tableVereine, ['id' => $id])) {
echo json_encode(['success' => false, 'message' => 'Failed to delete verein']);
exit;
}
echo json_encode(['success' => true, 'message' => '200, ok']);

View File

@@ -1,17 +1,18 @@
<?php
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$type = 'wkl';
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -1,17 +1,18 @@
<?php
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$type = 'wkl';
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -7,17 +7,18 @@ ini_set('display_startup_errors', 1);
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -7,13 +7,18 @@ ini_set('display_startup_errors', 1);
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
// Validate input
if (!isset($_POST['anz_abt']) || !ctype_digit($_POST['anz_abt'])) {
http_response_code(406);
@@ -22,10 +27,6 @@ if (!isset($_POST['anz_abt']) || !ctype_digit($_POST['anz_abt'])) {
$anz_abt = (int) $_POST['anz_abt'];
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -8,13 +8,18 @@ ini_set('display_startup_errors', 1);
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
// Validate input
if (!isset($_POST['abt']) || !ctype_digit($_POST['abt'])) {
http_response_code(406);
@@ -23,10 +28,6 @@ if (!isset($_POST['abt']) || !ctype_digit($_POST['abt'])) {
$abtInput = (int) $_POST['abt'];
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -1,19 +1,20 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
if ($dbconnection['success'] !== true){
@@ -23,7 +24,7 @@ if ($dbconnection['success'] !== true){
require $baseDir . '/../scripts/db/db-tables.php';
$input = json_decode(file_get_contents('php://input'), true);
$input = $_POST;
if (!$input || !isset($input['new'])) {
http_response_code(400);

View File

@@ -1,16 +1,17 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
verify_csrf();
$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -40,11 +40,11 @@ $icons = [
if (isset($mysqli) && isset($tableInternUsers)) {
if ($currentPage === 'kampfrichter' && checkIfUserHasSessionId('kampfrichter')):
$userDispId = intval($_SESSION['passcodekampfrichter_id']);
$userDispId = intval($_SESSION['user_id_kampfrichter']);
elseif ($currentPage === 'kampfrichter' && checkIfUserHasSessionId('trainer')):
$userDispId = intval($_SESSION['passcodetrainer_id']);
$userDispId = intval($_SESSION['user_id_trainer']);
elseif ($isWKL && checkIfUserHasSessionId('wk_leitung')):
$userDispId = intval($_SESSION['passcodewk_leitung_id']);
$userDispId = intval($_SESSION['user_id_wk_leitung']);
endif;
$sql = "SELECT `username`, `freigabe` FROM $tableInternUsers WHERE id = ?";
@@ -87,7 +87,7 @@ if ($isWKL) {
}
function checkIfUserHasSessionId($type) : bool {
if (isset($_SESSION['passcode'.$type.'_id']) && intval(['passcode'.$type.'_id']) > 0) { return true; }
if (isset($_SESSION['user_id_'.$type]) && intval(['user_id_'.$type]) > 0) { return true; }
else { return false; }
}
@@ -181,6 +181,8 @@ function sidebarRender(string $mode) {
<script>
window.CSRF_TOKEN = "<?= $csrf_token ?? $_SESSION['csrf_token'] ?? '' ?>";
const siteType = '<?= $currentPage ?>';
// Close button binding (inline to avoid race condition with sidebar.js)
document.addEventListener('DOMContentLoaded', function() {

View File

@@ -1,14 +1,15 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if ( empty($_SESSION['access_granted_trainer']) || $_SESSION['access_granted_trainer'] !== true || empty($_SESSION['passcodetrainer_id']) || intval($_SESSION['passcodetrainer_id']) < 1 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('trainer');
verify_csrf();
$type = 'tr';
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
@@ -20,8 +21,8 @@ if ($data['success'] === false){
require $baseDir . '/../scripts/db/db-tables.php';
$ids = isset($_GET['ids']) ? htmlspecialchars(strip_tags(trim($_GET['ids'])), ENT_QUOTES) : '';
$user = intval($_SESSION['passcodetrainer_id']);
$ids = isset($_POST['ids']) ? htmlspecialchars(strip_tags(trim($_POST['ids'])), ENT_QUOTES) : '';
$user = intval($_SESSION['user_id_trainer']);
$arrayids = array_filter(array_map('trim', explode(',', $ids)));

View File

@@ -1,21 +1,18 @@
<?php
header('Content-Type: application/json');
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_trainer']) || $_SESSION['access_granted_trainer'] !== true || empty($_SESSION['passcodetrainer_id']) || intval($_SESSION['passcodetrainer_id']) < 1 ) {
http_response_code(403);
exit;
}
$userId = $_SESSION['passcodetrainer_id'];
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('trainer');
verify_csrf();
$userId = $_SESSION['user_id_trainer'];
$type = 'tr';
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -5,21 +5,17 @@ ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
$token = isset($_GET['token']) ? $_GET['token'] : '';
require_once $baseDir . '/../scripts/session_functions.php';
/*if ($token !== 'OOlhSGI8CraW6BFmJbj6JFy4sxrYyZ0UxzzbASLhY1sWm0IgqmBXjqqwtqKSvpVFBSBgOFrXHuQLGQj1pxlxj3rlTt1r7kAAWX67dcP'){
echo json_encode(['success' => false, 'message' => '500 Error - Critical Server Error']);
exit;
}*/
ini_wkvs_session();
if (empty($_SESSION['access_granted_trainer']) || $_SESSION['access_granted_trainer'] !== true || empty($_SESSION['passcodetrainer_id']) || intval($_SESSION['passcodetrainer_id']) < 1 ) {
http_response_code(403);
exit;
}
check_user_permission('trainer');
function generateInvoiceNumber(): int {
verify_csrf();
function generateInvoiceNumber() : int {
return random_int(10000000, 99999999);
}
@@ -59,9 +55,7 @@ function createInvoice(mysqli $conn, $tableOrders, $orderType , $preis, $userId,
throw new RuntimeException('Failed to generate unique invoice number');
}
$userId = $_SESSION['passcodetrainer_id'];
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
$userId = $_SESSION['user_id_trainer'];
$type = 'tr';

View File

@@ -1,16 +1,17 @@
<?php
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if ( empty($_SESSION['access_granted_trainer']) || $_SESSION['access_granted_trainer'] !== true || empty($_SESSION['passcodetrainer_id']) || intval($_SESSION['passcodetrainer_id']) < 1 ) {
http_response_code(403);
exit;
}
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('trainer');
verify_csrf();
$type = 'tr';
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';
@@ -24,7 +25,7 @@ require $baseDir . '/../scripts/db/db-tables.php';
// --- Get input ---
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
$userId = intval($_SESSION['passcodetrainer_id']);
$userId = intval($_SESSION['user_id_trainer']);
// --- Validate inputs ---
if ($id < 1) {

View File

@@ -2,18 +2,15 @@
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
$isTrainer =
isset($_SESSION['access_granted_trainer'], $_SESSION['passcodetrainer_id']) &&
$_SESSION['access_granted_trainer'] === true &&
(int)$_SESSION['passcodetrainer_id'] > 0;
require_once $baseDir . '/../scripts/session_functions.php';
if (!$isTrainer) {
echo json_encode(['success' => false]);
http_response_code(403);
exit;
}
ini_wkvs_session();
check_user_permission('trainer');
verify_csrf();
if (!isset($_POST['musicId']) || !isset($_POST['turnerinId']) || intval($_POST['musicId']) < 1 || intval($_POST['turnerinId']) < 1) {
echo json_encode(['success' => false]);
@@ -21,8 +18,6 @@ if (!isset($_POST['musicId']) || !isset($_POST['turnerinId']) || intval($_POST['
exit;
}
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
$type = 'tr';
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -1,17 +1,14 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
$isTrainer =
isset($_SESSION['access_granted_trainer'], $_SESSION['passcodetrainer_id']) &&
$_SESSION['access_granted_trainer'] === true &&
(int)$_SESSION['passcodetrainer_id'] > 0;
require_once $baseDir . '/../scripts/session_functions.php';
if (!$isTrainer) {
echo json_encode(['success' => false]);
http_response_code(403);
exit;
}
ini_wkvs_session();
check_user_permission('trainer');
verify_csrf();
if (!isset($_POST['oldMusicId'])) {
echo json_encode(['success' => false]);
@@ -27,8 +24,6 @@ if ($oldMusicId < 1) {
exit;
}
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
$type = 'tr';
$data = include $baseDir . '/../scripts/db/db-verbindung-script.php';

View File

@@ -2,7 +2,7 @@
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_trainer']) || $_SESSION['access_granted_trainer'] !== true || empty($_SESSION['passcodetrainer_id']) || $_SESSION['passcodetrainer_id'] < 1) {
if (empty($_SESSION['access_granted_trainer']) || $_SESSION['access_granted_trainer'] !== true || empty($_SESSION['user_id_trainer']) || $_SESSION['user_id_trainer'] < 1) {
http_response_code(403);
exit;
}

View File

@@ -4,11 +4,6 @@ use Sprain\SwissQrBill\PaymentPart\Output\DisplayOptions;
use Sprain\SwissQrBill\PaymentPart\Output\TcPdfOutput\TcPdfOutput;
use TCPDF;
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
require $baseDir . '/../composer/vendor/autoload.php';
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
// Show all errors except deprecation notices (these come from vendor libraries
@@ -18,10 +13,20 @@ error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
// Add a higher memory limit
ini_set('memory_limit', '256M'); // Start with 256M, increase if needed
session_start();
if (!isset($baseDir)) $baseDir = $_SERVER['DOCUMENT_ROOT'];
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('trainer');
verify_csrf();
require $baseDir . '/../composer/vendor/autoload.php';
if (empty($_SESSION['access_granted_trainer']) || $_SESSION['access_granted_trainer'] !== true || empty($_SESSION['passcodetrainer_id']) || $_SESSION['passcodetrainer_id'] < 1) {
if (empty($_SESSION['access_granted_trainer']) || $_SESSION['access_granted_trainer'] !== true || empty($_SESSION['user_id_trainer']) || $_SESSION['user_id_trainer'] < 1) {
http_response_code(403);
header("Location: /intern/trainer");
exit;
@@ -338,7 +343,6 @@ if (isset($_POST['postversand'])) {
}
*/
if ($totalPreis !== 0) {
require __DIR__ . '/ajax-neu_qr_rechnung.php';
}
@@ -350,7 +354,7 @@ $pdf->SetX($columns['name']['max_width'] + $columns['programm']['max_width'] + $
$pdf->Cell($columns['preis']['max_width'], 10, 'CHF ' . number_format($totalPreis, 2), 0, 1, 'C');
$pdf->SetFont('GoogleSansFlex-Regular', '', 10);
if ($totalPreis !== 0) {
if ($totalPreis === 0) {
$pdf->Ln(10);
$pdf->SetTextColor(90, 103, 39);
$pdf->MultiCell(0, 8, 'Diese Rechnung wurde als bezahlt eigetragen, da der Betrag 0 CHF beträgt', 0, 'L');
@@ -410,7 +414,7 @@ $stmt->execute();
$stmt->close();
// 2. DELETE basket items
db_delete($mysqli, $tableBasketItems, ['user_id' => intval($_SESSION['passcodetrainer_id'])]);
db_delete($mysqli, $tableBasketItems, ['user_id' => intval($_SESSION['user_id_trainer'])]);
$mysqli->close();

View File

@@ -11,9 +11,6 @@ if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
?>
<!DOCTYPE html>
<html lang="de">
@@ -38,7 +35,14 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
</head>
<body>
<?php
$access_granted_trainer = $_SESSION['access_granted_trainer'] ?? false;
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session(true);
$csrf_token = $_SESSION['csrf_token'] ?? '';
$access_granted_trainer = check_user_permission('trainer', true) ?? false;
if ( ! $access_granted_trainer ) :
@@ -50,19 +54,9 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
else :
if (isset($_POST['abmelden'])) {
$_SESSION['access_granted_trainer'] = false;
$_SESSION['passcodetrainer_id'] = '';
$_SESSION['passcodetrainer_message'] = '';
$_SESSION['logoDisplay'] = true;
header("Location: " . $_SERVER['PHP_SELF']);
exit;
}
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'tr';
@@ -111,7 +105,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$programmes[] = $prog['programm'];
}
$userid = intval($_SESSION['passcodetrainer_id'] ?? 0);
$userid = intval($_SESSION['user_id_trainer'] ?? 0);
$arrayfreigaben = [];
@@ -159,7 +153,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
<?php
$iduser = $_SESSION['passcodetrainer_id'];
$iduser = $_SESSION['user_id_trainer'];
$result = $mysqli->query("SELECT * FROM `$tableOrders` WHERE user_id = $iduser AND order_status = 0");
@@ -408,7 +402,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
<div class="editContainerDivInner">
<form action="" method="post">
<input type="hidden" name="csrf_token" id="new_turnerin_nonce" value="<?= csrf_token()?>">
<input type="hidden" name="csrf_token" value="<?= $csrf_token ?>">
<?php if ( isset($_POST['edit_id']) ) { ?>
<input type="hidden" name="edit_id" value="<?= intval($_POST['edit_id']) ?>">
@@ -469,6 +463,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
</form>
<form class="form_excel" action="" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" value="<?= $csrf_token ?>">
<h4>Excel Tabelle hochladen</h4>
<a href="https://wkvs.ch/files/WKVS_Vorlage_Upload_Turnerinnen.xlsx" download>
<button type="button">Vorlage Herunterladen</button>
@@ -556,7 +551,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
if (!empty($grouped)) : ?>
<form action="" method="post" id="bulk-action-form">
<?= '<input type="hidden" name="csrf_token" id="bulk_update_nonce" value="'.csrf_token().'">' ?>
<input type="hidden" name="csrf_token" id="bulc_nonce" value="<?= $csrf_token ?>">
<div>
<p class="labelBulkSelect">Bulk Select:</p>
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 15px;">
@@ -751,7 +746,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
<div class="msgDiv"></div>
<form id="global-delete-form" method="post" style="display:none;">
<input type="hidden" name="delete_id" id="global-delete-id">
<input type="hidden" name="csrf_token" value="<?= csrf_token() ?>">
<input type="hidden" name="csrf_token" value="<?= $csrf_token ?>">
</form>
</section>
<div id="musicDiv"><audio controls><source id="sorceAudioPreview" src="" type="audio/mp3"></audio></div>
@@ -803,6 +798,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
</label> */ ?>
<input type="hidden" name="order_id" value="">
<input type="hidden" name="preis" value="">
<input type="hidden" name="csrf_token" value="<?= $csrf_token ?>">
<div>
<button type="submit" class="newBtn">
<span>Rechnung erstellen</span>
@@ -828,6 +824,8 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
<script>
const csrf_token = "<?= $csrf_token ?>";
(function () {
let lastWrite = 0;
const interval = 200;
@@ -860,6 +858,7 @@ function uploadFile(input) {
const formData = new FormData();
formData.append('music_file', input.files[0]);
formData.append('turnerinId', idTurnerin);
formdata.append('csrf_token', csrf_token);
fetch('/intern/scripts/audiofiles-uploads/ajax_audiofile_upload.php', {
method: 'POST',
@@ -1014,31 +1013,7 @@ document.addEventListener('DOMContentLoaded', function () {
<?php
}
?>
console.log('<?php if (isset($_SESSION['form_message'])) echo $_SESSION['form_message']; ?>');
// Single add-to-cart (unchanged)
document.querySelectorAll('.add-to-cart-ajax').forEach(button => {
button.addEventListener('click', function (e) {
e.preventDefault();
const productId = this.getAttribute('data-product-id');
fetch('', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
action: 'ajax_add_to_cart',
product_id: productId
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('Produkt wurde dem Warenkorb hinzugefügt!');
location.reload();
} else {
alert('Fehler beim Hinzufügen zum Warenkorb.');
}
});
});
});
<?php if (isset($_SESSION['form_message'])) echo "console.log(" . $_SESSION['form_message'] . ")"; ?>
// BULK ADD-TO-CART via the main bulk form
const bulkForm = document.getElementById('bulk-action-form');
@@ -1056,13 +1031,17 @@ document.addEventListener('DOMContentLoaded', function () {
}
const ids = checked.map(input => input.value);
const url = "/intern/scripts/trainer/ajax-add_entry_fees_to_basket.php" +
`?ids=${ids}`+
`&user=<?php echo $userid; ?>`+
"&token=6OLSZVVxBrSrmbpKrQ2uD8f6ylziCJHgs5kXKGEE7a0L5FkPz9EXpbec1i5jkOkHjfyAHJlvulO3HA6QImWykM";
console.log(url);
const url = "/intern/scripts/trainer/ajax-add_entry_fees_to_basket.php";
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
ids,
user: <?php echo $userid; ?>
})
})
.then(res => res.json())
.then(response => {
if (response.success) {
@@ -1094,39 +1073,6 @@ document.addEventListener('DOMContentLoaded', function () {
});
});
});
<?php
if (count($arrayfreigaben) > 1) {
?>
/*document.getElementById('freigabe-select').addEventListener('change', function() {
const freigabe = this.value;
const user_id = document.getElementById('user_id').value;
const nonce = document.getElementById('freigabe_nonce').value;
const type = document.getElementById('type_freigabe').value;
const params = new URLSearchParams();
params.append('freigabe', freigabe);
params.append('user_id', user_id);
params.append('type', 'trainer');
fetch('/intern/scripts/kampfrichter/ajax/ajax-update_selected_kampfrichter.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params
})
.then(res => res.json())
.then(data => {
if (data.success) {
window.location.reload(); // reload page to reflect changes
} else {
alert('Error: ' + data.data);
}
})
.catch(err => {
console.error(err);
alert('AJAX request failed');
});
});*/
<?php } ?>
});
let menuTriggerdGebueren = false;
@@ -1174,10 +1120,16 @@ jQuery(function($) {
const id = el.data('id');
// Build the URL with GET parameters safely
const url = `/intern/scripts/trainer/ajax-add_entry_fees_to_basket.php` +
`?ids=${id}`
const url = `/intern/scripts/trainer/ajax-add_entry_fees_to_basket.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
ids: id
})
})
.then(res => {
// 200299
if (res.ok) {
@@ -1317,13 +1269,25 @@ jQuery(function($) {
// Build the URL with GET parameters safely
const url = `/intern/scripts/trainer/ajax-neu_temp_order.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token
})
})
.then(res => res.json())
.then(response => {
if (response.success) {
// Fetch the order_id and preis
return fetch(`/intern/scripts/trainer/ajax-fetch_temp_order.php`)
return fetch(`/intern/scripts/trainer/ajax-fetch_temp_order.php` , {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token
})
})
.then(res2 => res2.json())
.then(orderData => {
if (orderData.success && orderData.result) {
@@ -1420,7 +1384,8 @@ jQuery(function($) {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
id: id
id: id,
csrf_token
})
})
.then(response => {
@@ -1461,13 +1426,7 @@ jQuery(function($) {
altFormat: "d. F Y",
allowInput: true,
disableMobile: "true",
// Enables the dropdown for months
// monthSelectorType: "static",
// Configuration for Year Selection
// This allows the user to type or use arrows,
// but the key is providing a logical range.
minDate: "1920-01-01",
maxDate: "today"
});

View File

@@ -3,12 +3,15 @@
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$access_granted_wkl = $_SESSION['access_granted_wk_leitung'] ?? false;
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;
?>
<!DOCTYPE html>
@@ -76,6 +79,7 @@ require $baseDir . '/intern/scripts/sidebar/sidebar.php';
let ws;
let firstConnect = true;
const RETRY_DELAY = 2000;
const csrf_token = "<?= $csrf_token ?>";
const urlAjaxNewWSToken = '/intern/scripts/ajax-create-ws-token.php';
@@ -86,7 +90,7 @@ require $baseDir . '/intern/scripts/sidebar/sidebar.php';
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({ access: freigabe })
body: new URLSearchParams({ access: freigabe, csrf_token })
});
if (!response.ok) return null;
@@ -210,9 +214,17 @@ require $baseDir . '/intern/scripts/sidebar/sidebar.php';
});
function sendType(typeValue, $element, ctext) {
const url = `/intern/scripts/displaycontrol/ajax-update_display_config_json.php?type=${encodeURIComponent(typeValue)}&ctext=${encodeURIComponent(ctext)}`;
const url = `/intern/scripts/displaycontrol/ajax-update_display_config_json.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
type: typeValue,
ctext
})
})
.then(res => res.json())
.then(response => {

View File

@@ -11,9 +11,14 @@ if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
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;
?>
<!DOCTYPE html>
<html lang="de">
@@ -50,7 +55,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
require $baseDir . '/../scripts/websocket/ws-create-token.php';
@@ -116,82 +121,117 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Wettkampf:</h3>
<div class="settingsGrid">
<div class="settingsRow"><span>Wettkampfname: </span><input type="text" class="ajaxInput" data-key="wkName" placeholder="Test WKVS" value="<?= $wkName ?>"></div>
<div class="settingsRow"><span>Anzahl Tage: </span><input type="number" id="anzahlTageWK" placeholder="2"></div>
<div id="divTageInputs" style="display: contents;"></div>
<div class="settingsRow"><span>Hintergrundfarbe Displays (bei Logo): </span><input type="color" class="ajaxInput" data-key="displayColourLogo" value="<?= $displayColor ?>"></div>
<div class="settingsRow"><span>Textfarbe Displays (bei Logo): </span><input type="color" class="ajaxInput" data-key="displayTextColourLogo" value="<?= $textColor ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Displays primär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringBg" value="<?= $displayColorScoringBg ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Displays sekundär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringBgSoft" value="<?= $displayColorScoringBgSoft ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Kacheln Displays primär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanel" value="<?= $displayColorScoringPanel ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Kacheln Displays sekundär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelSoft" value="<?= $displayColorScoringPanelSoft ?>"></div>
<div class="settingsRow"><span>Textfarbe Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelText" value="<?= $displayColorScoringPanelText ?>"></div>
<div class="settingsRow"><span>Sekundäre Textfarbe Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextSoft" value="<?= $displayColorScoringPanelTextSoft ?>"></div>
<div class="settingsRow"><span>Textfarbe Note Links Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextNoteL" value="<?= $displayColorScoringPanelTextNoteL ?>"></div>
<div class="settingsRow"><span>Textfarbe Note Rechts Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextNoteR" value="<?= $displayColorScoringPanelTextNoteR ?>"></div>
<div class="settingsRow"><span>Id Note links auf Display: </span><input type="number" class="ajaxInput" data-key="displayIdNoteL" placeholder="10" value="<?= $displayIdNoteL ?>"></div>
<div class="settingsRow"><span>Id Note rechts auf Display: </span><input type="number" class="ajaxInput" data-key="displayIdNoteR" placeholder="10" value="<?= $displayIdNoteR ?>"></div>
<div class="settingsRow"><span>Link Webseite: </span><input type="text" class="ajaxInput" data-key="linkWebseite" placeholder="www.wkvs.ch" value="<?= $linkWebseite ?>"></div>
<div class="settingsRow"><span>Maximale Länge Musik (in Sekunden) (0 = keine Beschränkung): </span><input type="number" class="ajaxInput" data-key="maxLengthMusic" placeholder="0" value="<?= $maxLengthMusic ?>"></div>
</div>
<div class="dashboardGrid">
<div class="twoColumDiv">
<div>
<h3 class="containerHeading">Rechnungen:</h3>
<div class="containerDiv firstDiv">
<h3 class="containerHeading">Wettkampf:</h3>
<div class="settingsGrid">
<div class="settingsRowGroup">
<div class="settingsRow"><span>Wettkampfname: </span><input type="text" class="ajaxInput" data-key="wkName" placeholder="Test WKVS" value="<?= $wkName ?>"></div>
<div class="settingsRow"><span>Link Webseite: </span><input type="text" class="ajaxInput" data-key="linkWebseite" placeholder="www.wkvs.ch" value="<?= $linkWebseite ?>"></div>
<div class="settingsRow"><span>Maximale Länge Musik (in Sekunden) (0 = keine Beschränkung): </span><input type="number" class="ajaxInput" data-key="maxLengthMusic" placeholder="0" value="<?= $maxLengthMusic ?>"></div>
</div>
<?php /* <div class="settingsRow"><span>Anzahl Tage: </span><input type="number" id="anzahlTageWK" placeholder="2"></div>
<div id="divTageInputs" style="display: contents;"></div> */ ?>
</div>
</div>
<div class="containerDiv secondDiv">
<h3 class="containerHeading">Rechnungen:</h3>
<div class="settingsGrid">
<div class="settingsRowGroup">
<div class="settingsRow"><span>Name: </span><input type="text" class="ajaxInput" data-key="rechnungenName" placeholder="Mustermann" value="<?= $rechnungenName ?>"></div>
<div class="settingsRow"><span>Vorname: </span><input type="text" class="ajaxInput" data-key="rechnungenVorname" placeholder="Max" value="<?= $rechnungenVorname ?>"></div>
<div class="settingsRow"><span>Strasse: </span><input type="text" class="ajaxInput" data-key="rechnungenStrasse" placeholder="Musterstrasse" value="<?= $rechnungenStrasse ?>"></div>
<div class="settingsRow"><span>Hausnummer: </span><input type="text" class="ajaxInput" data-key="rechnungenHausnummer" placeholder="123" value="<?= $rechnungenHausnummer ?>"></div>
<div class="settingsRow"><span>Postleitzahl: </span><input type="text" class="ajaxInput" data-key="rechnungenPostleitzahl" placeholder="4000" value="<?= $rechnungenPostleitzahl ?>"></div>
<div class="settingsRow"><span>Ort: </span><input type="text" class="ajaxInput" data-key="rechnungenOrt" placeholder="Basel" value="<?= $rechnungenOrt ?>"></div>
<div class="settingsRow"><span>IBAN: </span><input type="text" class="ajaxInput" data-key="rechnungenIBAN" placeholder="CH44 3199 9123 0008 8901 2" value="<?= $rechnungenIBAN ?>"></div>
</div>
</div>
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Displays:</h3>
<div class="settingsGrid">
<div class="settingsRow"><span>Name: </span><input type="text" class="ajaxInput" data-key="rechnungenName" placeholder="Mustermann" value="<?= $rechnungenName ?>"></div>
<div class="settingsRow"><span>Vorname: </span><input type="text" class="ajaxInput" data-key="rechnungenVorname" placeholder="Max" value="<?= $rechnungenVorname ?>"></div>
<div class="settingsRow"><span>Strasse: </span><input type="text" class="ajaxInput" data-key="rechnungenStrasse" placeholder="Musterstrasse" value="<?= $rechnungenStrasse ?>"></div>
<div class="settingsRow"><span>Hausnummer: </span><input type="text" class="ajaxInput" data-key="rechnungenHausnummer" placeholder="123" value="<?= $rechnungenHausnummer ?>"></div>
<div class="settingsRow"><span>Postleitzahl: </span><input type="text" class="ajaxInput" data-key="rechnungenPostleitzahl" placeholder="4000" value="<?= $rechnungenPostleitzahl ?>"></div>
<div class="settingsRow"><span>Ort: </span><input type="text" class="ajaxInput" data-key="rechnungenOrt" placeholder="Basel" value="<?= $rechnungenOrt ?>"></div>
<div class="settingsRow"><span>IBAN: </span><input type="text" class="ajaxInput" data-key="rechnungenIBAN" placeholder="CH44 3199 9123 0008 8901 2" value="<?= $rechnungenIBAN ?>"></div>
<div class="settingsRowGroup">
<div class="settingsRow"><span>Hintergrundfarbe Displays (bei Logo): </span><input type="color" class="ajaxInput" data-key="displayColourLogo" value="<?= $displayColor ?>"></div>
<div class="settingsRow"><span>Textfarbe Displays (bei Logo): </span><input type="color" class="ajaxInput" data-key="displayTextColourLogo" value="<?= $textColor ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Displays primär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringBg" value="<?= $displayColorScoringBg ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Displays sekundär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringBgSoft" value="<?= $displayColorScoringBgSoft ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Kacheln Displays primär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanel" value="<?= $displayColorScoringPanel ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Kacheln Displays sekundär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelSoft" value="<?= $displayColorScoringPanelSoft ?>"></div>
<div class="settingsRow"><span>Textfarbe Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelText" value="<?= $displayColorScoringPanelText ?>"></div>
<div class="settingsRow"><span>Sekundäre Textfarbe Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextSoft" value="<?= $displayColorScoringPanelTextSoft ?>"></div>
<div class="settingsRow"><span>Textfarbe Note Links Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextNoteL" value="<?= $displayColorScoringPanelTextNoteL ?>"></div>
<div class="settingsRow"><span>Textfarbe Note Rechts Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextNoteR" value="<?= $displayColorScoringPanelTextNoteR ?>"></div>
</div>
<div class="settingsRowGroup">
<div class="settingsRow"><span>Id Note links auf Display: </span><input type="number" class="ajaxInput" data-key="displayIdNoteL" placeholder="10" value="<?= $displayIdNoteL ?>"></div>
<div class="settingsRow"><span>Id Note rechts auf Display: </span><input type="number" class="ajaxInput" data-key="displayIdNoteR" placeholder="10" value="<?= $displayIdNoteR ?>"></div>
</div>
</div>
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Geräte management:</h3>
<table class="wkvsTabelle trainer" id="geraeteTable">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Start Index</th>
<th>Farbe Kampfrichter</th>
<th>Löschen</th>
</tr>
</thead>
<tbody>
<?php foreach ($geraete as $g): ?>
<tr data-id="<?= $g['id'] ?>">
<td><?= $g['id'] ?></td>
<td><input type="text" class="ajaxGeraete" data-field="name" value="<?= htmlspecialchars($g['name'] ?? '') ?>" style="width: 100%; padding: 6px; border: 1px dashed #777; border-radius: 4px;"></td>
<td><input type="number" class="ajaxGeraete" data-field="start_index" value="<?= $g['start_index'] ?>" style="width: 80px; padding: 6px; border: 1px dashed #777; border-radius: 4px;"></td>
<td><input type="color" class="ajaxGeraete" data-field="color_kampfrichter" value="<?= $g['color_kampfrichter'] ?>" style="width: 50px; height: 35px; padding: 2px; border: 1px dashed #777; border-radius: 4px;"></td>
<td>
<button class="deleteGeraete" data-id="<?= $g['id'] ?>" style="border:none; background:none; cursor:pointer;">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#b91c1c" stroke-width="2" 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></svg>
</button>
</td>
</tr>
<?php endforeach; ?>
<tr class="addRow">
<td></td>
<td><input type="text" id="newGeraeteName" placeholder="Neues Gerät..." style="width: 100%; padding: 6px; border: 1px solid #777; border-radius: 4px;"></td>
<td><input type="number" id="newGeraeteIndex" value="0" style="width: 80px; padding: 6px; border: 1px solid #777; border-radius: 4px;"></td>
<td><input type="color" id="newGeraeteColor" value="#424242" style="width: 50px; height: 35px; padding: 2px; border: 1px solid #777; border-radius: 4px;"></td>
<td><button id="addGeraeteBtn" style="padding: 6px 12px; background: var(--bg-top); color: #fff; border: none; border-radius: 4px; cursor: pointer;">Hinzufügen</button></td>
</tr>
</tbody>
</table>
<h3 class="containerHeading">Disziplinen:</h3>
<div class="tableWraperOverflowY">
<table class="wkvsTabelle trainer" id="geraeteTable">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Startindex</th>
<th>Farbe Kampfrichter</th>
<th>Löschen</th>
</tr>
</thead>
<tbody>
<?php foreach ($geraete as $g): ?>
<tr data-id="<?= $g['id'] ?>">
<td><?= $g['id'] ?></td>
<td><input type="text" class="ajaxGeraete" data-field="name" value="<?= htmlspecialchars($g['name'] ?? '') ?>" style="width: 100%; padding: 6px; border: 1px dashed #777; border-radius: 4px;"></td>
<td><input type="number" class="ajaxGeraete" data-field="start_index" value="<?= $g['start_index'] ?>" style="width: 80px; padding: 6px; border: 1px dashed #777; border-radius: 4px;"></td>
<td><input type="color" class="ajaxGeraete" data-field="color_kampfrichter" value="<?= $g['color_kampfrichter'] ?>" style="width: 50px; height: 35px; padding: 2px; border: 1px dashed #777; border-radius: 4px;"></td>
<td>
<button class="deleteGeraete" data-id="<?= $g['id'] ?>" style="border:none; background:none; cursor:pointer;">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#b91c1c" stroke-width="2" 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></svg>
</button>
</td>
</tr>
<?php endforeach; ?>
<tr class="addRow">
<td></td>
<td><input type="text" id="newGeraeteName" placeholder="Neues Gerät..." style="width: 100%; padding: 6px; border: 1px solid #777; border-radius: 4px;"></td>
<td><input type="number" id="newGeraeteIndex" value="0" style="width: 80px; padding: 6px; border: 1px solid #777; border-radius: 4px;"></td>
<td><input type="color" id="newGeraeteColor" value="#424242" style="width: 50px; height: 35px; padding: 2px; border: 1px solid #777; border-radius: 4px;"></td>
<td><button id="addGeraeteBtn" style="padding: 6px 12px; background: var(--bg-top); color: #fff; border: none; border-radius: 4px; cursor: pointer;">Hinzufügen</button></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Noten Bezeichnungen:</h3>
<h3 class="containerHeading">Bilder:</h3>
<div class="containerImages">
<div><label for="imgKampfrichter"><span>Kampfrichter</span><input type="file" data-key="Kampfrichter" accept="image/png, image/jpeg" id="imgKampfrichter"><img src="/intern/img/login/bgKampfrichter.webp"></label></div>
<div><label for="imgTrainer"><span>Trainer</span><input type="file" data-key="Trainer" accept="image/png, image/jpeg" id="imgTrainer"><img src="/intern/img/login/bgTrainer.webp"></label></div>
<div><label for="imgWk_leitung"><span>WK-Leitung</span><input type="file" data-key="Wk_leitung" accept="image/png, image/jpeg" id="imgWk_leitung"><img src="/intern/img/login/bgWk_leitung.webp"></label></div>
<div><label for="imgOtl"><span>Einmal Login</span><input type="file" data-key="Otl" accept="image/png, image/jpeg" id="imgOtl"><img src="/intern/img/login/bgOtl.webp"></label></div>
<div><label for="imgIcon"><span>Icon Webseite</span><input type="file" data-key="icon" accept="image/png, image/jpeg" id="imgIcon"><img src="/intern/img/icon.png"></label></div>
<div><label for="imgLogo_normal"><span>Logo</span><input type="file" data-key="logo-normal" accept="image/png, image/jpeg" id="imgLogo_normal"><img src="/intern/img/logo-normal.png"></label></div>
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Noten Konfiguration <span class="light">(fortgeschrittene Einstellungen)</span>:</h3>
<div class="tableWraperOverflowY">
<table class="wkvsTabelle trainer" id="notenTable">
<table class="wkvsTabelle trainer tableNoten" id="notenTable">
<thead>
<tr>
<th>ID</th>
@@ -339,17 +379,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Bilder:</h3>
<div class="containerImages">
<div><span>Kampfrichter: </span><label for="imgKampfrichter">Bild auswählen…</label><input type="file" data-key="Kampfrichter" accept="image/png, image/jpeg" id="imgKampfrichter"><img src="/intern/img/login/bgKampfrichter.webp"></div>
<div><span>Trainer: </span><label for="imgTrainer">Bild auswählen…</label><input type="file" data-key="Trainer" accept="image/png, image/jpeg" id="imgTrainer"><img src="/intern/img/login/bgTrainer.webp"></div>
<div><span>WK-Leitung: </span><label for="imgWk_leitung">Bild auswählen…</label><input type="file" data-key="Wk_leitung" accept="image/png, image/jpeg" id="imgWk_leitung"><img src="/intern/img/login/bgWk_leitung.webp"></div>
<div><span>Einmal Login: </span><label for="imgOtl">Bild auswählen…</label><input type="file" data-key="Otl" accept="image/png, image/jpeg" id="imgOtl"><img src="/intern/img/login/bgOtl.webp"></div>
<div><span>Icon Webseite: </span><label for="imgIcon">Bild auswählen…</label><input type="file" data-key="icon" accept="image/png, image/jpeg" id="imgIcon"><img src="/intern/img/icon.png"></div>
<div><span>Logo: </span><label for="imgLogo_normal">Bild auswählen…</label><input type="file" data-key="logo-normal" accept="image/png, image/jpeg" id="imgLogo_normal"><img src="/intern/img/logo-normal.png"></div>
</div>
</div>
</div>
<div class="msgDiv"></div>
</section>
@@ -361,6 +391,8 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
const $inputAnzahlTage = $('#anzahlTageWK');
const $divTageInputs = $('#divTageInputs');
const csrf_token = "<?= $csrf_token ?>";
function displayNDayFields() {
console.log('ja');
const anzTageRoh = parseInt($inputAnzahlTage.val(), 10);
@@ -407,6 +439,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
const formData = new FormData();
formData.append('image', file);
formData.append('type', type);
formData.append('csrf_token', csrf_token);
$('.msgDiv').html('<p style="color: #007bff; font-weight: 500;">Wird hochgeladen...</p>');
$input.closest('div').css('opacity', '0.5');
@@ -455,6 +488,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
url: '/intern/scripts/einstellungen/ajax-change-value.php',
type: 'POST',
data: {
csrf_token,
type: type,
value: val
},
@@ -486,7 +520,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-gereate-management.php',
type: 'POST',
data: { action: 'update', id: id, field: field, value: value },
data: { action: 'update', id: id, field: field, value: value, csrf_token },
success: function(response) {
if (response.success) {
displayMsg(1, "Gerät aktualisiert");
@@ -510,7 +544,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-gereate-management.php',
type: 'POST',
data: { action: 'add', name: name, start_index: index, color: color },
data: { action: 'add', name: name, start_index: index, color: color, csrf_token },
success: function(response) {
if (response.success) {
window.location.reload();
@@ -529,7 +563,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-gereate-management.php',
type: 'POST',
data: { action: 'delete', id: id },
data: { action: 'delete', id: id, csrf_token },
success: function(response) {
if (response.success) {
$tr.remove();
@@ -555,7 +589,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-noten-management.php',
type: 'POST',
data: { action: 'update', id: id, field: field, value: value },
data: { action: 'update', id: id, field: field, value: value, csrf_token },
success: function(response) {
if (response.success) {
displayMsg(1, "Note aktualisiert");
@@ -586,7 +620,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-noten-management.php',
type: 'POST',
data: { action: 'add', id: id, name: name, type_val: type_val, berechnung: berechnung, pro_geraet: pro_geraet },
data: { action: 'add', id: id, name: name, type_val: type_val, berechnung: berechnung, pro_geraet: pro_geraet, csrf_token },
success: function(response) {
if (response.success) {
window.location.reload();
@@ -605,7 +639,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-noten-management.php',
type: 'POST',
data: { action: 'delete', id: id },
data: { action: 'delete', id: id, csrf_token },
success: function(response) {
if (response.success) {
$tr.remove();
@@ -629,7 +663,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({ access: freigabe })
body: new URLSearchParams({ access: freigabe, csrf_token })
});
if (!response.ok) return null;

View File

@@ -1,10 +1,14 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$access_granted_wkl = $_SESSION['access_granted_wk_leitung'] ?? false;
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 ) :

View File

@@ -1,529 +0,0 @@
<?php
$days = 2;
$firstDay = "2026-04-18";
$dates = [];
$startDate = new DateTime($firstDay);
for ($i = 0; $i < $days; $i++) {
$current = clone $startDate;
$current->modify("+{$i} day");
$dates[] = $current->format("Y-m-d");
}
setlocale(LC_TIME, 'de_DE.UTF-8'); // set German locale
?>
<div class="calendar">
<!-- empty top-left corner -->
<div class="corner fBorderRight fBorderBottom"></div>
<!-- headers -->
<?php foreach ($dates as $ind => $d): ?>
<div class="day-header fBorderBottom"><h3><?= strftime("%a", strtotime($d)) ?> Halle</h3></div>
<div class="day-header fBorderBottom"><h3><?= strftime("%a", strtotime($d)) ?> Aula</h3></div>
<?php $notLast = ($ind !== count($dates) - 1) ? 'fBorderRight' : '';?>
<div class="day-header <?= $notLast ?> fBorderBottom"><h3><?= strftime("%a", strtotime($d)) ?> Sonstige</h3></div>
<?php endforeach; ?>
<!-- time column -->
<div class="time-column fBorderRight">
<?php for ($i = 0; $i <= 23; $i++) {
$si = str_pad($i, 2, '0', STR_PAD_LEFT);
echo '<div class="time">'.$si.':00</div>';
} ?>
</div>
<!-- day columns -->
<?php foreach ($dates as $ind => $d): ?>
<div class="day-column" data-day="<?= $d ?>" data-type="halle"></div>
<div class="day-column" data-day="<?= $d ?>" data-type="aula"></div>
<?php $notLast = ($ind !== count($dates) - 1) ? 'fBorderRight' : '';?>
<div class="day-column <?= $notLast ?>" data-day="<?= $d ?>" data-type="sonstige"></div>
<?php endforeach; ?>
</div>
<button id="exportCal">Export Calendar</button>
<style>
.calendar {
display: grid;
grid-template-columns: 80px <?php foreach ($dates as $d) { echo '1fr 1fr 1fr ';}?>;
grid-template-rows: 40px auto;
border: 1px solid #ccc;
font-family: Arial, sans-serif;
position: relative;
}
.corner {
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.day-header {
position: relative;
text-align: center;
font-weight: bold;
border-bottom: 1px solid #ccc;
line-height: 40px;
}
.day-header h3 {
margin: 0;
}
.time-column {
border-right: 1px solid #ccc;
}
.time {
height: 90px;
padding: 5px;
font-size: 12px;
box-sizing: border-box;
border-bottom: 1px solid #eee;
}
.day-column {
position: relative;
border-right: 1px solid #ccc;
}
.event {
position: absolute;
border-radius: 4px;
padding: 4px;
font-size: 12px;
cursor: grab;
transition: left 0.2s, width 0.2s;
}
.event.dragging {
opacity: 0.8;
z-index: 1000;
cursor: grabbing;
}
.event div span {
position: absolute;
top: 6px;
left: 10px;
}
.fBorderRight { border-right: 3px solid #000; }
.fBorderBottom { border-bottom: 3px solid #000; }
.day-column.highlight {
background-color: rgba(255, 255, 0, 0.1);
}
.day-column.highlight-active {
background-color: rgba(255, 255, 0, 0.25);
}
</style>
<script>
const events = [
{ day: "2026-04-18", start: 12.0, end: 13.0, title: "Kampfrichteressen", type: "sonstige", abt: "0", elem: "" },
// Day 1 - 2026-04-18
{ day: "2026-04-18", start: 8.0, end: 8.50, title: "Körperliches Aufwärmen", type: "aula", abt: "1", elem: "15" },
{ day: "2026-04-18", start: 8.50, end: 9.0, title: "Geführtes Einturnen", type: "halle", abt: "1", elem: "15" },
{ day: "2026-04-18", start: 9.0, end: 10.0, title: "Wettkampf", type: "halle", abt: "1", elem: "15" },
{ day: "2026-04-18", start: 10.0, end: 10.50, title: "Rangverkündigung", type: "aula", abt: "1", elem: "15" },
{ day: "2026-04-18", start: 10.50, end: 11.0, title: "Körperliches Aufwärmen", type: "aula", abt: "2", elem: "13" },
{ day: "2026-04-18", start: 11.0, end: 11.50, title: "Geführtes Einturnen", type: "halle", abt: "2", elem: "13" },
{ day: "2026-04-18", start: 11.50, end: 12.50, title: "Wettkampf", type: "halle", abt: "2", elem: "13" },
{ day: "2026-04-18", start: 12.50, end: 13.0, title: "Rangverkündigung", type: "aula", abt: "2", elem: "13" },
{ day: "2026-04-18", start: 13.0, end: 13.50, title: "Körperliches Aufwärmen", type: "aula", abt: "3", elem: "10" },
{ day: "2026-04-18", start: 13.50, end: 14.0, title: "Geführtes Einturnen", type: "halle", abt: "3", elem: "10" },
{ day: "2026-04-18", start: 14.0, end: 15.0, title: "Wettkampf", type: "halle", abt: "3", elem: "10" },
{ day: "2026-04-18", start: 15.0, end: 15.50, title: "Rangverkündigung", type: "aula", abt: "3", elem: "10" },
{ day: "2026-04-18", start: 15.50, end: 16.0, title: "Körperliches Aufwärmen", type: "aula", abt: "4", elem: "12" },
{ day: "2026-04-18", start: 16.0, end: 16.50, title: "Geführtes Einturnen", type: "halle", abt: "4", elem: "12" },
{ day: "2026-04-18", start: 16.50, end: 17.50, title: "Wettkampf", type: "halle", abt: "4", elem: "12" },
{ day: "2026-04-18", start: 17.30, end: 18.0, title: "Rangverkündigung", type: "aula", abt: "4", elem: "12" },
{ day: "2026-04-18", start: 18.0, end: 18.50, title: "Körperliches Aufwärmen", type: "aula", abt: "5", elem: "11" },
{ day: "2026-04-18", start: 18.50, end: 19.0, title: "Geführtes Einturnen", type: "halle", abt: "5", elem: "11" },
{ day: "2026-04-18", start: 19.0, end: 20.0, title: "Wettkampf", type: "halle", abt: "5", elem: "11" },
{ day: "2026-04-18", start: 20.0, end: 20.50, title: "Rangverkündigung", type: "aula", abt: "5", elem: "11" },
{ day: "2026-04-18", start: 20.50, end: 21.0, title: "Körperliches Aufwärmen", type: "aula", abt: "6", elem: "14" },
{ day: "2026-04-18", start: 21.0, end: 21.50, title: "Geführtes Einturnen", type: "halle", abt: "6", elem: "14" },
{ day: "2026-04-18", start: 21.50, end: 22.50, title: "Wettkampf", type: "halle", abt: "6", elem: "14" },
{ day: "2026-04-18", start: 22.50, end: 23.0, title: "Rangverkündigung", type: "aula", abt: "6", elem: "14" },
// Day 2 - 2026-04-19 (same pattern with shifted times)
{ day: "2026-04-19", start: 8.0, end: 8.30, title: "Körperliches Aufwärmen", type: "aula", abt: "1", elem: "15" },
{ day: "2026-04-19", start: 8.30, end: 9.0, title: "Geführtes Einturnen", type: "halle", abt: "1", elem: "15" },
{ day: "2026-04-19", start: 9.0, end: 10.0, title: "Wettkampf", type: "halle", abt: "1", elem: "15" },
{ day: "2026-04-19", start: 10.0, end: 10.30, title: "Rangverkündigung", type: "aula", abt: "1", elem: "15" },
{ day: "2026-04-19", start: 10.30, end: 11.0, title: "Körperliches Aufwärmen", type: "aula", abt: "2", elem: "13" },
{ day: "2026-04-19", start: 11.0, end: 11.30, title: "Geführtes Einturnen", type: "halle", abt: "2", elem: "13" },
{ day: "2026-04-19", start: 11.30, end: 12.30, title: "Wettkampf", type: "halle", abt: "2", elem: "13" },
{ day: "2026-04-19", start: 12.30, end: 13.0, title: "Rangverkündigung", type: "aula", abt: "2", elem: "13" },
// ...repeat for abt 36 with times staggered
];
const pixelsPerHour = 90;
// Convert hour float to Date
function hourFloatToDate(day, hourFloat) {
const d = new Date(day);
const hours = Math.floor(hourFloat);
const minutes = Math.round((hourFloat % 1) * 60);
d.setHours(hours, minutes, 0, 0);
return d;
}
function hoursToHHMM(hours) {
const h = Math.floor(hours);
const m = Math.round((hours - h) * 60);
return `${h.toString().padStart(2,'0')}:${m.toString().padStart(2,'0')}`;
}
// Convert HH:MM string to hours float
function HHMMToHours(str) {
const [h, m] = str.split(':').map(Number);
return h + m/60;
}
// Format Date to hh:mm
function formatTime(date) {
return new Intl.DateTimeFormat(undefined, { hour: '2-digit', minute: '2-digit' }).format(date);
}
// Collision detection
function eventsCollide(a, b) {
return a.start < b.end && a.end > b.start && a.day === b.day && a.type === b.type;
}
// Assign columns with proper overlap tracking
function assignColumns(events) {
events.sort((a,b) => a.start - b.start);
const active = [];
events.forEach(event => {
// Remove finished events
for (let i = active.length-1; i>=0; i--) {
if (active[i].end <= event.start) active.splice(i,1);
}
// Find first free column index
let colIndex = 0;
while(active.some(e => e.columnIndex === colIndex)) colIndex++;
event.columnIndex = colIndex;
active.push(event);
// Update totalColumns for current overlap group
const maxColumns = Math.max(...active.map(e => e.columnIndex + 1));
active.forEach(e => e.totalColumns = maxColumns);
});
}
// Render events into the calendar
function renderEvents(events, colors) {
events.forEach(event => {
const dayColumn = document.querySelector(`.day-column[data-day="${event.day}"][data-type="${event.type}"]`);
const el = document.createElement("div");
el.className = "event";
const startDate = hourFloatToDate(event.day, event.start);
const endDate = hourFloatToDate(event.day, event.end);
const duration = event.end - event.start; // in hours
const lineBreak = duration >= 1 ? "<br>" : " "; // use space if < 1h
if (event.abt != 0){
el.innerHTML = `<div><span><b>${event.title} - Abt. ${event.abt}</b> (${event.elem})${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}</span></div>`;
} else {
el.innerHTML = `<div><span><b>${event.title}</b>${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}</span></div>`;
}
el.style.background = colors[event.abt].background;
el.style.color = colors[event.abt].foreground;
el.style.borderTop = `3px solid ${colors[event.abt].borderTop}`;
const widthPercent = 100 / event.totalColumns;
el.style.top = (event.start * pixelsPerHour) + "px";
el.style.height = ((event.end - event.start) * pixelsPerHour - 11) + "px";
el.style.width = `calc(${widthPercent}% - 10px)`;
el.style.left = `${event.columnIndex * widthPercent}%`;
// Store reference for updates
event.el = el;
addDragBehavior(el, event, colors);
dayColumn.appendChild(el);
});
}
// Drag & drop behavior
function addDragBehavior(el, event, colors) {
el.addEventListener("pointerdown", e => {
e.preventDefault();
el.setPointerCapture(e.pointerId);
el.classList.add("dragging");
const startY = e.clientY;
const origTop = parseFloat(el.style.top);
const type = event.type;
const validColumns = Array.from(document.querySelectorAll(`.day-column[data-type="${type}"]`));
validColumns.forEach(c => c.classList.add("highlight"));
function onPointerMove(eMove) {
const deltaY = eMove.clientY - startY;
// Vertical movement (snapped to 15 min)
let newTop = origTop + deltaY;
newTop = Math.max(0, newTop);
newTop = Math.round(newTop / (pixelsPerHour/12)) * (pixelsPerHour/12);
el.style.top = newTop + "px";
// Horizontal movement locked to same type columns
const pointerX = eMove.clientX;
const targetColumn = validColumns.find(c => {
const rect = c.getBoundingClientRect();
return pointerX >= rect.left && pointerX <= rect.right;
});
if (targetColumn && targetColumn !== el.parentElement) {
targetColumn.appendChild(el);
el.style.left = 0;
}
// Update live time
const newStart = newTop / pixelsPerHour;
const newEnd = newStart + (event.end - event.start);
const startDate = hourFloatToDate(event.day, newStart);
const endDate = hourFloatToDate(event.day, newEnd);
const duration = event.end - event.start; // in hours
const lineBreak = duration >= 1 ? "<br>" : " "; // use space if < 1h
if (event.abt != 0){
el.querySelector("span").innerHTML = `<b>${event.title} - Abt. ${event.abt}</b> (${event.elem})${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
} else {
el.querySelector("span").innerHTML = `<b>${event.title}</b>${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
}
}
function onPointerUp(eUp) {
el.classList.remove("dragging");
el.releasePointerCapture(eUp.pointerId);
document.removeEventListener("pointermove", onPointerMove);
document.removeEventListener("pointerup", onPointerUp);
validColumns.forEach(c => c.classList.remove("highlight"));
// Update event day based on column
const newColumn = validColumns.find(c => el.parentElement === c);
if(newColumn) event.day = newColumn.dataset.day;
// Update start/end
const newStart = parseFloat(el.style.top) / pixelsPerHour;
const duration = event.end - event.start;
event.start = newStart;
event.end = newStart + duration;
// Recalculate columns for current day/type
const dayEvents = events.filter(ev => ev.day === event.day && ev.type === event.type);
assignColumns(dayEvents);
// Update positions, widths, and displayed time
dayEvents.forEach(ev => {
const widthPercent = 100 / ev.totalColumns;
ev.el.style.width = `calc(${widthPercent}% - 10px)`;
ev.el.style.left = `${ev.columnIndex * widthPercent}%`;
const startDate = hourFloatToDate(ev.day, ev.start);
const endDate = hourFloatToDate(ev.day, ev.end);
const duration = ev.end - ev.start; // in hours
const lineBreak = duration >= 1 ? "<br>" : " "; // use space if < 1h
if (ev.abt != 0){
ev.el.querySelector("span").innerHTML = `<b>${ev.title} - Abt. ${ev.abt}</b> (${ev.elem})${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
} else {
ev.el.querySelector("span").innerHTML = `<b>${ev.title}</b>${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
}
});
}
document.addEventListener("pointermove", onPointerMove);
document.addEventListener("pointerup", onPointerUp);
});
el.addEventListener("dblclick", () => {
const durationHours = prompt("Enter new duration in hours:", hoursToHHMM((event.end - event.start).toFixed(2)));
if(durationHours !== null) {
const duration = HHMMToHours(durationHours);
if(!isNaN(duration) && duration > 0) {
event.end = event.start + duration;
// Recalculate columns for the day/type
const dayEvents = events.filter(ev => ev.day === event.day && ev.type === event.type);
assignColumns(dayEvents);
// Update all event positions, widths, and displayed text
dayEvents.forEach(ev => {
const widthPercent = 100 / ev.totalColumns;
ev.el.style.width = `calc(${widthPercent}% - 10px)`;
ev.el.style.left = `${ev.columnIndex * widthPercent}%`;
ev.el.style.top = (ev.start * pixelsPerHour) + "px";
ev.el.style.height = ((ev.end - ev.start) * pixelsPerHour - 11) + "px";
// Update displayed time with conditional line break
const startDate = hourFloatToDate(ev.day, ev.start);
const endDate = hourFloatToDate(ev.day, ev.end);
const dur = ev.end - ev.start;
const lineBreak = dur >= 1 ? "<br>" : " ";
if (ev.abt != 0){
ev.el.querySelector("span").innerHTML = `<b>${ev.title} - Abt. ${ev.abt}</b> (${ev.elem})${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
} else {
ev.el.querySelector("span").innerHTML = `<b>${ev.title}</b>${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
}
});
}
}
});
}
// ----------------- USAGE -----------------
// Example colors
const colors = {
"0": {
"background": "rgba(172, 172, 172, 0.18)",
"foreground": "#4b4b4bff",
"borderTop": "#5a5a5aff"
},
"1": {
"background": "rgba(59, 130, 246, 0.18)",
"foreground": "#1e3a8a",
"borderTop": "#1e3a8a"
},
"2": {
"background": "rgba(20, 184, 166, 0.18)",
"foreground": "#065f46",
"borderTop": "#065f46"
},
"3": {
"background": "rgba(34, 197, 94, 0.18)",
"foreground": "#14532d",
"borderTop": "#14532d"
},
"4": {
"background": "rgba(163, 230, 53, 0.20)",
"foreground": "#365314",
"borderTop": "#365314"
},
"5": {
"background": "rgba(245, 158, 11, 0.20)",
"foreground": "#92400e",
"borderTop": "#92400e"
},
"6": {
"background": "rgba(249, 115, 22, 0.20)",
"foreground": "#9a3412",
"borderTop": "#9a3412"
},
"7": {
"background": "rgba(244, 63, 94, 0.18)",
"foreground": "#9f1239",
"borderTop": "#9f1239"
},
"8": {
"background": "rgba(236, 72, 153, 0.18)",
"foreground": "#9d174d",
"borderTop": "#9d174d"
},
"9": {
"background": "rgba(168, 85, 247, 0.18)",
"foreground": "#581c87",
"borderTop": "#581c87"
},
"10": {
"background": "rgba(99, 102, 241, 0.18)",
"foreground": "#312e81",
"borderTop": "#312e81"
},
"11": {
"background": "rgba(100, 116, 139, 0.20)",
"foreground": "#1e293b",
"borderTop": "#1e293b"
},
"12": {
"background": "rgba(6, 182, 212, 0.18)",
"foreground": "#164e63",
"borderTop": "#164e63"
}
};
// Initialize
const grouped = {};
events.forEach(e => {
const key = `${e.day}-${e.type}`;
if(!grouped[key]) grouped[key] = [];
grouped[key].push(e);
});
Object.values(grouped).forEach(arr => assignColumns(arr));
renderEvents(events, colors);
function exportToICS(events) {
let icsContent = `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//YourApp//Calendar//EN
CALSCALE:GREGORIAN
METHOD:PUBLISH
`;
events.forEach(event => {
const startDate = hourFloatToDate(event.day, event.start);
const endDate = hourFloatToDate(event.day, event.end);
// Format as YYYYMMDDTHHMMSS
function formatICSDate(d) {
return d.toISOString().replace(/[-:]/g,'').split('.')[0] + 'Z';
}
icsContent += `BEGIN:VEVENT
UID:${event.day}-${event.start}-${event.title}
DTSTAMP:${formatICSDate(new Date())}
DTSTART:${formatICSDate(startDate)}
DTEND:${formatICSDate(endDate)}
SUMMARY:${event.title} - Abt. ${event.abt}
DESCRIPTION:Type: ${event.type}, Elem: ${event.elem}
END:VEVENT
`;
});
icsContent += `END:VCALENDAR`;
// Create downloadable link
const blob = new Blob([icsContent], { type: 'text/calendar;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'calendar.ics';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
// Attach to button
document.getElementById('exportCal').addEventListener('click', () => exportToICS(events));
</script>

View File

@@ -2,7 +2,6 @@
use Dotenv\Dotenv;
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
@@ -11,12 +10,18 @@ ini_set('display_startup_errors', 1);
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
$access_granted_wkl = $_SESSION['access_granted_wk_leitung'] ?? false;
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';
@@ -31,7 +36,7 @@ echo '<link rel="icon" type="png" href="/intern/img/icon.png">';
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'wkl';
@@ -103,11 +108,11 @@ require $baseDir . '/intern/scripts/sidebar/sidebar.php';
<div class="ot-modal-content">
<div class="ot-modal-top-content">
<div class="ot-title">One-Time Login URL:</div>
<button id="otClose" class="ot-close-btn">✕</button>
<button id="otCloseOTL" class="ot-close-btn">✕</button>
</div>
<a id="aOturl" class="ot-url" target="_blank" href="/"></a>
<p id="oturlGb"></p>
<button id="otCopy" class="ot-copy-btn">Copy URL</button>
<button id="otCopy" class="ot-copy-btn">URL Kopieren</button>
<div class="qrcodeWrapper">
<div id="qrcode"></div>
</div>
@@ -118,7 +123,7 @@ require $baseDir . '/intern/scripts/sidebar/sidebar.php';
const otModal = document.getElementById("oturldiv");
const otUrl = document.getElementById("aOturl");
const otCopy = document.getElementById("otCopy");
const otClose = document.getElementById("otClose");
const otClose = document.getElementById("otCloseOTL");
function showOneTimeUrl(fullUrl) {
otUrl.innerHTML = fullUrl;
@@ -177,11 +182,12 @@ otModal.addEventListener("click", (e) => {
<div id="secure-password-msg"></div>
<form id="secure-password-form-new">
<input type="hidden" id="username-new" name="username" value="Neuer Benutzer">
<input type="hidden" id="name_person-new" name="text" value="Neuer Benutzer">
<input type="hidden" id="password-new" name="password" value="TemporaeresPasswort">
<input type="hidden" id="nonce-new" value="<?php echo csrf_token(); ?>">
<input type="hidden" id="field_id-new" name="field_id" value="0">
<button type="submit">Neuer Benutzer</button>
</form>
<button type="submit" id="newUserLink">Neuer Benutzer (Registrationslink)</button>
</div>
<?php
@@ -201,7 +207,7 @@ $disciplines = array_map(
$stmt->close();
$vereine = db_select($mysqli, $tableVereine, "id, verein, email", '', [], 'verein ASC');
$entrys = db_select($mysqli, $tableInternUsers, "id, username, password_cipher, freigabe", '', [], 'username ASC');
$entrys = db_select($mysqli, $tableInternUsers, "id, username, name_person, password_cipher, freigabe", '', [], 'username ASC');
echo '<h3 class="benutzer">Benutzer</h3><section class="inner-pw-set-bg" id="section-benutzer">';
foreach ($entrys as $entry){
@@ -234,6 +240,10 @@ foreach ($entrys as $entry){
<label for="username-<?php echo $entry['id']; ?>">Benutzername</label>
<input type="text" id="username-<?php echo $entry['id']; ?>" name="username" value="<?php echo $entry['username']; ?>" required>
</div>
<div class="field-group">
<label for="name_person-<?php echo $entry['id']; ?>">Name des Benutzers:</label>
<input type="text" id="name_person-<?php echo $entry['id']; ?>" name="name_person" value="<?php echo $entry['name_person']; ?>" required>
</div>
<div class="field-group">
<label for="password-<?php echo $entry['id']; ?>">Passwort</label>
<?php if ($decrypted_password === 'SET_BY_OTL'){
@@ -322,24 +332,30 @@ foreach ($entrys as $entry){
</div>
<button type="submit">Benutzer aktualisieren</button>
<input type="hidden" id="nonce-<?php echo $entry['id']; ?>" value="<?php echo csrf_token(); ?>">
<input type="hidden" id="field_id-<?php echo $entry['id']; ?>" name="field_id" value="<?php echo intval($entry['id']); ?>">
</form>
<button
id="delete-user-<?php echo intval($entry['id']); ?>"
class="delete-user-btn"
data-id="<?php echo intval($entry['id']); ?>"
data-nonce="<?php echo csrf_token(); ?>"
type="button">
Benutzer löschen
</button>
<button
id="createOturl-<?php echo intval($entry['id']); ?>"
class="createOturl"
data-username="<?php echo $entry['username']; ?>"
data-username="<?php echo $entry['username']; ?>"
data-type="login"
data-id="<?php echo intval($entry['id']); ?>"
type="button">
Einmallogin erstellen
Einmallogin-Link erstellen
</button>
<button
class="createOturl"
data-username="<?php echo $entry['username']; ?>"
data-type="pwreset"
data-id="<?php echo intval($entry['id']); ?>"
type="button">
Passwortreset-Link erstellen
</button>
@@ -369,16 +385,14 @@ foreach ($entrys as $entry){
</td>
<td>
<button type="submit" style="padding: 6px 14px; border: 1px solid #7777778e; background: #7777778e; color: #fff; border-radius: 4px; font-size: 0.85rem; cursor: pointer; transition: all 0.2s;">Speichern</button>
<input type="hidden" id="nonceverein-<?php echo $entryvaer['id']; ?>" value="<?php echo csrf_token(); ?>">
<input type="hidden" id="field_idverein-<?php echo $entryvaer['id']; ?>" name="field_id" value="<?php echo intval($entryvaer['id']); ?>">
</td>
</form>
<td>
<button
id="delete-verein-<?php echo intval($entryvaer['id']); ?>"
class="delete-verein-btn deleteProgramm"
class="delete-verein-btn"
data-id="<?php echo intval($entryvaer['id']); ?>"
data-nonce="<?php echo csrf_token(); ?>"
type="button" style="border:none; background:none; cursor:pointer;">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" style="color: #b91c1c;">
<polyline points="3 6 5 6 21 6"></polyline>
@@ -398,7 +412,6 @@ foreach ($entrys as $entry){
</td>
<td>
<button type="submit">Hinzufügen</button>
<input type="hidden" id="nonceverein-new" value="<?php echo csrf_token(); ?>">
<input type="hidden" id="field_idverein-new" name="field_id" value="0">
</td>
</form>
@@ -462,16 +475,127 @@ foreach ($entrys as $entry){
</div>
</section>
</section>
<div class="bgNewUserLink hidden">
<div class="newUserLink">
<div class="ot-modal-top-content">
<div class="ot-title">Daten & Freigaben:</div>
<button id="otCloseNBL" class="ot-close-btn">✕</button>
</div>
<form>
<div class="field-group">
<label for="username-linkUser">Benutzername (optional)</label>
<input type="text" id="username-linkUser" name="username" value="">
</div>
<div class="field-group">
<label for="name_person-linkUser">Name des Benutzers (optional)</label>
<input type="text" id="name_person-linkUser" name="name_person" value="">
</div>
<div class="field-group">
<label for="password-linkUser">Passwort (optional)</label>
<input type="text" id="password-linkUser" name="password" value="">
</div>
<p>Alle Daten, welche nicht hier gesetzt werden, werden durch den Benutzer selbst gesetzt.</p>
<!-- Permission dropdown: Zugang (Roles) -->
<div class="perm-section perm-section-types open" id="perm-zugang-linkUser">
<div class="perm-section-header" onclick="this.parentElement.classList.toggle('open')">
<span class="perm-section-title">
Zugang
<span class="perm-badge" id="badge-zugang-linkUser">erforderlich</span>
</span>
<svg class="perm-section-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>
</div>
<div class="perm-section-body">
<label>
<input type="checkbox" name="freigabe[]" value="wk_leitung">
WK-Leitung
</label>
<label>
<input type="checkbox" name="freigabe[]" value="trainer">
Trainer
</label>
<label>
<input type="checkbox" name="freigabe[]" value="kampfrichter">
Kampfrichter
</label>
</div>
</div>
<!-- Permission dropdown: Trainer Vereine -->
<div class="perm-section perm-section-trainer" id="perm-tr-linkUser">
<div class="perm-section-header" onclick="this.parentElement.classList.toggle('open')">
<span class="perm-section-title">
Trainer Vereine
<span class="perm-badge" id="badge-tr-linkUser">erforderlich</span>
</span>
<svg class="perm-section-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>
</div>
<div class="perm-section-body">
<label>
<input type="checkbox" name="freigabeTrainer[]" value="admin">
Admin (alle Vereine)
</label>
<?php foreach ($vereine as $verein): ?>
<label>
<input type="checkbox" name="freigabeTrainer[]" value="<?php echo $verein['verein']; ?>">
<?php echo ucfirst($verein['verein']); ?>
</label>
<?php endforeach; ?>
</div>
</div>
<!-- Permission dropdown: Kampfrichter Geräte -->
<div class="perm-section perm-section-kampfrichter" id="perm-kr-linkUser">
<div class="perm-section-header" onclick="this.parentElement.classList.toggle('open')">
<span class="perm-section-title">
Kampfrichter Geräte
<span class="perm-badge" id="badge-kr-linkUser">erforderlich</span>
</span>
<svg class="perm-section-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>
</div>
<div class="perm-section-body">
<label>
<input type="checkbox" name="freigabeKampfrichter[]" value="admin">
Admin (alle Geräte)
</label>
<?php foreach ($disciplines as $discipline): ?>
<label>
<input type="checkbox" name="freigabeKampfrichter[]" value="<?php echo $discipline; ?>">
<?php echo ucfirst($discipline); ?>
</label>
<?php endforeach; ?>
</div>
</div>
<button type="submit">Link erstellen</button>
<input type="hidden" id="field_id-linkUser" name="field_id" value="linkUser">
</form>
</div>
</div>
<script>
const csrf_token = "<?= $csrf_token ?>";
jQuery(document).ready(function($) {
$(document).on('change', '.inputPreisProgramm', function() {
const $input = $(this);
const url = `/intern/scripts/logindata/ajax-update_programm_preis.php` +
`?id=${encodeURIComponent($input.data('field-id'))}` +
`&value=${encodeURIComponent($input.val())}` +
`&token=k7uweziEUWZiJhwe7687UWIQZ28SQIH2ug74pINKyxHxPerB6wUZ`;
const url = `/intern/scripts/logindata/ajax-update_programm_preis.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
id: $input.data('field-id'),
value: $input.val()
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
@@ -488,12 +612,17 @@ jQuery(document).ready(function($) {
$(document).on('change', '.inputAktivProgramm', function() {
const $input = $(this);
const url = `/intern/scripts/logindata/ajax-update_programm_aktiv.php` +
`?id=${encodeURIComponent($input.data('field-id'))}` +
`&value=${encodeURIComponent($input.is(':checked') ? 1 : 0)}` +
`&token=0UgBVHutbxTRTYsB04ujFKMjMRA8GgdqRJjVh3DKU1LRJfwtcDfrpDc7jpMxcrg9rYurAEwYPy5gu15R77MsgKsDMkFZEykx0A67`;
const url = `/intern/scripts/logindata/ajax-update_programm_aktiv.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
id: $input.data('field-id'),
value: $input.is(':checked') ? 1 : 0
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
@@ -564,11 +693,16 @@ jQuery(document).ready(function($) {
return;
}
const url = `/intern/scripts/logindata/ajax-neu_programm.php` +
`?value=${encodeURIComponent(value)}` +
`&token=sWZ4GxbsoVhUPk5zhjH0uU9hets3zV2KsV8CZUvAWCCRk4uuuDr9vfFVgxWqr5FtDttbtm50EdWK9YxuMPswGZBQZFHAUAET1aG1`;
const url = `/intern/scripts/logindata/ajax-neu_programm.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
value
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
@@ -589,11 +723,16 @@ jQuery(document).ready(function($) {
$(document).on('click', '.deleteProgramm', function() {
const $input = $(this);
const url = `/intern/scripts/logindata/ajax-remove_programm.php` +
`?id=${encodeURIComponent($input.data('field-id'))}` +
`&token=bKqBAPjwojZdarJaE7jwvRrIEf2WzJUlFlufQadfLJ98qJcrWZK5pRlGoUQOHp1L06urGRbEdE9v5oIRirPiUCjm93wATghO4qx`;
const url = `/intern/scripts/logindata/ajax-remove_programm.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
id: $input.data('field-id')
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
@@ -618,11 +757,15 @@ function toggleFreigabenDropdowns(el) {
const $input = $(el);
const type = $input.val();
console.log(type);
if (type !== 'kampfrichter' && type !== 'trainer') {
return;
}
const dropdown = $input.closest('.single_pwedit').find('.perm-section-' + type);
const dropdown = $input.closest('form').find('.perm-section-' + type);
console.log(dropdown.length);
if ($input.is(':checked')) {
dropdown.show();
@@ -631,7 +774,7 @@ function toggleFreigabenDropdowns(el) {
}
}
const targetCheckboxes = '#section-benutzer .perm-section-types input[type="checkbox"]';
const targetCheckboxes = '.perm-section-types input[type="checkbox"]';
$(targetCheckboxes).each(function() {
toggleFreigabenDropdowns(this);
@@ -642,9 +785,6 @@ $(document).on('change', targetCheckboxes, function() {
});
// ----------------------------------------------------
// ----------------------------------------------------
// ----------------------------------------------------
@@ -660,6 +800,7 @@ document.querySelectorAll('[id^="secure-password-form-"], #secure-password-form-
const password = document.getElementById('password-' + id)?.value || document.getElementById('password-new').value || 'TemporaeresPasswort';
const username = document.getElementById('username-' + id)?.value || document.getElementById('username-new').value;
const namePerson = document.getElementById('name_person-' + id)?.value || document.getElementById('name_person-new').value;
const field_id = document.getElementById('field_id-' + id)?.value || document.getElementById('field_id-new').value;
// Collect all checked freigabe checkboxes within THIS form
@@ -676,10 +817,12 @@ document.querySelectorAll('[id^="secure-password-form-"], #secure-password-form-
params.append('action', 'set_general_password');
params.append('password', password);
params.append('username', username);
params.append('namePerson', namePerson);
params.append('field_id', field_id);
// We send an empty pwtype or 'all' to satisfy backend temporarily if it still checks it
params.append('pwtype', 'all');
params.append('csrf_token', csrf_token);
freigaben.forEach(value => params.append('freigaben[]', value));
freigabenTrainer.forEach(value => params.append('freigabenTrainer[]', value));
@@ -762,12 +905,12 @@ document.querySelectorAll('[id$="-verein"], #new-verein').forEach(form => {
const verein = document.getElementById('verein-' + id)?.value || document.getElementById('verein-new').value;
const field_id = document.getElementById('field_idverein-' + id)?.value || document.getElementById('field_idverein-new').value;
const nonce = document.getElementById('nonceverein-' + id)?.value || document.getElementById('nonceverein-new').value;
const params = new URLSearchParams();
params.append('action', 'set_verein');
params.append('verein', verein);
params.append('field_id', field_id);
params.append('csrf_token', csrf_token);
// Show loading overlay
if (id === 'new'){
@@ -801,10 +944,7 @@ document.querySelectorAll('[id$="-verein"], #new-verein').forEach(form => {
.catch(err => {
console.error(err);
document.getElementById('loading-overlay').style.display = 'none';
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = 'Error, see console';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, 'Fehler, siehe Konsole.');
});
});
});
@@ -813,7 +953,6 @@ document.querySelectorAll('.delete-user-btn').forEach(btn => {
e.preventDefault();
const id = btn.dataset.id;
const nonce = btn.dataset.nonce;
if (!confirm("Benutzer wirklich löschen?")) {
return;
@@ -825,8 +964,9 @@ document.querySelectorAll('.delete-user-btn').forEach(btn => {
const params = new URLSearchParams();
params.append('action', 'delete_secure_user');
params.append('field_id', id);
params.append('csrf_token', csrf_token);
fetch('/intern/scripts/logindata/ajax02.php', {
fetch('/intern/scripts/logindata/ajax-delete-user.php', {
method: 'POST',
body: params
})
@@ -840,23 +980,15 @@ document.querySelectorAll('.delete-user-btn').forEach(btn => {
if (div) div.remove();
const success = document.getElementById('success-overlay');
success.querySelector('.textSucsess').textContent = data.message || 'Benutzer gelöscht!';
success.classList.add('show');
setTimeout(() => { success.classList.remove('show'); }, 2500);
displayMsg(1, data.message || 'Benutzer gelöscht!');
} else {
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = data.data || 'Fehler beim Löschen';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, data.data || 'Fehler beim Löschen');
}
})
.catch(err => {
console.error(err);
document.getElementById('loading-overlay').style.display = 'none';
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = 'Error, see console';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, 'Fehler, siehe Konsole.');
});
});
});
@@ -876,12 +1008,15 @@ document.querySelectorAll('.createOturl').forEach(btn => {
e.preventDefault();
const id = btn.dataset.id;
const type = btn.dataset.type;
const username = btn.getAttribute("data-username");
const params = new URLSearchParams();
params.append('user_id', id);
params.append('type', type);
params.append('csrf_token', csrf_token);
fetch('/intern/scripts/logindata/ajax05.php', {
fetch('/intern/scripts/logindata/ajax-create-otl.php', {
method: 'POST',
body: params
})
@@ -947,10 +1082,7 @@ document.querySelectorAll('.createOturl').forEach(btn => {
})
.catch(err => {
console.error(err);
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = 'Error, see console';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, 'Fehler, siehe Konsole.');
});
});
});
@@ -960,7 +1092,6 @@ document.querySelectorAll('.delete-verein-btn').forEach(btn => {
e.preventDefault();
const id = btn.dataset.id;
const nonce = btn.dataset.nonce;
if (!confirm("Verein wirklich löschen?")) {
return;
@@ -971,8 +1102,9 @@ document.querySelectorAll('.delete-verein-btn').forEach(btn => {
const params = new URLSearchParams();
params.append('field_id', id);
params.append('csrf_token', csrf_token);
fetch('/intern/scripts/logindata/ajax04.php', {
fetch('/intern/scripts/logindata/ajax-delete-verein.php', {
method: 'POST',
body: params
})
@@ -985,27 +1117,143 @@ document.querySelectorAll('.delete-verein-btn').forEach(btn => {
const tr = document.getElementById('div_verein-' + id);
if (tr) tr.remove();
const success = document.getElementById('success-overlay');
success.querySelector('.textSucsess').textContent = data.message || 'Verein gelöscht!';
success.classList.add('show');
setTimeout(() => { success.classList.remove('show'); }, 2500);
displayMsg(0, data.message || 'Verein gelöscht!');
} else {
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = data || 'Fehler beim Löschen';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, data || 'Fehler beim Löschen');
}
})
.catch(err => {
console.error(err);
document.getElementById('loading-overlay').style.display = 'none';
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = 'Error, see console';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, 'Fehler, siehe Konsole.');
});
});
const $bgNewUserLink = $('.bgNewUserLink');
const $closeXNUL = $('#otCloseNBL');
$('#newUserLink').on('click', function () {
$bgNewUserLink.toggleClass("hidden");
});
$closeXNUL.on('click', function (e) {
$bgNewUserLink.addClass("hidden");
});
$bgNewUserLink.on('click', function (e) {
if (e.target === e.currentTarget) {
$(this).addClass("hidden");
}
});
});
const formNewUserLink = document.querySelector('.newUserLink form');
formNewUserLink.addEventListener('submit', e => {
e.preventDefault();
const password = document.getElementById('password-linkUser').value ?? null;
const username = document.getElementById('username-linkUser').value ?? null;
const namePerson = document.getElementById('name_person-linkUser').value ?? null;
// Collect all checked freigabe checkboxes within THIS form
const checkboxesFreigaben = formNewUserLink.querySelectorAll('input[name="freigabe[]"]:checked');
const freigaben = Array.from(checkboxesFreigaben).map(cb => cb.value);
const checkboxesTrainer = formNewUserLink.querySelectorAll('input[name="freigabeTrainer[]"]:checked');
const freigabenTrainer = Array.from(checkboxesTrainer).map(cb => cb.value);
const checkboxesKampfrichter = formNewUserLink.querySelectorAll('input[name="freigabeKampfrichter[]"]:checked');
const freigabenKampfrichter = Array.from(checkboxesKampfrichter).map(cb => cb.value);
if (freigaben.length === 0) { displayMsg(2, "Keine Freigaben ausgewält."); return; }
if (freigaben.includes('kampfrichter') && freigabenKampfrichter.length === 0) { displayMsg(2, "Keine Freigabe für Kampfrichter ausgewält."); return; }
if (freigaben.includes('trainer') && freigabenTrainer.length === 0) { displayMsg(2, "Keine Freigabe für Trainer ausgewält."); return; }
const params = new URLSearchParams();
params.append('password', password);
params.append('username', username);
params.append('namePerson', namePerson);
params.append('csrf_token', csrf_token);
freigaben.forEach(value => params.append('freigaben[]', value));
freigabenTrainer.forEach(value => params.append('freigabenTrainer[]', value));
freigabenKampfrichter.forEach(value => params.append('freigabenKampfrichter[]', value));
fetch('/intern/scripts/logindata/ajax-create-link-user.php', {
method: 'POST',
body: params
})
.then(res => res.json())
.then(data => {
if (data.success) {
let urlDiv = document.getElementById('oturldiv');
if (!urlDiv){
return
}
urlDiv.style.display = 'flex';
let fullUrl = window.location.origin + '/intern/otlogin?otl=' + data.url;
console.log(fullUrl);
let aOturl = document.getElementById('aOturl');
if (!aOturl){
return
}
aOturl.innerHTML = fullUrl;
aOturl.href = fullUrl;
let oturlGb = document.getElementById('oturlGb');
if (!oturlGb){
return
}
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
oturlGb.innerHTML = 'Link gültig bis: ' + germanDate(tomorrow);
const qrcodeContainer = document.getElementById("qrcode");
qrcodeContainer.innerHTML = '';
// 1. Generate the QR Code
const qr = new QRCode(qrcodeContainer, {
text: fullUrl,
width: 256,
height: 256
});
// 2. Add Download Logic
document.getElementById("btnDownloadQRCode").addEventListener("click", () => {
// Find the canvas element inside the qrcode div
const canvas = qrcodeContainer.querySelector("canvas");
if (canvas) {
const image = canvas.toDataURL("image/png");
const link = document.createElement("a");
link.href = image;
link.download = `QR_Code_Einmallogin_${username}.png`;
link.click();
} else {
alert("QR Code not ready yet!");
}
});
}
})
.catch(err => {
console.error(err);
if (id === 'new'){
document.getElementById('new-overlay').style.display = 'none';
} else {
document.getElementById('loading-overlay').style.display = 'none';
}
displayMsg(0, data.message || data || 'Es trat ein Fehler auf. Siehe Konsole.');
});
});
</script>
</body>
</html>

View File

@@ -7,13 +7,19 @@ ini_set('display_startup_errors', 1);
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
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;
?>
<!DOCTYPE html>
<html lang="de">
@@ -44,7 +50,6 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
</head>
<body>
<?php
$access_granted_wkl = $_SESSION['access_granted_wk_leitung'] ?? false;
if ( ! $access_granted_wkl ) :
@@ -59,7 +64,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'wkl';
@@ -320,7 +325,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
</label>
</td>
<td>
<?php if (file_exists($baseDir . "/../test-wkvs/rechnungen/" . intval($row['order_id']) . ".pdf")) : ?>
<?php if (file_exists($baseDir . "/../private-files/rechnungen/" . intval($row['order_id']) . ".pdf")) : ?>
<a href="/intern/wk-leitung/rechnungen_viewer?order_id=<?= intval($row['order_id']) ?>" target="_blank">
<?= intval($row['order_id']) ?>
</a>
@@ -375,6 +380,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
<?php endif; ?>
<script>
const csrf_token = "<?= $csrf_token ?>";
const $input = $('#scorNumber');
const $rawInput = $('#scorNumberRaw');
@@ -414,6 +420,7 @@ $('#submitScorNumber').on('click', function(e) {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
csrf_token,
scor: SCOR
})
})
@@ -456,6 +463,8 @@ $('.bulkSelectSubmit').on('click', function (e) {
params.append('ids[]', id);
});
params.append('csrf_token', csrf_token);
fetch('/intern/scripts/rechnungen/ajax_delete_order.php', {
method: 'POST',

View File

@@ -1,13 +1,17 @@
<?php
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
if (!isset($_GET['order_id']) || intval($_GET['order_id']) < 1) {
echo json_encode(['success' => false, 'message' => 'Keine Id angegeben']);
http_response_code(422);

View File

@@ -1,8 +1,5 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
// Show all errors except deprecation notices (these come from vendor libraries
@@ -10,17 +7,25 @@ ini_set('display_startup_errors', 1);
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
$logintype = 'wk_leitung';
require_once $baseDir . '/../scripts/session_functions.php';
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
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 {
@@ -99,6 +104,9 @@ foreach ($allAbt as $abt) {
<link rel="stylesheet" href="/intern/css/riegeneinteilung.css">
<link rel="icon" type="png" href="/intern/img/icon.png">
<link href="/files/fonts/fonts.css" rel="stylesheet">
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
<script src="/intern/js/jquery/jquery-ui.min.js"></script>
<script src="/intern/js/jquery/jquery.ui.touch-punch.min.js"></script>
<script src="/intern/js/custom-msg-display.js"></script>
</head>
@@ -367,15 +375,11 @@ foreach ($allAbt as $abt) {
</div>
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
<script src="/intern/js/jquery/jquery-ui.min.js"></script>
<script src="/intern/js/jquery/jquery.ui.touch-punch.min.js"></script>
<link rel="stylesheet" href="/intern/js/jquery/jquery-ui.css">
<script>
$(function () {
const csrf_token = "<?= $csrf_token ?>";
function updateCounters() {
$(".geraet-table").each(function () {
const count = $(this).find("tr.turnerin-row").length;
@@ -453,6 +457,7 @@ $(function () {
url: "/intern/scripts/riegeneinteilung/ajax_update_turnerin.php",
method: "POST",
data: {
csrf_token,
turnerin_id: turnerinId,
abteilung: newAbt,
geraet: newGeraet
@@ -470,6 +475,7 @@ $(function () {
url: "/intern/scripts/riegeneinteilung/ajax_update_turnerin.php",
method: "POST",
data: {
csrf_token,
turnerin_id: turnerinId,
abteilung: newAbt,
geraet: newGeraet
@@ -479,6 +485,7 @@ $(function () {
}
const payload = {
csrf_token,
new: newIndexes(newTable),
old: newTable.is(oldTable) ? [] : newIndexes(oldTable)
};
@@ -486,8 +493,7 @@ $(function () {
$.ajax({
url: "/intern/scripts/riegeneinteilung/ajax_update_start_indexes.php",
method: "POST",
contentType: "application/json",
data: JSON.stringify(payload),
data: payload,
success: function () {
console.log("Order saved");
},
@@ -619,6 +625,7 @@ $(function () {
url: "/intern/scripts/riegeneinteilung/ajax_delete_specific_abt.php",
method: "POST",
data: {
csrf_token,
abt: $(this).data('abt')
}
})
@@ -639,6 +646,7 @@ $(function () {
url: "/intern/scripts/riegeneinteilung/ajax_change_number_of_abt.php",
method: "POST",
data: {
csrf_token,
anz_abt: $(this).val()
}
})
@@ -657,7 +665,10 @@ $(function () {
$.ajax({
url: "/intern/scripts/riegeneinteilung/ajax_auto_riegeneinteilung.php",
method: "POST"
method: "POST",
data: {
csrf_token
}
})
.done(function (data, textStatus, jqXHR) {
if (jqXHR.status === 201) {

74
www/liveScoring/index.php Normal file
View File

@@ -0,0 +1,74 @@
<?php
/*
ini_set('display_errors', 1);
$baseDir = $_SERVER['DOCUMENT_ROOT'];
require $baseDir .'/../scripts/db/db-verbindung-script-guest.php';
require $baseDir . "/../scripts/db/db-tables.php";
$stmt = $guest->prepare("SELECT
u.id,
u.name,
u.vorname,
u.programm,
u.verein
FROM $tableTurnerinnen u
WHERE (u.bezahlt = 2 OR u.bezahltoverride = 5)");
$stmt->execute();
$result = $stmt->get_result();
$tures = $result->fetch_all(MYSQLI_ASSOC);
$stmt->close();
$indexedTures = array_column($tures, null, 'id');
$stmt = $guest->prepare("SELECT `note_bezeichnung_id`, `geraet_id`, `person_id`, `run_number`, `public_value`
FROM $tableNoten
WHERE `is_public` = 1
AND `jahr` = 2026");
$stmt->execute();
$result = $stmt->get_result();
$dbNoten = $result->fetch_all(MYSQLI_ASSOC);
$stmt->close();
$indexedNoten = array_column($dbNoten, null, 'person_id');
$stmt = $guest->prepare("SELECT `id` FROM $tableNotenBezeichnungen");
$stmt->execute();
$result = $stmt->get_result();
$dbNotenBez = $result->fetch_all(MYSQLI_ASSOC);
$stmt->close();
$indexedNotenBez = array_column($dbNotenBez, null, 'person_id');
?>
<table>
<?php foreach ($indexedTures as $t) : ?>
<tr>
<td><?= $t['name'] ?>, <?= $t['vorname'] ?></td>
<td><?= $t['programm'] ?></td>
<td><?= $t['verein'] ?></td>
<?php foreach ($indexedNotenBez as $t) : ?>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</table>
*/