1998 lines
101 KiB
PHP
1998 lines
101 KiB
PHP
<?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);
|
||
|
||
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_trainer = check_user_permission('trainer', true) ?? false;
|
||
|
||
if (!$access_granted_trainer):
|
||
|
||
$logintype = 'trainer';
|
||
|
||
require $baseDir . '/../scripts/login/login.php';
|
||
|
||
$logintype = '';
|
||
|
||
else:
|
||
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="de">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<link rel="icon" type="png" href="/intern/img/icon.png">
|
||
<title>Intern - Trainer</title>
|
||
|
||
<link rel="stylesheet" href="/intern/css/trainer.css">
|
||
<link rel="stylesheet" href="/intern/css/sidebar.css">
|
||
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
|
||
<link href="/files/fonts/fonts.css" rel="stylesheet">
|
||
<script src="/intern/js/custom-msg-display.js"></script>
|
||
<script src="/intern/js/custom-select.js"></script>
|
||
<link rel="stylesheet" href="/intern/css/custom-select.css">
|
||
<link rel="stylesheet" href="/intern/css/custom-msg-display.css">
|
||
<link rel="stylesheet" href="/intern/css/user.css">
|
||
|
||
<!-- Self hosted Flatpickr -->
|
||
<link rel="stylesheet" href="/intern/css/flatpickr/flatpickr.min.css">
|
||
<script src="/intern/js/flatpickr/flatpickr.min.js"></script>
|
||
<script src="/intern/js/flatpickr/de.min.js"></script>
|
||
<script src="/intern/js/flatpickr/fr.min.js"></script>
|
||
<script src="/intern/js/flatpickr/it.min.js"></script>
|
||
</head>
|
||
|
||
<body class="trainer">
|
||
<?php
|
||
|
||
require $baseDir . '/../scripts/db/db-functions.php';
|
||
require $baseDir . '/../scripts/db/db-tables.php';
|
||
|
||
|
||
|
||
$type = 'tr';
|
||
|
||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||
|
||
if ($dbconnection['success'] !== true) {
|
||
echo 'Critical DB Error.';
|
||
exit;
|
||
}
|
||
|
||
$currentPage = 'trainer';
|
||
|
||
require $baseDir . '/../scripts/sidebar/sidebar.php';
|
||
|
||
function createPaystatusSvg(int $type, int $dataId, string $classes = ""): string
|
||
{
|
||
switch ($type) {
|
||
case 4:
|
||
return '<div class="bezahlstatus paymentPayed ' . $classes . '" data-id=""><span class="paymentStatus"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10"/><path d="M8 12l3 3 5-6"/></svg><span>Bezahlt</span></span></div>';
|
||
|
||
case 3:
|
||
return '<div class="bezahlstatus paymentProcess ' . $classes . '" data-id="' . $dataId . '" title="Zum Warenkorb hinzufügen"><span class="paymentStatus"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l3 3"/></svg><span>In Bearbeitung</span></span></div>';
|
||
|
||
case 2:
|
||
return '<div class="bezahlstatus paymentPartiallyOpen addTurnerinToWarenkorb ' . $classes . '" data-id="' . $dataId . '" title="Zum Warenkorb hinzufügen"><span class="paymentStatus"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10"/><path d="M15 9l-6 6M9 9l6 6"/></svg><span>Partiell bezahlt</span></span></div>';
|
||
|
||
case 1:
|
||
return '<div class="bezahlstatus paymentOpen addTurnerinToWarenkorb ' . $classes . '" data-id="' . $dataId . '" title="Zum Warenkorb hinzufügen"><span class="paymentStatus"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10"/><path d="M15 9l-6 6M9 9l6 6"/></svg><span>Nicht bezahlt</span></span></div>';
|
||
|
||
case 6:
|
||
return '<div class="tooltip-container">
|
||
<div class="bezahlstatus paymentAdmin">A</div>
|
||
<div class="tooltip" role="tooltip">Durch WK-Leitung überschrieben</div>
|
||
</div>';
|
||
default:
|
||
return '';
|
||
}
|
||
}
|
||
|
||
$svgbezahlt = '<div class="bezahlstatus paymentPayed" data-id=""><span class="paymentStatus"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10"/><path d="M8 12l3 3 5-6"/></svg><span>Bezahlt</span></span></div>';
|
||
$svgpending = '<div class="bezahlstatus paymentProcess addTurnerinToWarenkorb" data-id="" title="Zum Warenkorb hinzufügen"><span class="paymentStatus"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l3 3"/></svg><span>In Bearbeitung</span></span></div>';
|
||
$svgnichtbezahlt = '<div class="bezahlstatus paymentOpen addTurnerinToWarenkorb" data-id="" title="Zum Warenkorb hinzufügen"><span class="paymentStatus"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10"/><path d="M15 9l-6 6M9 9l6 6"/></svg><span>Nicht bezahlt</span></span></div>';
|
||
$svg_cart = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24"><path d="M7 18c-1.104 0-1.99.896-1.99 2S5.896 22 7 22s2-.896 2-2-.896-2-2-2zm10 0c-1.104 0-1.99.896-1.99 2s.886 2 1.99 2 2-.896 2-2-.896-2-2-2zM7.01 14l.94-2h7.72c.75 0 1.41-.41 1.74-1.03l3.58-6.49A1 1 0 0019 3H5.21l-.94-2H1v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.11.89 2 2 2H19v-2H7.42c-.14 0-.25-.11-.25-.25l.02-.1z"/></svg>';
|
||
|
||
$disciplines = db_select($mysqli, $db_tabelle_disziplinen, '*', '', [], 'start_index ASC');
|
||
|
||
$indexedDisciplines = array_column($disciplines, null, 'id');
|
||
|
||
$vereine_db = db_select($mysqli, $db_tabelle_vereine, "`verein`, `konto`, `id`", "", [], "verein ASC");
|
||
|
||
$vereine_kontos = array_column($vereine_db, 'konto', 'verein');
|
||
|
||
$vereine_to_ids = array_column($vereine_db, 'id', 'verein');
|
||
|
||
$vereine = array_keys($vereine_kontos);
|
||
|
||
$current_year = date('Y');
|
||
$monat = date('n');
|
||
if ($monat > 6)
|
||
$current_year++;
|
||
|
||
$dbProgramme = db_select($mysqli, $db_tabelle_kategorien, '`id`, `programm`, `order_index`, `preis`', 'aktiv = ?', [1], 'order_index ASC');
|
||
|
||
$programmes = array_column($dbProgramme, 'programm', 'id');
|
||
|
||
$order_index_kats = array_column($dbProgramme, 'order_index', 'programm');
|
||
|
||
$preise_kats_id = array_column($dbProgramme, 'preis', 'id');
|
||
|
||
$preise_kats = array_column($dbProgramme, 'preis', 'programm');
|
||
|
||
$userid = (int)$_SESSION['user_id_trainer'] ?? 0;
|
||
$arrayfreigaben = [];
|
||
|
||
|
||
if ($userid > 0) {
|
||
$freigabe_json = db_get_var($mysqli, "SELECT freigabe FROM $db_tabelle_intern_benutzende WHERE id = ?", [$userid]);
|
||
|
||
if (is_string($freigabe_json) && $freigabe_json !== '') {
|
||
$arrayfreigaben = json_decode($freigabe_json, true) ?: [];
|
||
|
||
$arrayfreigaben = $arrayfreigaben['freigabenTrainer'] ?? [];
|
||
}
|
||
}
|
||
|
||
if (!empty($arrayfreigaben)) {
|
||
$selectedverein = $_SESSION['selectedFreigabeTrainer'] ?? '';
|
||
|
||
if (!in_array($selectedverein, $arrayfreigaben)) {
|
||
$selectedverein = $arrayfreigaben[0];
|
||
$_SESSION['selectedFreigabeTrainer'] = $selectedverein;
|
||
}
|
||
}
|
||
|
||
$is_admin = $selectedverein === "admin";
|
||
|
||
require $baseDir . "/../scripts/trainer/post-handler.php";
|
||
|
||
$timeZone = new \DateTimeZone('Europe/Zurich');
|
||
|
||
$formatter = new \IntlDateFormatter(
|
||
'de_CH',
|
||
\IntlDateFormatter::FULL,
|
||
\IntlDateFormatter::NONE,
|
||
$timeZone,
|
||
null,
|
||
'd. MMMM YYYY'
|
||
);
|
||
|
||
$sortprio = [];
|
||
|
||
$displayLogo = $_SESSION['logoDisplay'] ?? true;
|
||
|
||
$rechnungenPostversand = db_get_variable($mysqli, $db_tabelle_var, ['rechnungenPostversand']);
|
||
|
||
$rechnungenPostversandKosten = db_get_variable($mysqli, $db_tabelle_var, ['rechnungenPostversandKosten']);
|
||
|
||
$personEinzahl = db_get_variable($mysqli, $db_tabelle_var, ['personEinzahl']);
|
||
|
||
if ($personEinzahl === null) $personEinzahl = 'Person';
|
||
|
||
$personMehrzahl = db_get_variable($mysqli, $db_tabelle_var, ['personMehrzahl']);
|
||
|
||
if ($personMehrzahl === null) $personMehrzahl = 'Personen';
|
||
|
||
$entries = $is_admin ? db_select($mysqli, $db_tabelle_teilnehmende, "*", '', [], "programm ASC, verein ASC, name ASC, vorname ASC") ?? [] : db_select($mysqli, $db_tabelle_teilnehmende, "*", 'verein = ?', [$selectedverein], "programm ASC, verein ASC, name ASC, vorname ASC") ?? [];
|
||
|
||
$grouped = [];
|
||
|
||
foreach ($entries as $entry) {
|
||
$key = $entry['programm'];
|
||
$grouped[$key][] = $entry;
|
||
}
|
||
|
||
$indexed_entries = array_column($entries, null, 'id');
|
||
|
||
$idsEntriesArray = array_keys($indexed_entries);
|
||
|
||
$placeholders = '';
|
||
|
||
if (!empty($idsEntriesArray)) {
|
||
$placeholders = implode(', ', array_fill(0, count($idsEntriesArray), '?'));
|
||
|
||
$sqlQuery = "SELECT
|
||
paf.`person_id`,
|
||
paf.`geraet_id`,
|
||
paf.`audiofile_id`,
|
||
af.`file_name`,
|
||
af.`file_path`
|
||
FROM $db_tabelle_teilnehmende_audiofiles paf
|
||
LEFT JOIN $db_tabelle_audiofiles af
|
||
ON af.`id` = paf.`audiofile_id`
|
||
WHERE paf.`person_id` IN ($placeholders)
|
||
";
|
||
|
||
$stmt = $mysqli->prepare($sqlQuery);
|
||
|
||
$stmt->bind_param(str_repeat('i', count($idsEntriesArray)), ...$idsEntriesArray);
|
||
|
||
$stmt->execute();
|
||
|
||
$result = $stmt->get_result();
|
||
|
||
$audiofilesPersonen = $result->fetch_all(MYSQLI_ASSOC);
|
||
|
||
$stmt->close();
|
||
|
||
$indexedAudiofilesPersonen = [];
|
||
|
||
foreach ($audiofilesPersonen as $sAf) {
|
||
$indexedAudiofilesPersonen[$sAf['person_id']][$sAf['geraet_id']] = ["audiofile_id" => $sAf['audiofile_id'], "file_name" => $sAf['file_name'], "file_path" => $sAf['file_path']];
|
||
}
|
||
}
|
||
|
||
uksort($grouped, function ($a, $b) use ($order_index_kats) {
|
||
$a_index = $order_index_kats[$a] ?? PHP_INT_MAX;
|
||
$b_index = $order_index_kats[$b] ?? PHP_INT_MAX;
|
||
return $a_index <=> $b_index;
|
||
});
|
||
|
||
$total_count = 0;
|
||
|
||
$invalidProgrammes = false;
|
||
|
||
?>
|
||
|
||
<div class="internMenuDiv">
|
||
<div class="headerDivWarenkorb">
|
||
<h3 class="headingStartgebuerenTabelle">Warenkorb Startgebühren</h3>
|
||
<button class="closeWarenkorb">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M18 6L6 18M6 6l12 12"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
|
||
|
||
|
||
<?php
|
||
|
||
$iduser = $_SESSION['user_id_trainer'];
|
||
|
||
$all_warenkorb_items = db_select($mysqli, $db_tabelle_warenkorb_startgebueren, '`item_id`', '`user_id` = ?', [$iduser]);
|
||
|
||
$basket_entries = [];
|
||
$subtotalprice = 0;
|
||
$abzuege = 0;
|
||
|
||
$vereine_warenkorb = [];
|
||
|
||
foreach ($all_warenkorb_items as $row) {
|
||
$teiln_row = $indexed_entries[$row['item_id']] ?? [];
|
||
$basket_entries[$row['item_id']] = $teiln_row;
|
||
$kat = $teiln_row['programm'] ?? '';
|
||
$bezahlt_person = (float) $teiln_row['betrag_bezahlt'] ?? 0.00;
|
||
$startgebuer_kat = (float) ($preise_kats[$kat] ?? 0);
|
||
$startgebuer = $startgebuer_kat - $bezahlt_person;
|
||
$basket_entries[$row['item_id']]['startgebuer'] = $startgebuer;
|
||
$basket_entries[$row['item_id']]['has_part_payed'] = $bezahlt_person !== 0.00;
|
||
$verein = $teiln_row['verein'] ?? '';
|
||
$vereine_warenkorb[$verein] ??= 0.00;
|
||
$vereine_warenkorb[$verein] += $startgebuer;
|
||
$subtotalprice += $startgebuer;
|
||
}
|
||
|
||
foreach ($vereine_warenkorb as $verein => &$preis) {
|
||
$preis = min($preis, ($vereine_kontos[$verein] ?? 0));
|
||
if ($preis <= 0.00) unset($vereine_warenkorb[$verein]);
|
||
}
|
||
|
||
$totalprice = $subtotalprice - $abzuege;
|
||
|
||
uasort($basket_entries, fn($a, $b) => $a['name'] <=> $b['name']);
|
||
|
||
$basketIsEmptyClass = ($basket_entries && is_array($basket_entries) && count($basket_entries) > 0) ? '' : 'hidden';
|
||
$basketIsNotEmptyClass = ($basket_entries && is_array($basket_entries) && count($basket_entries) > 0) ? 'hidden' : '';
|
||
|
||
$basket_abzuege_is_empty_class = (count($vereine_warenkorb) > 0) ? '' : 'hidden';
|
||
|
||
?>
|
||
<div class="innerInternMenuDiv">
|
||
<table class="tableStartgebueren <?= $basketIsEmptyClass ?>">
|
||
<thead></thead>
|
||
<tbody class="tbodyStartGebueren">
|
||
<?php
|
||
if ($basket_entries && is_array($basket_entries) && count($basket_entries) > 0) :
|
||
foreach ($basket_entries as $entry) : ?>
|
||
<tr class="rowStartgebuer" data-id="<?= (int) $entry['id'] ?>">
|
||
<td class="cellStartgebuer"><b><?= htmlspecialchars($entry['name'] ?? '') ?></b>, <?= htmlspecialchars($entry['vorname'] ?? '') ?> | <?= htmlspecialchars($entry['programm'] ?? '') ?><?= $entry['has_part_payed'] ? ' (Red.)' : '' ?></td>
|
||
<td class="cellStartgebuer" data-type="startgebuer" data-value="<?= (float) $entry['startgebuer'] ?>" data-verein="<?= htmlspecialchars($entry['verein']) ?>">CHF <?= number_format($entry['startgebuer'], 2, '.', '') ?></td>
|
||
<td class="cellStartgebuer deleteStartgebuerCell" data-type="delete" data-id="<?= (int) $entry['id'] ?>">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
||
<polyline points="3 6 5 6 21 6"></polyline>
|
||
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
|
||
<line x1="10" y1="11" x2="10" y2="17"></line>
|
||
<line x1="14" y1="11" x2="14" y2="17"></line>
|
||
</svg>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach;
|
||
endif; ?>
|
||
<tr class="rowStartgebuerTotal">
|
||
<td>Kosten:</td>
|
||
<td class="totalStartgebueren" colspan="2" data-value="<?= $subtotalprice ?>">CHF <?= number_format($subtotalprice, 2, '.', '') ?></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<table class="tableAbzugeStartgebueren <?= $basket_abzuege_is_empty_class ?>">
|
||
<thead>
|
||
<tr>
|
||
<td colspan="3">
|
||
Abzüge
|
||
</td>
|
||
</tr>
|
||
</thead>
|
||
<tbody class="tbodyAbzuege">
|
||
<?php foreach ($vereine_warenkorb as $verein => $betrag) : ?>
|
||
<tr class="rowStartgebuer" data-id="<?= (int) $vereine_to_ids[$verein] ?>">
|
||
<td class="cellStartgebuer">Guthaben <b><?= htmlspecialchars($verein ?? '') ?></b></td>
|
||
<td class="cellStartgebuer" data-type="abzug" data-value="<?= (float) $betrag ?>" data-verein="<?= $verein ?>">CHF <?= number_format((float) $betrag, 2, '.', '') ?></td>
|
||
<td class="cellStartgebuer" data-id="<?= (int) $vereine_to_ids[$verein] ?>">
|
||
<label class="checkbox">
|
||
<input type="checkbox"
|
||
class="deactivateAbzug"
|
||
value="<?= (int) $vereine_to_ids[$verein] ?>">
|
||
<span class="checkbox-ui"></span>
|
||
</label>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<tr class="rowStartgebuerTotal">
|
||
<td>Abzüge:</td>
|
||
<td class="totalAbzuegeStartgebueren" colspan="2" data-value="<?= (float) $abzuege ?>">CHF <?= number_format((float) $abzuege, 2, '.', '') ?></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<table class="tableKostenTotal <?= $basketIsEmptyClass ?>">
|
||
<thead></thead>
|
||
<tbody class="tbodyTotal">
|
||
<tr class="rowKostenTotal">
|
||
<td>Total:</td>
|
||
<td class="totalKosten" colspan="2" data-value="<?= (float) $totalprice ?>">CHF <?= number_format((float) $totalprice, 2, '.', '') ?></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div>
|
||
<button id="checkoutButton" class="checkoutButton newBtn <?= $basketIsEmptyClass ?>">
|
||
<span>Daten für Rechnung eingeben</span>
|
||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 74 74" height="34" width="34">
|
||
<circle stroke-width="3" stroke="black" r="35.5" cy="37" cx="37"></circle>
|
||
<path fill="black"
|
||
d="M25 35.5C24.1716 35.5 23.5 36.1716 23.5 37C23.5 37.8284 24.1716 38.5 25 38.5V35.5ZM49.0607 38.0607C49.6464 37.4749 49.6464 36.5251 49.0607 35.9393L39.5147 26.3934C38.9289 25.8076 37.9792 25.8076 37.3934 26.3934C36.8076 26.9792 36.8076 27.9289 37.3934 28.5147L45.8787 37L37.3934 45.4853C36.8076 46.0711 36.8076 47.0208 37.3934 47.6066C37.9792 48.1924 38.9289 48.1924 39.5147 47.6066L49.0607 38.0607ZM25 38.5L48 38.5V35.5L25 35.5V38.5Z">
|
||
</path>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
|
||
<p id="textKeineStartgebuerenAusgewählt" class="<?= $basketIsNotEmptyClass ?>">Es wurden keine Startgebühren
|
||
ausgwählt</p>
|
||
|
||
</div>
|
||
|
||
<section class="bgSection">
|
||
<div class="headerDivTrainer">
|
||
<div class="headingPanelDiv">
|
||
<h2 class="headingPanel">Trainerpanel</h2>
|
||
<h3 class="headingPanelUser"><?= ucfirst($selectedverein) ?></h3>
|
||
</div>
|
||
<div class="menuWrapper">
|
||
<div class="trainerBurgerMenuDiv">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none"
|
||
stroke="var(--accent)" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="9" cy="21" r="1"></circle>
|
||
<circle cx="20" cy="21" r="1"></circle>
|
||
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
|
||
</svg>
|
||
</div>
|
||
<?php sidebarRender('button'); ?>
|
||
</div>
|
||
</div>
|
||
|
||
<?php
|
||
|
||
sidebarRender('modal');
|
||
|
||
if (!empty($programmes) && is_array($programmes)): ?>
|
||
|
||
<div class="editContainerDiv">
|
||
|
||
<h3 class="heading_edit_turnerin">
|
||
<?= isset($_POST['edit_id']) ? 'Daten aktualisieren' : $personEinzahl . ' hinzufügen' ?></h3>
|
||
|
||
<div class="editContainerDivInner">
|
||
<form action="" method="post">
|
||
<input type="hidden" name="csrf_token" value="<?= $csrf_token ?>">
|
||
|
||
<?php if (isset($_POST['edit_id'])) { ?>
|
||
<input type="hidden" name="edit_id" value="<?= (int)$_POST['edit_id'] ?>">
|
||
<?php } ?>
|
||
|
||
<label for="nachname">Name:</label>
|
||
<input type="text" id="nachname" name="nachname" required
|
||
value="<?= htmlspecialchars($_POST['nachname'] ?? '') ?>">
|
||
|
||
<label for="vorname">Vorname:</label>
|
||
<input type="text" id="vorname" name="vorname" required
|
||
value="<?= htmlspecialchars($_POST['vorname'] ?? '') ?>">
|
||
|
||
<label>Geburtsdatum:</label>
|
||
<input type="text" name="geburtsdatum" id="geburtsdatum" class="flatpickr-input" placeholder="Tag. Monat Jahr"
|
||
required value="<?= htmlspecialchars($_POST['geburtsdatum'] ?? '') ?>">
|
||
|
||
<?php
|
||
|
||
$has_id_kat_post = isset($_POST['programm']);
|
||
|
||
$id_kat_post = (int) ($_POST['programm'] ?? 0);
|
||
|
||
?>
|
||
<label for="selectTriggerProgramm">Kategorie:</label>
|
||
<div class="customSelect <?= isset($_POST['edit_id']) ? 'programmEditing' : '' ?>" id="selectedOption">
|
||
<button type="button" id="selectTriggerProgramm" class="selectTrigger" aria-expanded="false">
|
||
<span
|
||
class="selectLabel placeholder"><?= $has_id_kat_post && array_key_exists($id_kat_post, $programmes) ? $programmes[$id_kat_post] ?? '' : 'Bitte auswählen…' ?></span>
|
||
<svg class="selectArrow" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'
|
||
height="14" width="14">
|
||
<path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2' stroke-linecap='round'
|
||
stroke-linejoin='round' />
|
||
</svg>
|
||
</button>
|
||
<ul class="selectOptions">
|
||
<?php foreach ($programmes as $id => $prog): ?>
|
||
<?php
|
||
$isSelected = $has_id_kat_post && $id === $id_kat_post;
|
||
?>
|
||
|
||
<li data-value="<?= $id ?>" class="<?= $isSelected ? 'selected' : '' ?>">
|
||
<?= $prog ?>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
<input type="hidden" name="programm" class="selectValue" value="<?= $id_kat_post ?>">
|
||
</div>
|
||
|
||
<?php if (!$is_admin): ?>
|
||
<label for="verein">Verein:</label>
|
||
<input type="text" id="verein" name="verein" required disabled
|
||
value="<?= htmlspecialchars($selectedverein); ?>">
|
||
<?php else: ?>
|
||
|
||
<?php
|
||
|
||
$hasPostVerein = isset($_POST['verein']);
|
||
|
||
$postVerein = htmlspecialchars($_POST['verein'] ?? '');
|
||
|
||
?>
|
||
|
||
<label for="selectTriggerVerein">Verein:</label>
|
||
<div class="customSelect" id="selectedOption">
|
||
<button type="button" id="selectTriggerVerein" class="selectTrigger" aria-expanded="false">
|
||
<span
|
||
class="selectLabel placeholder"><?= $hasPostVerein ? $postVerein : 'Bitte auswählen…' ?></span>
|
||
<svg class="selectArrow" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'
|
||
height="14" width="14">
|
||
<path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2' stroke-linecap='round'
|
||
stroke-linejoin='round' />
|
||
</svg>
|
||
</button>
|
||
<ul class="selectOptions">
|
||
<?php foreach ($vereine as $sverein): ?>
|
||
<?php $isSelected = $hasPostVerein && $sverein === $postVerein; ?>
|
||
|
||
<li data-value="<?= $sverein ?>" class="<?= $isSelected ? 'selected' : '' ?>">
|
||
<?= $sverein ?>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
<input type="hidden" name="verein" class="selectValue" value="<?= $postVerein ?>">
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($is_admin && isset($_GET['edit_id']) && is_numeric($_GET['edit_id']) && !isset($_POST['submit_turnerinnen_form'])): ?>
|
||
|
||
<?php
|
||
|
||
$araryBezahlt = [
|
||
0 => 'Automatisch',
|
||
1 => 'Nicht bezahlt',
|
||
2 => 'Partiell bezahlt',
|
||
3 => 'In Bearbeitung',
|
||
4 => 'Bezahlt'
|
||
];
|
||
|
||
$hasPostBezahlt = isset($_POST['bezahltOverride']) && in_array((int)$_POST['bezahltOverride'], array_keys($araryBezahlt));
|
||
|
||
$postBezahlt = (int)$_POST['bezahltOverride'] ?? 0;
|
||
|
||
$postStrBezahlt = $araryBezahlt[$postBezahlt];
|
||
|
||
?>
|
||
|
||
<label for="selectTriggerBezahltAdmin">Bezahlstatus (override):</label>
|
||
<div class="customSelect" id="selectedOption">
|
||
<button type="button" id="selectTriggerBezahltAdmin" class="selectTrigger"
|
||
aria-expanded="false">
|
||
<span
|
||
class="selectLabel placeholder"><?= $hasPostBezahlt ? $postStrBezahlt : 'Bitte auswählen…' ?></span>
|
||
<svg class="selectArrow" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'
|
||
height="14" width="14">
|
||
<path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2' stroke-linecap='round'
|
||
stroke-linejoin='round' />
|
||
</svg>
|
||
</button>
|
||
<ul class="selectOptions">
|
||
<?php foreach ($araryBezahlt as $bezahltStatus => $strBezahltStatus): ?>
|
||
<?php
|
||
$isSelected = $hasPostBezahlt && $bezahltStatus === $postBezahlt;
|
||
?>
|
||
|
||
<li data-value="<?= $bezahltStatus ?>" class="<?= $isSelected ? 'selected' : '' ?>">
|
||
<?= $strBezahltStatus ?>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
<input type="hidden" name="bezahltOverride" class="selectValue" value="<?= $postBezahlt ?>">
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<input type="submit" name="submit_turnerinnen_form"
|
||
value="<?= isset($_POST['edit_id']) ? 'Änderung speichern' : 'Daten speichern'; ?>">
|
||
<?php if (isset($_GET['edit_id'])) : ?>
|
||
<a class="emptyEditForm" href="/intern/trainer">Formular leeren</a>
|
||
<?php endif; ?>
|
||
</form>
|
||
|
||
<?php if (!$is_admin) : ?>
|
||
<form class="form_excel" action="" method="post" enctype="multipart/form-data">
|
||
<h3>Mehrere <?= htmlspecialchars($personMehrzahl) ?> hinzufügen</h3>
|
||
|
||
<ol class="listExcelForm">
|
||
<li>
|
||
Vorlage herunterladen: <br>
|
||
<a href="/files/WKVS_Vorlage_Upload_Personen_Bulk.xlsx" download>Vorlage Tabelle</a>
|
||
</li>
|
||
<li>
|
||
Heruntergeladene Tablle den Anweisungen nach ausfüllen.
|
||
</li>
|
||
<li>
|
||
Ausgefüllte Vorlage hochladen:
|
||
<input type="file" name="xlsx_file" accept=".xlsx" required>
|
||
</li>
|
||
<li>
|
||
Datensätze importieren:
|
||
<button type="submit">Importieren</button>
|
||
</li>
|
||
</ol>
|
||
|
||
|
||
</form>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
<?php if (isset($excelMessage) && !empty($excelMessage)) { ?>
|
||
<p><?= htmlspecialchars($excelMessage); ?></p>
|
||
<?php } ?>
|
||
|
||
<?php else: ?>
|
||
<div class="allTurnerinenDiv">
|
||
<h3>Eingabetool noch nicht freigeschalten</h3>
|
||
<p>(Keine aktiven Kategorien)</p>
|
||
</div>
|
||
<?php exit; ?>
|
||
<?php endif; ?>
|
||
|
||
<div class="allTurnerinenDiv">
|
||
<h3 class="headingAlleTurnerinnen">Alle <?= $personMehrzahl ?>:</h3>
|
||
|
||
<?php if (!empty($grouped)): ?>
|
||
<form action="" method="post" id="bulk-action-form">
|
||
<input type="hidden" name="csrf_token" id="bulc_nonce" value="<?= $csrf_token ?>">
|
||
<div class="bulkSelectDiv">
|
||
<p class="selectTriggerBulkAction">Bulk Select:</p>
|
||
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 15px;">
|
||
|
||
|
||
<?php
|
||
|
||
$araryBezahlt = [
|
||
0 => 'Automatisch',
|
||
1 => 'Nicht bezahlt',
|
||
2 => 'Partiell bezahlt',
|
||
3 => 'In Bearbeitung',
|
||
4 => 'Bezahlt'
|
||
];
|
||
|
||
?>
|
||
|
||
<div class="customSelect" id="selectedOption">
|
||
<button type="button" id="selectTriggerBulkAction" class="selectTrigger"
|
||
aria-expanded="false">
|
||
<span class="selectLabel placeholder">Aktion auswählen</span>
|
||
<svg class="selectArrow" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'
|
||
fill='none' height="14" width="14">
|
||
<path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2'
|
||
stroke-linecap='round' stroke-linejoin='round' />
|
||
</svg>
|
||
</button>
|
||
<ul class="selectOptions">
|
||
<li data-value="changeKat" class="">Kategorie ändern</li>
|
||
<?php if ($is_admin): ?>
|
||
<li data-value="changeEntryFee" class="">Bezahlt Status ändern</li>
|
||
<?php endif; ?>
|
||
<li data-value="payEntryFee" class="">Startgebühren bezahlen</li>
|
||
<li data-value="deletePersonen" class="">Personen löschen</li>
|
||
</ul>
|
||
<input type="hidden" name="bulk_action_select" id="bulk_action_select" class="selectValue"
|
||
value="">
|
||
</div>
|
||
|
||
<div class="customSelect customSelectBulkActionProgramm hidden" id="selectedOption">
|
||
<button type="button" id="selectTriggerBulkActionProgramm" class="selectTrigger"
|
||
aria-expanded="false">
|
||
<span class="selectLabel placeholder">Kategorie ändern zu...</span>
|
||
<svg class="selectArrow" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'
|
||
fill='none' height="14" width="14">
|
||
<path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2'
|
||
stroke-linecap='round' stroke-linejoin='round' />
|
||
</svg>
|
||
</button>
|
||
<ul class="selectOptions">
|
||
<?php foreach ($programmes as $id => $prog): ?>
|
||
|
||
<li data-value="<?= $id ?>" class="">
|
||
<?= $prog ?>
|
||
</li>
|
||
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
<input type="hidden" name="bulk_action_programm" id="bulk_action_programm"
|
||
class="selectValue" value="">
|
||
</div>
|
||
|
||
|
||
<?php if ($is_admin): ?>
|
||
|
||
<div class="customSelect customSelectBulkActionBezahlt hidden" id="selectedOption">
|
||
<button type="button" id="selectTriggerBulkActionProgramm" class="selectTrigger"
|
||
aria-expanded="false">
|
||
<span class="selectLabel placeholder">Bezahlstatus ändern zu...</span>
|
||
<svg class="selectArrow" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'
|
||
fill='none' height="14" width="14">
|
||
<path d='M6 9L12 15L18 9' stroke='currentColor' stroke-width='2'
|
||
stroke-linecap='round' stroke-linejoin='round' />
|
||
</svg>
|
||
</button>
|
||
<ul class="selectOptions">
|
||
<?php foreach ($araryBezahlt as $bezahltStatus => $strBezahltStatus): ?>
|
||
|
||
<li data-value="<?= $bezahltStatus ?>" class="">
|
||
<?= $strBezahltStatus ?>
|
||
</li>
|
||
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
<input type="hidden" name="bulk_action_bezahlt" id="bulk_action_bezahlt" class="selectValue"
|
||
value="">
|
||
</div>
|
||
|
||
<?php endif; ?>
|
||
|
||
<input type="submit" name="apply_bulk_action" class="bulk-select-submit" value="Anwenden">
|
||
</div>
|
||
|
||
<script>
|
||
$('#bulk_action_programm').addClass("hidden");
|
||
$('.bulk-select-submit').addClass("hidden");
|
||
</script>
|
||
</div>
|
||
<?php
|
||
foreach ($grouped as $programm => $entries_group):
|
||
$count = count($entries_group);
|
||
$total_count += $count;
|
||
?>
|
||
<div class="singleProgDiv">
|
||
<h2 class="titleSingleProg"><?= htmlspecialchars($programm) ?></h2>
|
||
<div class="tableWraperOverflowY">
|
||
<table class="widefat striped wkvsTabelle trainer">
|
||
<thead>
|
||
<tr>
|
||
<th style="width:20px;">
|
||
<label class="checkbox">
|
||
<input type="checkbox"
|
||
id="check_all_<?= str_replace(" ", "-", $programm); ?>">
|
||
<span class="checkbox-ui"></span>
|
||
</label>
|
||
</th>
|
||
<th>Name</th>
|
||
<th>Geburtsdatum</th>
|
||
<?php if ($is_admin) { ?>
|
||
<th>Verein</th> <?php } ?>
|
||
<th>Startgebühr</th>
|
||
<?php foreach ($indexedDisciplines as $dindex => $sDisc):
|
||
if ((int)$sDisc['audiofile'] === 1): ?>
|
||
<th class="notMobile">Musik <?= $sDisc['name'] ?></th>
|
||
<?php endif;
|
||
endforeach; ?>
|
||
<th>Aktionen</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($entries_group as $row): ?>
|
||
<tr data-person-id="<?= (int)$row['id'] ?>">
|
||
<td>
|
||
<label class="checkbox">
|
||
<input type="checkbox" name="turnerin_ids[]"
|
||
class="row_check_<?= str_replace(" ", "-", htmlspecialchars($programm)); ?>"
|
||
value="<?= (int)$row['id']; ?>">
|
||
<span class="checkbox-ui"></span>
|
||
</label>
|
||
</td>
|
||
<td <?php if (!in_array(htmlspecialchars($row['programm']), $programmes)) : ?>
|
||
style="background-color: #f00;" title="Ungültige Kategorie"
|
||
<?php $invalidProgrammes = true; endif; ?>><b><?= htmlspecialchars($row['name']); ?></b>, <?= htmlspecialchars($row['vorname']); ?></td>
|
||
<td><?= htmlspecialchars($formatter->format(new \DateTimeImmutable($row['geburtsdatum'], $timeZone))) ?></td>
|
||
<?php if ($is_admin) { ?>
|
||
<td><?= htmlspecialchars($row['verein']); ?></td> <?php } ?>
|
||
<td>
|
||
<div class="paymentDivWraper">
|
||
<?php
|
||
$value = ((int)$row['bezahltoverride'] !== 0)
|
||
? htmlspecialchars($row['bezahltoverride'])
|
||
: htmlspecialchars($row['bezahlt']);
|
||
?>
|
||
|
||
<?= createPaystatusSvg((int) $value, $row['id'], "hoverPaymentInfo") ?>
|
||
|
||
<?php if ((int)$row['bezahltoverride'] !== 0): ?>
|
||
<?= createPaystatusSvg(6, $row['id']) ?>
|
||
<?php endif; ?>
|
||
</div>
|
||
</td>
|
||
|
||
<?php foreach ($indexedDisciplines as $dindex => $sDisc):
|
||
if ((int)$sDisc['audiofile'] === 1):
|
||
$hasMusic = isset($indexedAudiofilesPersonen[$row['id']][$sDisc['id']]);
|
||
$musicClass = $hasMusic ? 'hasMusic' : 'noMusic';
|
||
$musicText = $hasMusic ? ($indexedAudiofilesPersonen[$row['id']][$sDisc['id']]['file_name'] ?? 'ERROR') : 'Musik hochladen';
|
||
?>
|
||
<td>
|
||
<div class="musicDivWraper">
|
||
<div class="musicStatus noMusic">
|
||
<div class="uploadmusic-container">
|
||
<label
|
||
style="cursor: pointer; display: flex; align-items: center; gap: 8px; margin: 0;">
|
||
<?php if ($hasMusic): ?>
|
||
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
|
||
viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||
stroke-width="2" stroke-linecap="round"
|
||
stroke-linejoin="round">
|
||
<path d="M23 4v6h-6"></path>
|
||
<path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path>
|
||
</svg>
|
||
<?php else: ?>
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
|
||
viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||
stroke-width="2" stroke-linecap="round"
|
||
stroke-linejoin="round">
|
||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
||
<polyline points="17 8 12 3 7 8"></polyline>
|
||
<line x1="12" y1="3" x2="12" y2="15"></line>
|
||
</svg>
|
||
|
||
<span class="label-music"><?= $musicText ?></span>
|
||
<?php endif; ?>
|
||
<input type="file" name="music_file" accept=".mp3,.wav,.ogg"
|
||
data-id="<?= $row['id'] ?>"
|
||
data-geraetid="<?= $sDisc['id'] ?>"
|
||
data-musicid="<?= $indexedAudiofilesPersonen[$row['id']][$sDisc['id']]['audiofile_id'] ?? 0 ?>"
|
||
style="display:none;" onchange="uploadFile(this)">
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<?php if ($hasMusic): ?>
|
||
<?php $musicFile = $indexedAudiofilesPersonen[$row['id']][$sDisc['id']]['file_path'] ?? '' ?>
|
||
<div class="musicStatus <?= $musicClass ?>">
|
||
<span class="label-music"
|
||
data-url="<?= $musicFile ?>"><?= $musicText ?></span>
|
||
</div>
|
||
<?php endif; ?>
|
||
</td>
|
||
<?php endif;
|
||
endforeach; ?>
|
||
<td style="min-width:150px;">
|
||
<div class="editDiv" style="display: flex; align-items: center; gap: 10px;">
|
||
<?php if (in_array($row['bezahlt'], [1,2]) && (int)$row['bezahltoverride'] !== 5) { ?>
|
||
<button class="addTurnerinToWarenkorb" type="submit"
|
||
aria-label="Zum Warenkarb hinzufügen" title="Zum Warenkarb hinzufügen"
|
||
data-id="<?= $row['id'] ?>">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22"
|
||
viewBox="0 0 24 24" fill="none" stroke="var(--accent)"
|
||
stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="9" cy="21" r="1"></circle>
|
||
<circle cx="20" cy="21" r="1"></circle>
|
||
<path
|
||
d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6">
|
||
</path>
|
||
</svg>
|
||
</button>
|
||
<?php } ?>
|
||
|
||
<a class="editPerson" href="?edit_id=<?= (int)$row['id']; ?>" aria-label="Bearbeiten"
|
||
title="Bearbeiten">
|
||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24"
|
||
width="24">
|
||
|
||
<path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25z"
|
||
fill="#536467ff" />
|
||
|
||
<path
|
||
d="M20.71 7.04a1.003 1.003 0 0 0 0-1.42l-2.34-2.34a1.003 1.003 0 0 0-1.42 0l-1.83 1.83 3.75 3.75 1.84-1.82z"
|
||
fill="var(--bg-top)" />
|
||
</svg>
|
||
</a>
|
||
|
||
<button type="button"
|
||
onclick="confirmDelete(<?= $row['id'] ?>, '<?= $row['name'] ?>, <?= $row['vorname'] ?>')"
|
||
aria-label="Löschen" title="Löschen">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22"
|
||
viewBox="0 0 24 24" fill="none" stroke="var(--accent)"
|
||
stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
||
<polyline points="3 6 5 6 21 6"></polyline>
|
||
<path
|
||
d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2">
|
||
</path>
|
||
<line x1="10" y1="11" x2="10" y2="17"></line>
|
||
<line x1="14" y1="11" x2="14" y2="17"></line>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<p><?= $count ?> <?= ($count > 1) ? $personMehrzahl : $personEinzahl ?></p>
|
||
</div>
|
||
<?php
|
||
endforeach;
|
||
|
||
?>
|
||
<p><strong>Gesamtanzahl <?= $personMehrzahl ?>: <?= $total_count; ?></strong></p>
|
||
</form>
|
||
<?php else: ?>
|
||
<p>Noch keine Datensätze vorhanden.</p>
|
||
<?php endif; ?>
|
||
<div class="msgDiv"></div>
|
||
<div class="tooltipPaymentStatusContainer opacity0">
|
||
<div class="tooltipPaymentStatus" role="tooltip">
|
||
<?= createPaystatusSvg(1, 0) ?>
|
||
<span>Noch keine Rechnung ausgestellt</span>
|
||
|
||
<?= createPaystatusSvg(2, 0) ?>
|
||
<span>Startgebühren teilweise bezahlt, Restbetrag noch zu zahlen</span>
|
||
|
||
<?= createPaystatusSvg(3, 0) ?>
|
||
<span>Rechnung ausgestellt, warte auf Zahlungseingang /
|
||
Verarbeitung</span>
|
||
|
||
<?= createPaystatusSvg(4, 0) ?>
|
||
<span>Zahlung bestätigt, für Wettkampf freigegeben</span>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<div id="musicDiv">
|
||
<div class="audio-player">
|
||
<audio id="sorceAudioPreview" src=""></audio>
|
||
|
||
<div class="controls">
|
||
<button id="play-pause-btn" class="btn">Play</button>
|
||
|
||
<div class="progress-container">
|
||
<span id="current-time">0:00</span>
|
||
<input type="range" id="seek-bar" value="0" max="100">
|
||
<span id="duration">0:00</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="paymentFormContainer" class="payment-modal-overlay" style="display:none;">
|
||
<div class="payment-modal-content">
|
||
<div class="payment-modal-header">
|
||
<h2>Zahldaten</h2>
|
||
<span class="closePaymentForm">×</span>
|
||
</div>
|
||
<p class="payment-modal-desc">Die folgenden Daten werden für die Verbuchung der Zahlung benötigt. <br>Die
|
||
Rechnung wird bei uns gespeichert (Art 958f Abs 1 ZGB).</p>
|
||
<div class="paymentFormOverflowWrapper">
|
||
<form id="paymentForm">
|
||
<div class="fullinput-row">
|
||
<div class="fullinput-group">
|
||
<label for="vorname" class="requiredInput">Vorname</label>
|
||
<input type="text" id="vorname" name="vorname" class="fullinput" required
|
||
placeholder="Vorname" autocomplete="given-name">
|
||
</div>
|
||
<div class="fullinput-group">
|
||
<label for="name" class="requiredInput">Name</label>
|
||
<input type="text" id="name" name="name" class="fullinput" required placeholder="Nachname"
|
||
autocomplete="family-name">
|
||
</div>
|
||
</div>
|
||
<div class="fullinput-row">
|
||
<div class="fullinput-group">
|
||
<label for="strasse" class="requiredInput">Strasse</label>
|
||
<input type="text" id="strasse" name="strasse" class="fullinput" required
|
||
placeholder="Strasse">
|
||
</div>
|
||
<div class="fullinput-group" style="flex: 0 0 80px;">
|
||
<label for="hausnummer" class="requiredInput">Nr.</label>
|
||
<input type="text" id="hausnummer" name="hausnummer" class="fullinput" required
|
||
placeholder="Nr.">
|
||
</div>
|
||
</div>
|
||
<div class="fullinput-row">
|
||
<div class="fullinput-group" style="flex: 0 0 100px;">
|
||
<label for="plz" class="requiredInput">PLZ</label>
|
||
<input type="text" id="plz" name="plz" class="fullinput" required placeholder="PLZ">
|
||
</div>
|
||
<div class="fullinput-group">
|
||
<label for="ort" class="requiredInput">Ort</label>
|
||
<input type="text" id="ort" name="ort" class="fullinput" required placeholder="Ort">
|
||
</div>
|
||
</div>
|
||
<?php if ($rechnungenPostversand): ?>
|
||
<label class="checkbox payment-checkbox-label">
|
||
<input type="checkbox" id="postversand" name="postversand">
|
||
<span class="checkbox-ui"></span>
|
||
<span>Postversand der Rechnung (Aufpreis CHF
|
||
<?= number_format((float)$rechnungenPostversandKosten ?? 0, 2) ?>)</span>
|
||
</label>
|
||
<?php endif; ?>
|
||
<input type="hidden" name="csrf_token" value="<?= $csrf_token ?>">
|
||
<div>
|
||
<button type="submit" class="newBtn">
|
||
<span>Rechnung erstellen</span>
|
||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 74 74" height="34"
|
||
width="34">
|
||
<circle stroke-width="3" stroke="black" r="35.5" cy="37" cx="37"></circle>
|
||
<path fill="black"
|
||
d="M25 35.5C24.1716 35.5 23.5 36.1716 23.5 37C23.5 37.8284 24.1716 38.5 25 38.5V35.5ZM49.0607 38.0607C49.6464 37.4749 49.6464 36.5251 49.0607 35.9393L39.5147 26.3934C38.9289 25.8076 37.9792 25.8076 37.3934 26.3934C36.8076 26.9792 36.8076 27.9289 37.3934 28.5147L45.8787 37L37.3934 45.4853C36.8076 46.0711 36.8076 47.0208 37.3934 47.6066C37.9792 48.1924 38.9289 48.1924 39.5147 47.6066L49.0607 38.0607ZM25 38.5L48 38.5V35.5L25 35.5V38.5Z">
|
||
</path>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
|
||
const personEinzahl = "<?= $personEinzahl ?>";
|
||
const personMehrzahl = "<?= $personMehrzahl ?>";
|
||
|
||
const startgebueren = <?= json_encode($preise_kats_id) ?>;
|
||
|
||
const csrf_token = "<?= $csrf_token ?>";
|
||
|
||
const menuburger = document.querySelector('.trainerBurgerMenuDiv');
|
||
const menudiv = document.querySelector('.internMenuDiv');
|
||
//const menubg = document.querySelector('.menuBg');
|
||
const content = document.querySelector('.bgSection');
|
||
const closeMenuMobile = document.querySelector('.closeWarenkorb');
|
||
|
||
const storageKey = "trainerInternMenuOpen";
|
||
|
||
const isOpen = localStorage.getItem(storageKey) === "true";
|
||
|
||
if (isOpen) {
|
||
menuburger.classList.add("open");
|
||
menudiv.classList.add("open");
|
||
content.classList.add("open");
|
||
}
|
||
|
||
menuburger.addEventListener("click", function () {
|
||
menuburger.classList.add("menuTransition");
|
||
menudiv.classList.add("menuTransition");
|
||
content.classList.add("menuTransition");
|
||
|
||
menuburger.classList.toggle("open");
|
||
menudiv.classList.toggle("open");
|
||
content.classList.toggle("open");
|
||
|
||
const isOpenEl =
|
||
menudiv.classList.contains("open") &&
|
||
menuburger.classList.contains("open");
|
||
|
||
localStorage.setItem(storageKey, isOpenEl);
|
||
});
|
||
|
||
closeMenuMobile.addEventListener("click", function () {
|
||
const isOpenEl =
|
||
menudiv.classList.contains("open") &&
|
||
menuburger.classList.contains("open");
|
||
|
||
if (isOpenEl) {
|
||
menuburger.classList.remove("open");
|
||
menudiv.classList.remove("open");
|
||
content.classList.remove("open");
|
||
|
||
localStorage.setItem(storageKey, false);
|
||
}
|
||
});
|
||
|
||
let lastWrite = 0;
|
||
const interval = 200;
|
||
|
||
window.addEventListener('scroll', function () {
|
||
const now = Date.now();
|
||
if (now - lastWrite >= interval) {
|
||
sessionStorage.setItem('scrollY', window.scrollY);
|
||
lastWrite = now;
|
||
}
|
||
}, { passive: true });
|
||
|
||
<?php if (!isset($_GET['edit_id']) || (int)$_GET['edit_id'] < 1) : ?>
|
||
window.addEventListener('load', function () {
|
||
const scrollY = sessionStorage.getItem('scrollY');
|
||
if (scrollY !== null) {
|
||
window.scrollTo(0, parseInt(scrollY, 10));
|
||
}
|
||
});
|
||
<?php else: ?>
|
||
window.addEventListener('load', function () {
|
||
window.scrollTo(0, 0);
|
||
})
|
||
<?php endif; ?>
|
||
|
||
function uploadFile($input) {
|
||
|
||
const turnerinId = $input.data('id');
|
||
const oldMusicId = $input.data('musicid');
|
||
const geraetId = $input.data('geraetid');
|
||
|
||
const DOMInput = $input[0];
|
||
|
||
// Check if a file was actually selected before proceeding
|
||
if (!DOMInput.files || DOMInput.files.length === 0) {
|
||
displayMsg(0, 'Bitte wählen Sie eine Datei aus.');
|
||
return;
|
||
}
|
||
|
||
// 1. Create FormData to properly package binary files
|
||
const formData = new FormData();
|
||
formData.append('csrf_token', csrf_token);
|
||
formData.append('music_file', DOMInput.files[0]); // The file object
|
||
formData.append('turnerinId', turnerinId);
|
||
formData.append('geraetId', geraetId);
|
||
|
||
$.ajax({
|
||
url: "/intern/scripts/audiofiles-uploads/ajax_audiofile_upload.php",
|
||
type: 'POST',
|
||
data: formData,
|
||
processData: false,
|
||
contentType: false,
|
||
dataType: 'json',
|
||
success: function (response) {
|
||
if (response.success) {
|
||
$.ajax({
|
||
url: "/intern/scripts/trainer/ajax_link_bodenmusik.php",
|
||
type: 'POST',
|
||
data: {
|
||
csrf_token,
|
||
musicId: response.id,
|
||
turnerinId,
|
||
geraetId,
|
||
oldMusicId
|
||
},
|
||
success: function (response) {
|
||
if (response.success) {
|
||
window.location.reload();
|
||
} else {
|
||
displayMsg(0, response.message || 'Fehler beim Hochladen der Musik');
|
||
}
|
||
},
|
||
error: function (xhr, status, error) {
|
||
displayMsg(0, 'Fehler beim Hochladen: ' + error);
|
||
}
|
||
});
|
||
} else {
|
||
displayMsg(0, response.message || 'Fehler beim Hochladen der Musik');
|
||
}
|
||
},
|
||
error: function (xhr, status, error) {
|
||
displayMsg(0, 'Fehler beim Hochladen: ' + error);
|
||
}
|
||
})
|
||
|
||
}
|
||
|
||
async function confirmDelete(id, name) {
|
||
if (await displayConfirm(name + ' wirklich aus dem System entfernen?')) {
|
||
$.ajax({
|
||
url: "/intern/scripts/trainer/ajax-delete-person.php",
|
||
type: 'POST',
|
||
data: {
|
||
csrf_token,
|
||
personen_ids: JSON.stringify(id)
|
||
},
|
||
success: function (response) {
|
||
if (response.success) {
|
||
displayMsg(1, response.message);
|
||
const $el = $(`tr[data-person-id="${id}"]`);
|
||
if ($el.length !== 1) window.reload();
|
||
$el.remove();
|
||
} else {
|
||
displayMsg(0, response.message);
|
||
}
|
||
},
|
||
error: function (xhr, status, error) {
|
||
displayMsg(0, 'Fehler beim Löschen: ' + error);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
function updatePosition($input, $div) {
|
||
const offset = $input.offset();
|
||
const height = $input.outerHeight();
|
||
const inputWidth = $input.outerWidth();
|
||
const divWidth = $div.outerWidth();
|
||
const divHeight = $div.outerHeight();
|
||
|
||
const left = offset.left + (inputWidth / 2) - (divWidth / 2);
|
||
const top = offset.top + height + 20;
|
||
|
||
const windowWidth = $(window).width();
|
||
const windowHeight = $(window).height();
|
||
const scrollTop = $(window).scrollTop();
|
||
const scrollLeft = $(window).scrollLeft();
|
||
|
||
const isInsideViewport =
|
||
left >= scrollLeft &&
|
||
top >= scrollTop &&
|
||
left + divWidth <= scrollLeft + windowWidth &&
|
||
top + divHeight <= scrollTop + windowHeight;
|
||
|
||
if (!isInsideViewport) {
|
||
$div.hide();
|
||
return;
|
||
}
|
||
|
||
$div.show().css({
|
||
left: left,
|
||
top: top
|
||
});
|
||
}
|
||
|
||
|
||
function updateMusicPreviewFileUrl(path) {
|
||
const $source = $('#sorceAudioPreview');
|
||
|
||
$source.attr('src', path);
|
||
|
||
const extension = path.split('.').pop().toLowerCase();
|
||
$source.attr('type', 'audio/' + extension);
|
||
|
||
// Reload audio element if needed
|
||
$source.closest('audio')[0].load();
|
||
}
|
||
|
||
async function urlExists(url) {
|
||
try {
|
||
const response = await fetch(url, { method: 'HEAD', mode: 'no-cors' });
|
||
return true;
|
||
} catch (error) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
let lastInput = null;
|
||
|
||
const $musicDiv = $('#musicDiv');
|
||
$musicDiv.hide();
|
||
|
||
$('.label-music').on('click', async function () {
|
||
if (lastInput !== this) {
|
||
if (lastInput !== null && $(lastInput).hasClass('selected')) {
|
||
$(lastInput).removeClass('selected');
|
||
}
|
||
lastInput = this;
|
||
const url = $(lastInput).data("url") ?? '';
|
||
if (url === '') { return; }
|
||
const exists = await urlExists(url);
|
||
if (!exists) { return; }
|
||
$(lastInput).addClass('selected');
|
||
updateMusicPreviewFileUrl($(lastInput).data("url"));
|
||
$musicDiv.show();
|
||
updatePosition($(lastInput), $musicDiv);
|
||
} else {
|
||
if (lastInput !== null && $(lastInput).hasClass('selected')) {
|
||
$(lastInput).removeClass('selected');
|
||
}
|
||
$musicDiv.hide();
|
||
lastInput = null;
|
||
}
|
||
});
|
||
|
||
$(window).on('scroll resize', function () {
|
||
if (lastInput) {
|
||
updatePosition($(lastInput), $musicDiv);
|
||
}
|
||
});
|
||
|
||
let bulkSelectPay;
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
<?php
|
||
if (isset($invalidProgrammes) && $invalidProgrammes === true) {
|
||
?>
|
||
displayMsg(2, `Manche ${personMehrzahl} haben nicht aktive Kategorien`);
|
||
<?php
|
||
}
|
||
?>
|
||
|
||
<?php if (isset($_SESSION['form_message'])) echo "console.log('" . $_SESSION['form_message'] . "');"; ?>
|
||
|
||
const $bulkForm = $('#bulk-action-form');
|
||
$bulkForm.on('submit', async function (e) {
|
||
|
||
const $checked = $('input[name="turnerin_ids[]"]:checked');
|
||
if ($checked.length < 1) {
|
||
displayMsg(2, 'Bitte mindestens eine Person auswählen.');
|
||
return;
|
||
}
|
||
const ids = $checked.map(function() {
|
||
return $(this).val();
|
||
}).get();
|
||
|
||
const $actionInput = $('#bulk-action-form').find('#bulk_action_select');
|
||
|
||
if ($actionInput.length !== 1) return;
|
||
|
||
switch ($actionInput.val()) {
|
||
case 'payEntryFee' :
|
||
e.preventDefault();
|
||
|
||
const url = "/intern/scripts/trainer/ajax-add_entry_fees_to_basket.php";
|
||
|
||
fetch(url, {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||
body: new URLSearchParams({
|
||
csrf_token,
|
||
ids,
|
||
user: <?= $userid; ?>
|
||
})
|
||
})
|
||
.then(res => res.json())
|
||
.then(response => {
|
||
if (response.success) {
|
||
window.location.reload();
|
||
} else {
|
||
alert('Error: ' + response.message);
|
||
}
|
||
})
|
||
.catch(err => {
|
||
console.error('AJAX fetch error:', err);
|
||
});
|
||
break;
|
||
case 'deletePersonen':
|
||
e.preventDefault();
|
||
|
||
if (!await displayConfirm('Unwiederuflich löschen?')) return;
|
||
|
||
$.ajax({
|
||
url: "/intern/scripts/trainer/ajax-delete-person.php",
|
||
type: 'POST',
|
||
data: {
|
||
csrf_token,
|
||
personen_ids: JSON.stringify(ids)
|
||
},
|
||
success: function (response) {
|
||
if (response.success) {
|
||
displayMsg(1, response.message);
|
||
ids.forEach(function(id) {
|
||
const $el = $(`tr[data-person-id="${id}"]`);
|
||
if ($el.length !== 1) window.reload();
|
||
$el.remove();
|
||
});
|
||
} else {
|
||
displayMsg(0, response.message);
|
||
}
|
||
},
|
||
error: function (xhr, status, error) {
|
||
displayMsg(0, 'Fehler beim Löschen: ' + error);
|
||
}
|
||
});
|
||
|
||
break;
|
||
|
||
case 'changeKat':
|
||
e.preventDefault();
|
||
const kat_id = parseInt($('#bulk_action_programm').val() || 0);
|
||
|
||
if (!await displayConfirm('Die Änderung der Kat bei bezahlten Startgebühren kann dazu führen, dass Teile der Startgebühr nachgezahlt werden müssen.')) return;
|
||
|
||
$.ajax({
|
||
url: "/intern/scripts/trainer/ajax-update-person-kat.php",
|
||
type: 'POST',
|
||
data: {
|
||
csrf_token,
|
||
personen_ids: JSON.stringify(ids),
|
||
kat_id
|
||
},
|
||
success: function (response) {
|
||
if (response.success) {
|
||
displayMsg(1, response.message);
|
||
location.reload();
|
||
} else {
|
||
displayMsg(0, response.message);
|
||
}
|
||
},
|
||
error: function (xhr, status, error) {
|
||
displayMsg(0, 'Fehler beim Ändern der Kat: ' + error);
|
||
}
|
||
});
|
||
|
||
break;
|
||
default:
|
||
return;
|
||
}
|
||
|
||
});
|
||
|
||
// find all "check all" master checkboxes
|
||
document.querySelectorAll('[id^="check_all_"]').forEach(master => {
|
||
const programm = master.id.replace("check_all_", "");
|
||
const checkboxes = document.querySelectorAll(".row_check_" + programm);
|
||
|
||
// toggle all rows when master is clicked
|
||
master.addEventListener("change", function () {
|
||
checkboxes.forEach(cb => cb.checked = master.checked);
|
||
});
|
||
|
||
// update master if all rows are manually checked/unchecked
|
||
checkboxes.forEach(cb => {
|
||
cb.addEventListener("change", function () {
|
||
master.checked = [...checkboxes].every(c => c.checked);
|
||
});
|
||
});
|
||
});
|
||
});
|
||
|
||
let menuTriggerdGebueren = false;
|
||
jQuery(function ($) {
|
||
const scrollY = sessionStorage.getItem("scrollY");
|
||
if (scrollY) $(window).scrollTop(scrollY);
|
||
|
||
$(window).on('beforeunload', function () {
|
||
sessionStorage.setItem("scrollY", $(window).scrollTop());
|
||
});
|
||
|
||
const user = '<?= strtolower($selectedverein); ?>';
|
||
|
||
$('#bulk_action_select').change(function () {
|
||
let value = $(this).val();
|
||
$('.bulk-select-submit').removeClass("hidden");
|
||
|
||
if (value === 'changeKat') {
|
||
$('.customSelectBulkActionProgramm').removeClass("hidden");
|
||
bulkSelectPay = false;
|
||
|
||
if (user === 'admin') {
|
||
$('.customSelectBulkActionBezahlt').addClass("hidden");
|
||
}
|
||
}
|
||
|
||
if (value === 'changeEntryFee' && user === 'admin') {
|
||
$('.customSelectBulkActionBezahlt').removeClass("hidden");
|
||
$('.customSelectBulkActionProgramm').addClass("hidden");
|
||
bulkSelectPay = false;
|
||
}
|
||
|
||
if (value === 'payEntryFee') {
|
||
if (user === 'admin') {
|
||
$('.customSelectBulkActionBezahlt').addClass("hidden");
|
||
}
|
||
$('.customSelectBulkActionProgramm').addClass("hidden");
|
||
bulkSelectPay = true;
|
||
}
|
||
});
|
||
$('.addTurnerinToWarenkorb').on('click', function (e) {
|
||
e.preventDefault();
|
||
|
||
const el = $(this);
|
||
const id = el.data('id');
|
||
|
||
// Build the URL with GET parameters safely
|
||
const url = `/intern/scripts/trainer/ajax-add_entry_fees_to_basket.php`;
|
||
|
||
fetch(url, {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||
body: new URLSearchParams({
|
||
csrf_token,
|
||
ids: id
|
||
})
|
||
})
|
||
.then(res => {
|
||
// 200–299
|
||
if (res.ok) {
|
||
return res.json();
|
||
}
|
||
|
||
if (res.status == 406) {
|
||
displayMsg(2, 'Startgebühr bereits im Warenkorb');
|
||
throw new Error('ALREADY_IN_CART');
|
||
}
|
||
|
||
// Non-2xx → throw a structured error
|
||
return res.json().then(body => {
|
||
throw {
|
||
status: res.status,
|
||
message: body.message || res.statusText
|
||
};
|
||
});
|
||
})
|
||
.then(data => {
|
||
// SUCCESS PATH (200)
|
||
displayMsg(1, 'Startgebühren dem Warenkorb hinzugefügt');
|
||
|
||
const $tbody = $('.tbodyStartGebueren');
|
||
|
||
// Extract row item for cleaner access
|
||
const item = data.arrayGebueren[id];
|
||
|
||
// 1. Create the SVG trash icon element
|
||
const $deleteIcon = $(`
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
||
<polyline points="3 6 5 6 21 6"></polyline>
|
||
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
|
||
<line x1="10" y1="11" x2="10" y2="17"></line>
|
||
<line x1="14" y1="11" x2="14" y2="17"></line>
|
||
</svg>
|
||
`);
|
||
|
||
// 2. Build Table Cells (<td>)
|
||
const $tdName = $('<td>', { class: 'cellStartgebuer' })
|
||
.append($('<b>', { text: item.turnerinName }))
|
||
.append(document.createTextNode(`, ${item.turnerinVorname} | ${item.programm}${item.appendix}`));
|
||
|
||
const $tdPrice = $('<td>', {
|
||
class: 'cellStartgebuer',
|
||
'data-type': 'startgebuer',
|
||
'data-value' : item.preis,
|
||
'data-verein' : item.verein,
|
||
text: 'CHF ' + item.formated_preis
|
||
});
|
||
|
||
const $tdDelete = $('<td>', {
|
||
class: 'cellStartgebuer',
|
||
'data-type': 'delete',
|
||
'data-id': id
|
||
}).append($deleteIcon);
|
||
|
||
// 3. Build Table Row (<tr>) and append cells
|
||
const $row = $('<tr>', {
|
||
class: 'rowStartgebuer',
|
||
'data-id': id
|
||
}).append($tdName, $tdPrice, $tdDelete);
|
||
|
||
// 4. Append row to tbody
|
||
$tbody.append($row);
|
||
|
||
// Separate rows
|
||
const $totalRow = $tbody.find('tr.rowStartgebuerTotal').detach();
|
||
const rows = $tbody.find('tr:not(.rowStartgebuerTotal)').get();
|
||
|
||
// Sort remaining rows
|
||
rows.sort(function (a, b) {
|
||
const textA = $(a).find('td:first').text();
|
||
const textB = $(b).find('td:first').text();
|
||
|
||
const keyA = textA.split(', ')[1]?.toLowerCase() || '';
|
||
const keyB = textB.split(', ')[1]?.toLowerCase() || '';
|
||
|
||
return keyA.localeCompare(keyB, 'de', { sensitivity: 'base' });
|
||
});
|
||
|
||
// Re-append sorted rows
|
||
$.each(rows, function (_, row) {
|
||
$tbody.append(row);
|
||
});
|
||
|
||
// Append total row last
|
||
$tbody.append($totalRow);
|
||
|
||
const abzugeArray = data.arrayAbzuege;
|
||
|
||
const $abzuegeTbody = $('.tableAbzugeStartgebueren');
|
||
|
||
Object.entries(abzugeArray).forEach(([vereinName, details]) => {
|
||
const sabzug = parseFloat(details.betrag);
|
||
const smax = parseFloat(details.max);
|
||
if (sabzug === 0.00 || smax === 0.00) return;
|
||
|
||
const verein = vereinName;
|
||
|
||
const vereinId = details.vereinId;
|
||
|
||
|
||
|
||
let allAbzuegeVerein = 0;
|
||
|
||
const $allAbzuegeVerein = $(`.rowStartgebuer .cellStartgebuer[data-type="abzug"][data-verein="${verein}"]`);
|
||
|
||
if ($allAbzuegeVerein.length > 0) {
|
||
$allAbzuegeVerein.each((ind, el) => {
|
||
allAbzuegeVerein += parseFloat($(el).attr('data-value'));
|
||
});
|
||
|
||
allAbzuegeVerein += sabzug;
|
||
|
||
const betrag = Math.min(allAbzuegeVerein, smax);
|
||
|
||
$allAbzuegeVerein.text('CHF ' + betrag.toFixed(2)).attr('data-value', betrag);
|
||
} else {
|
||
const betrag = Math.min(sabzug, smax);
|
||
|
||
const formattedBetrag = parseFloat(betrag).toFixed(2);
|
||
|
||
const $tr = $('<tr>', { class: 'rowStartgebuer', 'data-id': vereinId });
|
||
|
||
const $td1 = $('<td>', { class: 'cellStartgebuer' })
|
||
.text('Guthaben ')
|
||
.append($('<b>').text(verein));
|
||
|
||
const $td2 = $('<td>', {
|
||
class: 'cellStartgebuer',
|
||
'data-type': 'abzug',
|
||
'data-value': betrag,
|
||
'data-verein': verein
|
||
}).text(`CHF ${formattedBetrag}`);
|
||
|
||
const $input = $('<input>', {
|
||
type: 'checkbox',
|
||
class: 'deactivateAbzug',
|
||
value: vereinId
|
||
});
|
||
|
||
const $label = $('<label>', { class: 'checkbox' })
|
||
.append($input)
|
||
.append($('<span>', { class: 'checkbox-ui' }));
|
||
|
||
const $td3 = $('<td>', { class: 'cellStartgebuer', 'data-id': vereinId })
|
||
.append($label);
|
||
|
||
$tr.append($td1, $td2, $td3);
|
||
|
||
$abzuegeTbody.find('tr.rowStartgebuerTotal').before($tr);
|
||
}
|
||
$abzuegeTbody.removeClass('hidden');
|
||
});
|
||
|
||
toggleWarenkorbContentsDisplay();
|
||
recalculatePreis();
|
||
|
||
if (!menuTriggerdGebueren) {
|
||
menuTriggerdGebueren = true;
|
||
$('.trainerBurgerMenuDiv').addClass('open');
|
||
$('.internMenuDiv').addClass('open');
|
||
$('.bgSection').addClass('open');
|
||
$('.closeInternMenuMobileDiv').addClass('open');
|
||
|
||
localStorage.setItem(storageKey, true);
|
||
}
|
||
})
|
||
.catch(error => {
|
||
if (error.message === 'ALREADY_IN_CART') {
|
||
return; // Silent exit, message was already displayed
|
||
}
|
||
// ERROR PATH ONLY
|
||
console.error('Fetch error:', error);
|
||
|
||
const msg = error?.message || 'Netzwerk- oder Serverfehler';
|
||
displayMsg(0, msg);
|
||
});
|
||
|
||
});
|
||
|
||
const $paymentFormContainer = $('#paymentFormContainer');
|
||
|
||
$('.closePaymentForm').on('click', () => $paymentFormContainer.hide());
|
||
|
||
$('#checkoutButton').on('click', () => $paymentFormContainer.show());
|
||
|
||
$('#paymentForm').on('submit', function (e) {
|
||
e.preventDefault();
|
||
|
||
const $form = $(this);
|
||
const $submitBtn = $form.find('button[type="submit"]');
|
||
const originalText = $submitBtn.text();
|
||
|
||
const usedKonten = {};
|
||
|
||
$('.rowStartgebuer.active .cellStartgebuer[data-type="abzug"]').each((ind, el) => {
|
||
const verein = $(el).attr('data-verein');
|
||
const value = parseFloat($(el).attr('data-value')) || 0;
|
||
|
||
if (verein) {
|
||
usedKonten[verein] = value;
|
||
}
|
||
});
|
||
|
||
$submitBtn.text('Bitte warten...').prop('disabled', true);
|
||
|
||
const formData = new FormData(this);
|
||
formData.append('usedKonten', JSON.stringify(usedKonten));
|
||
|
||
fetch("/intern/scripts/trainer/ajax-neu-verbuchte-startgebuer.php", {
|
||
method: 'POST',
|
||
body: formData
|
||
})
|
||
.then(res => {
|
||
if (!res.ok) {
|
||
throw new Error(`HTTP Error: ${res.status}`);
|
||
}
|
||
// Check if it's a PDF
|
||
const contentType = res.headers.get('content-type');
|
||
if (contentType && contentType.includes('application/pdf')) {
|
||
// Get filename from Content-Disposition if possible
|
||
let filename = 'Rechnung.pdf';
|
||
const disposition = res.headers.get('content-disposition');
|
||
if (disposition && disposition.indexOf('attachment') !== -1) {
|
||
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
|
||
const matches = filenameRegex.exec(disposition);
|
||
if (matches != null && matches[1]) {
|
||
filename = matches[1].replace(/['"]/g, '');
|
||
}
|
||
}
|
||
|
||
return res.blob().then(blob => ({ blob, filename }));
|
||
} else {
|
||
return res.json().then(data => {
|
||
throw new Error(data.message || 'Error generating invoice');
|
||
});
|
||
}
|
||
})
|
||
.then(({ blob, filename }) => {
|
||
// Create a link to download the PDF
|
||
const url = window.URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.style.display = 'none';
|
||
a.href = url;
|
||
a.download = filename;
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
window.URL.revokeObjectURL(url);
|
||
|
||
// Clean up and reload
|
||
$paymentFormContainer.hide();
|
||
displayMsg(1, 'Rechnung erfolgreich erstellt!');
|
||
|
||
setTimeout(() => {
|
||
window.location.reload();
|
||
}, 1500);
|
||
})
|
||
.catch(err => {
|
||
console.error(err);
|
||
alert('Fehler: ' + err.message);
|
||
$submitBtn.text(originalText).prop('disabled', false);
|
||
});
|
||
});
|
||
|
||
$('.form_excel').on('submit', function (e) {
|
||
e.preventDefault();
|
||
|
||
let formData = new FormData(this);
|
||
formData.append('csrf_token', csrf_token);
|
||
|
||
displayMsg(2, "Verarbeite Excel…");
|
||
|
||
$.ajax({
|
||
url: "/intern/scripts/trainer/ajax-add-personen-excel.php",
|
||
type: 'POST',
|
||
data: formData,
|
||
contentType: false,
|
||
processData: false,
|
||
success: function (response) {
|
||
if (response.success) {
|
||
displayMsg(1, response.message);
|
||
|
||
$('.form_excel')[0].reset();
|
||
|
||
displayMsg(1, "Lade Seite in 3 Sekunden neu…");
|
||
setTimeout(() => {
|
||
window.location.reload();
|
||
}, 3000);
|
||
} else {
|
||
displayMsg(0, response.message);
|
||
}
|
||
},
|
||
error: function (xhr, status, error) {
|
||
displayMsg(0, 'Fehler beim Upload: ' + error);
|
||
}
|
||
});
|
||
});
|
||
|
||
const $paymentInfoDiv = $('.tooltipPaymentStatusContainer');
|
||
|
||
let hoverTimeout = null;
|
||
|
||
$(document).on('mouseenter', '.hoverPaymentInfo', function() {
|
||
const $el = $(this);
|
||
clearTimeout(hoverTimeout);
|
||
|
||
// 2. Start a new timer
|
||
hoverTimeout = setTimeout(() => {
|
||
const pos = $el.offset();
|
||
|
||
$paymentInfoDiv.css({
|
||
top: pos.top,
|
||
left: pos.left
|
||
}).removeClass("opacity0");
|
||
}, 600);
|
||
});
|
||
|
||
$(document).on('mouseleave', '.hoverPaymentInfo', function() {
|
||
$paymentInfoDiv.addClass("opacity0");
|
||
|
||
clearTimeout(hoverTimeout);
|
||
});
|
||
|
||
$(document).on('click', '.cellStartgebuer[data-type="delete"]', function () {
|
||
|
||
const el = $(this);
|
||
|
||
const id = el.data('id');
|
||
|
||
const url = '/intern/scripts/trainer/ajax-remove_basket_item.php';
|
||
$.ajax({
|
||
url: url,
|
||
type: 'POST',
|
||
data: {
|
||
id: id,
|
||
csrf_token: csrf_token
|
||
},
|
||
success: function(response) {
|
||
if (!response.success) {
|
||
displayMsg(0, response.message || "Startgebühr konnte nicht entfernt werden");
|
||
return;
|
||
}
|
||
|
||
$('.rowStartgebuer[data-id="' + id + '"]').remove();
|
||
|
||
const verein = response.verein;
|
||
const vereinKonto = parseFloat(response.vereinKonto) || 0;
|
||
|
||
const $abzugCell = $(`.rowStartgebuer .cellStartgebuer[data-type="abzug"][data-verein="${verein}"]`);
|
||
|
||
if ($abzugCell.length === 1) {
|
||
const $startgebueren = $(`.rowStartgebuer .cellStartgebuer[data-type="startgebuer"][data-verein="${verein}"]`);
|
||
|
||
let startgebueren = 0.00;
|
||
|
||
$startgebueren.each((ind, el) => {
|
||
const val = parseFloat($(el).attr("data-value")) || 0;
|
||
startgebueren += val;
|
||
});
|
||
|
||
if (startgebueren === 0 || vereinKonto === 0) {
|
||
$abzugCell.closest('tr').remove();
|
||
} else {
|
||
const newAbzug = Math.min(startgebueren, vereinKonto);
|
||
|
||
$abzugCell
|
||
.text("CHF " + newAbzug.toFixed(2))
|
||
.attr("data-value", newAbzug);
|
||
}
|
||
}
|
||
|
||
toggleWarenkorbContentsDisplay();
|
||
recalculatePreis();
|
||
|
||
displayMsg(1, "Startgebühr entfernt");
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error(`HTTP ${xhr.status}: ${error}`);
|
||
displayMsg(0, "Fehler beim Entfernen der Startgebühr");
|
||
}
|
||
})
|
||
});
|
||
|
||
// We need the raw DOM element from the jQuery object to access HTML5 Audio methods
|
||
const $audio = $('#sorceAudioPreview');
|
||
const audioDOM = $audio[0];
|
||
|
||
const $playPauseBtn = $('#play-pause-btn');
|
||
const $seekBar = $('#seek-bar');
|
||
const $currentTimeDisplay = $('#current-time');
|
||
const $durationDisplay = $('#duration');
|
||
|
||
// Helper function to format seconds into MM:SS format
|
||
function formatTime(seconds) {
|
||
if (isNaN(seconds)) return "0:00";
|
||
const mins = Math.floor(seconds / 60);
|
||
const secs = Math.floor(seconds % 60);
|
||
return mins + ":" + (secs < 10 ? '0' : '') + secs;
|
||
}
|
||
|
||
// Toggle Play / Pause
|
||
$playPauseBtn.on('click', function() {
|
||
if (audioDOM.paused) {
|
||
audioDOM.play();
|
||
$(this).text('Pause');
|
||
} else {
|
||
audioDOM.pause();
|
||
$(this).text('Play');
|
||
}
|
||
});
|
||
|
||
// Update duration display once metadata loads
|
||
$audio.on('loadedmetadata', function() {
|
||
$durationDisplay.text(formatTime(audioDOM.duration));
|
||
});
|
||
|
||
// Update seek bar and current time as audio plays
|
||
$audio.on('timeupdate', function() {
|
||
const progress = (audioDOM.currentTime / audioDOM.duration) * 100;
|
||
$seekBar.val(progress || 0);
|
||
$currentTimeDisplay.text(formatTime(audioDOM.currentTime));
|
||
});
|
||
|
||
// Seek audio when dragging the seek bar range input
|
||
$seekBar.on('input', function() {
|
||
const seekTo = ($(this).val() / 100) * audioDOM.duration;
|
||
audioDOM.currentTime = seekTo;
|
||
});
|
||
|
||
// Reset UI when audio ends
|
||
$audio.on('ended', function() {
|
||
$playPauseBtn.text('Play');
|
||
$seekBar.val(0);
|
||
$currentTimeDisplay.text("0:00");
|
||
});
|
||
|
||
function recalculatePreis() {
|
||
const $sidebar = $('.innerInternMenuDiv');
|
||
const $startgebueren = $sidebar.find('.cellStartgebuer[data-type="startgebuer"]');
|
||
|
||
let kosten = 0;
|
||
|
||
$startgebueren.each((ind, el) => {
|
||
kosten += parseFloat($(el).attr('data-value'));
|
||
});
|
||
|
||
$('.totalStartgebueren').attr('data-value', kosten).text('CHF ' + kosten.toFixed(2));
|
||
|
||
const $abzuege = $('.rowStartgebuer.active .cellStartgebuer[data-type="abzug"]');
|
||
|
||
let abzuege = 0;
|
||
|
||
$abzuege.each((ind, el) => {
|
||
abzuege += parseFloat($(el).attr('data-value'));
|
||
});
|
||
|
||
$('.totalAbzuegeStartgebueren').attr('data-value', abzuege).text('CHF ' + abzuege.toFixed(2));
|
||
|
||
const totalPreis = kosten - abzuege;
|
||
|
||
$('.totalKosten').attr('data-value', totalPreis).text('CHF ' + totalPreis.toFixed(2));
|
||
}
|
||
|
||
function toggleWarenkorbContentsDisplay() {
|
||
const $sidebar = $('.innerInternMenuDiv');
|
||
const $startgebueren = $sidebar.find('.cellStartgebuer[data-type="startgebuer"]');
|
||
const $abzuege = $sidebar.find('.rowStartgebuer .cellStartgebuer[data-type="abzug"]');
|
||
|
||
const displayNotAll = $startgebueren.length === 0;
|
||
const displayNotAbzuege = $abzuege.length === 0;
|
||
|
||
$('.tableStartgebueren').toggleClass('hidden', displayNotAll);
|
||
$('.tableAbzugeStartgebueren').toggleClass('hidden', displayNotAll || displayNotAbzuege);
|
||
$('.tableKostenTotal').toggleClass('hidden', displayNotAll);
|
||
$('.checkoutButton').toggleClass('hidden', displayNotAll);
|
||
$('#textKeineStartgebuerenAusgewählt').toggleClass('hidden', !displayNotAll);
|
||
}
|
||
|
||
$(document).on('click', '.deactivateAbzug', function () {
|
||
const $input = $(this);
|
||
const $tr = $input.closest('tr');
|
||
$tr.toggleClass('active', $input.prop('checked'));
|
||
recalculatePreis();
|
||
});
|
||
|
||
<?php if (isset($_GET['edit_id']) && (int)$_GET['edit_id'] > 1) : ?>
|
||
|
||
$(document).ready(function() {
|
||
|
||
const $originalProgramm = $('.programmEditing .selectValue');
|
||
const originalProgramm = $originalProgramm.val();
|
||
|
||
$('.programmEditing .selectValue').on('change', function () {
|
||
const $input = $(this);
|
||
const newProgramm = ($input.val() || '').trim();
|
||
|
||
// If they switch back to the original program, no difference in price
|
||
if (originalProgramm === newProgramm) {
|
||
return;
|
||
}
|
||
|
||
console.log(newProgramm, startgebueren[newProgramm]);
|
||
console.log(originalProgramm, startgebueren[originalProgramm]);
|
||
|
||
// Safety: Ensure both keys exist in our data array
|
||
if (startgebueren[newProgramm] === undefined || startgebueren[originalProgramm] === undefined) {
|
||
return;
|
||
}
|
||
|
||
// 2. Math Swap: New price minus Original price calculates the actual delta
|
||
const priceDiff = startgebueren[newProgramm] - startgebueren[originalProgramm];
|
||
|
||
console.log(priceDiff);
|
||
|
||
// 3. Display messages using Math.abs() to keep numbers positive/clean
|
||
if (priceDiff > 0) {
|
||
displayInfo(`Information`, `Durch die Änderungen dieser Kategorie werden CHF ${priceDiff} an Startgebühren zusätzlich fällig.`);
|
||
} else if (priceDiff < 0) {
|
||
const positiveRefund = Math.abs(priceDiff);
|
||
displayInfo(`Information`, `Durch die Änderungen dieser Kategorie werden diesem Verein CHF ${positiveRefund} an Startgebühren wieder gutgeschrieben.`);
|
||
}
|
||
|
||
});
|
||
|
||
});
|
||
|
||
<?php endif; ?>
|
||
});
|
||
</script>
|
||
|
||
<script>
|
||
flatpickr("#geburtsdatum", {
|
||
locale: "de",
|
||
dateFormat: "Y-m-d",
|
||
altInput: true,
|
||
altFormat: "d. F Y",
|
||
allowInput: true,
|
||
disableMobile: "true",
|
||
|
||
minDate: "1920-01-01",
|
||
maxDate: "today"
|
||
});
|
||
</script>
|
||
|
||
<?php
|
||
if (isset($_SESSION['form_message']) && $_SESSION['form_message'] !== '' && isset($_SESSION['form_message_type']) && ((int)$_SESSION['form_message_type'] === 0 || (int)$_SESSION['form_message_type'] === 1)) {
|
||
echo '<script>displayMsg(' . (int)$_SESSION['form_message_type'] . ', "' . $_SESSION['form_message'] . '");</script>';
|
||
unset($_SESSION['form_message']);
|
||
unset($_SESSION['form_message_type']);
|
||
}
|
||
?>
|
||
<?php endif; ?>
|
||
</body>
|
||
</html>
|