431 lines
17 KiB
PHP
431 lines
17 KiB
PHP
<?php
|
|
|
|
ini_set('display_errors', 1);
|
|
ini_set('display_startup_errors', 1);
|
|
|
|
|
|
if (!isset($baseDir)) {
|
|
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
|
}
|
|
|
|
require_once $baseDir . '/../scripts/session_functions.php';
|
|
|
|
ini_wkvs_session(true);
|
|
|
|
$csrf_token = $_SESSION['csrf_token'] ?? '';
|
|
|
|
$access_granted_wkl = check_user_permission('wk_leitung', true) ?? false;
|
|
|
|
if (!$access_granted_wkl):
|
|
|
|
$logintype = 'wk_leitung';
|
|
|
|
require $baseDir . '/../scripts/login/login.php';
|
|
|
|
$logintype = '';
|
|
|
|
else:
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="de">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<link rel="icon" type="png" href="/intern/img/icon.png">
|
|
<title>WK-leitung - Wettkämpfe</title>
|
|
|
|
|
|
<link rel="stylesheet" href="/intern/css/einstellungen-ai.css">
|
|
<link rel="stylesheet" href="/intern/css/sidebar.css">
|
|
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
|
|
<script src="/intern/js/custom-msg-display.js"></script>
|
|
<link rel="stylesheet" href="/intern/css/custom-msg-display.css">
|
|
<script src="/intern/js/custom-select.js"></script>
|
|
<link rel="stylesheet" href="/intern/css/custom-select.css">
|
|
<link rel="stylesheet" href="/files/fonts/fonts.css">
|
|
<link rel="stylesheet" href="/intern/css/user.css">
|
|
<link rel="stylesheet" href="/externe-geraete/css/display.css">
|
|
|
|
<script src="/intern/js/ace/ace.js"></script>
|
|
|
|
<link rel="stylesheet" href="/intern/css/coloris/coloris.min.css" />
|
|
<script src="/intern/js/coloris/coloris.min.js"></script>
|
|
|
|
</head>
|
|
|
|
<body class="wettkaempfe">
|
|
<?php
|
|
|
|
|
|
require $baseDir . '/../scripts/db/db-functions.php';
|
|
require $baseDir . '/../scripts/db/db-tables.php';
|
|
|
|
require $baseDir . '/../scripts/websocket/ws-create-token.php';
|
|
|
|
|
|
$type = 'wkl';
|
|
|
|
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
|
|
|
if ($dbconnection['success'] !== true) {
|
|
echo 'Critical DB Error.';
|
|
exit;
|
|
}
|
|
|
|
$currentPage = 'wettkaempfe';
|
|
|
|
require $baseDir . '/../scripts/sidebar/sidebar.php';
|
|
|
|
$wettkaempfe = db_select($mysqli, $db_tabelle_wettkaempfe, '*', '', [], 'id ASC');
|
|
|
|
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
|
|
|
?>
|
|
<section class="bgSection">
|
|
<?php sidebarRender('modal'); ?>
|
|
<div class="headerDivTrainer">
|
|
<div class="headingPanelDiv">
|
|
<h2 class="headingPanel">Wettkämpfe</h2>
|
|
</div>
|
|
<div class="menuWrapper">
|
|
<?php sidebarRender('button'); ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="dashboardGrid">
|
|
|
|
<div class="containerDiv">
|
|
<div>
|
|
<h3 class="containerHeading">Wettkämpfe</h3>
|
|
|
|
<table id="programmTable" class="wkvsTabelle">
|
|
<thead>
|
|
<tr>
|
|
<th>Wettkampf ID</th>
|
|
<th>Name</th>
|
|
<th>Slug</th>
|
|
<th>Status</th>
|
|
<th>Löschen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($wettkaempfe as $s_wk) :
|
|
$aktiv = ((int) $s_wk['id'] === $current_wk_id); ?>
|
|
<tr>
|
|
<td><?= (int) $s_wk['id'] ?></td>
|
|
<td>
|
|
<input class="ajaxInput" data-type="name" data-id="<?= (int) $s_wk['id'] ?>" value="<?= htmlspecialchars($s_wk['name'] ?? '') ?>">
|
|
</td>
|
|
<td>
|
|
<input class="ajaxInput" data-type="slug" data-id="<?= (int) $s_wk['id'] ?>" value="<?= htmlspecialchars($s_wk['slug'] ?? '') ?>">
|
|
</td>
|
|
<td>
|
|
<span class="statusSpan <?= $aktiv ? 'activeWk' : 'inactiveWk' ?>"><?= $aktiv ? 'Aktiv' : 'Inaktiv' ?></span>
|
|
<span class="activateSpan <?= $aktiv ? 'hidden' : '' ?>" data-id="<?= (int) $s_wk['id'] ?>">Aktivieren</span>
|
|
</td>
|
|
<td>
|
|
<button class="deleteWk deleteBtn" data-id="<?= (int) $s_wk['id'] ?>">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22"
|
|
viewBox="0 0 24 24" fill="none" stroke="var(--ui-danger)"
|
|
stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
<polyline points="3 6 5 6 21 6"></polyline>
|
|
<path
|
|
d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2">
|
|
</path>
|
|
<line x1="10" y1="11" x2="10" y2="17"></line>
|
|
<line x1="14" y1="11" x2="14" y2="17"></line>
|
|
</svg>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<tr class="addRow">
|
|
<td></td>
|
|
<td>
|
|
<input type="text" required placeholder="Bezeichnung" class="inputNewWkName">
|
|
</td>
|
|
<td>
|
|
<input type="text" required placeholder="Bsp. wkvs-2026" class="inputNewWkSlug">
|
|
</td>
|
|
<td colspan="2">
|
|
<button type="submit" class="blackBtn neuWkBtn">Neuen Wettkampf erstellen</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="msgDiv"></div>
|
|
|
|
</section>
|
|
|
|
<script>
|
|
|
|
const csrf_token = "<?= $csrf_token ?>";
|
|
|
|
$('.neuWkBtn').on('click', function () {
|
|
const $btn = $(this);
|
|
const $row = $btn.closest(".addRow");
|
|
const $nameInput = $row.find(".inputNewWkName");
|
|
const $slugInput = $row.find(".inputNewWkSlug");
|
|
|
|
if ($nameInput.length !== 1 || $slugInput.length !== 1) return;
|
|
|
|
const name = $nameInput.val().trim();
|
|
|
|
if (name === '') {
|
|
displayMsg(2, "Der Wettkampfname darf nicht leer sein");
|
|
return;
|
|
}
|
|
|
|
const slug = $slugInput.val().trim();
|
|
|
|
if (slug === '') {
|
|
displayMsg(2, "Der Slug darf nicht leer sein");
|
|
return;
|
|
}
|
|
if (/\s/.test(slug)) {
|
|
displayMsg(2, "Der Slug darf keine Leerzeichen enthalten");
|
|
return;
|
|
}
|
|
|
|
if (!/^[a-z0-9-]+$/.test(slug)) {
|
|
displayMsg(2, "Der Slug darf nur Kleinbuchstaben, Zahlen und Bindestriche enthalten");
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url: '/intern/scripts/wettkaempfe/ajax-add-wettkampf.php',
|
|
type: "POST",
|
|
data: {
|
|
csrf_token,
|
|
name,
|
|
slug
|
|
},
|
|
success: function(response) {
|
|
if (!response.success) {
|
|
displayMsg(0, response.message || "Der Wettkampf konnte nicht hinzugefügt werden");
|
|
return;
|
|
}
|
|
|
|
const $newRow = $('<tr>', {});
|
|
|
|
// 1. ID Column (Plain text)
|
|
const $tdId = $('<td>', { text: response.id });
|
|
|
|
// 2. Name Column (with nested <input>)
|
|
const $tdName = $('<td>');
|
|
const $inputName = $('<input>', {
|
|
class: 'ajaxInput',
|
|
'data-type': 'name',
|
|
'data-id': response.id,
|
|
val: name // Sets the input value securely
|
|
});
|
|
$tdName.append($inputName);
|
|
|
|
// 3. Slug Column (with nested <input>)
|
|
const $tdSlug = $('<td>');
|
|
const $inputSlug = $('<input>', {
|
|
class: 'ajaxInput',
|
|
'data-type': 'slug',
|
|
'data-id': response.id,
|
|
val: slug // Sets the input value securely
|
|
});
|
|
$tdSlug.append($inputSlug);
|
|
|
|
// 4. Empty Column
|
|
const $tdStatus = $('<td>', {});
|
|
|
|
const $spanStatus = $('<span>', {
|
|
text: 'Inaktiv',
|
|
class: "statusSpan inactiveWk"
|
|
});
|
|
|
|
const $spanActivate = $('<span>', {
|
|
text: 'aktivieren',
|
|
'data-id': response.id,
|
|
class: "activateSpan"
|
|
});
|
|
|
|
$tdStatus.append($spanStatus, $spanActivate);
|
|
|
|
// 5. Action Column (Delete button with SVG)
|
|
const $tdAction = $('<td>', {});
|
|
|
|
const $deleteBtn = $('<button>', {
|
|
class: 'deleteWk deleteBtn',
|
|
'data-id': response.id
|
|
});
|
|
|
|
const $svgIcon = $(`
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22"
|
|
viewBox="0 0 24 24" fill="none" stroke="var(--ui-danger)"
|
|
stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round">
|
|
<polyline points="3 6 5 6 21 6"></polyline>
|
|
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
|
|
<line x1="10" y1="11" x2="10" y2="17"></line>
|
|
<line x1="14" y1="11" x2="14" y2="17"></line>
|
|
</svg>
|
|
`);
|
|
|
|
$deleteBtn.append($svgIcon);
|
|
$tdAction.append($deleteBtn);
|
|
|
|
// 6. Assemble everything
|
|
$newRow.append($tdId, $tdName, $tdSlug, $tdStatus, $tdAction);
|
|
|
|
// 7. Insert into the DOM
|
|
// Note: If you want to insert the new row *before* an existing row ($row), use this:
|
|
$newRow.insertBefore($row);
|
|
|
|
displayMsg(1, "Neuer Wettkampf hinzugefügt");
|
|
|
|
},
|
|
error: () => {
|
|
displayMsg(0, "Fehler beim Hinzufügen des Wettkampfes");
|
|
}
|
|
});
|
|
|
|
});
|
|
|
|
$(document).on('click', '.deleteWk', async function () {
|
|
const $btn = $(this);
|
|
const $row = $btn.closest("tr");
|
|
const name = $row.find('.ajaxInput[data-type="name"]').val() || '';
|
|
|
|
if (!await displayConfirm(`Wettkampf "${name}" wirklich unwiederruflich löschen? Diese Aktion löscht alle Ergebnisse dieses Wettkampfes!`)) return;
|
|
|
|
const dataId = $btn.data('id');
|
|
|
|
$.ajax({
|
|
url: '/intern/scripts/wettkaempfe/ajax-delete-wettkampf.php',
|
|
type: "DELETE",
|
|
data: {
|
|
csrf_token,
|
|
id: dataId
|
|
},
|
|
success: function(response) {
|
|
if (!response.success) {
|
|
displayMsg(0, response.message || "Der Wettkampf konnte nicht gelöscht werden");
|
|
return;
|
|
}
|
|
|
|
$row.remove();
|
|
|
|
displayMsg(1, "Wettkampf gelöscht");
|
|
|
|
},
|
|
error: () => {
|
|
displayMsg(0, "Fehler beim Löschen des Wettkampfes");
|
|
}
|
|
});
|
|
|
|
});
|
|
|
|
$(document).on('change', '.ajaxInput', function () {
|
|
const $input = $(this);
|
|
const value = $input.val().trim();
|
|
const inputType = $input.data('type');
|
|
const dataId = $input.data('id');
|
|
|
|
if (value === '') {
|
|
displayMsg(2, "Dieses Feld darf nicht leer sein");
|
|
return;
|
|
}
|
|
|
|
if (inputType === "slug") {
|
|
if (/\s/.test(value)) {
|
|
displayMsg(2, "Der Slug darf keine Leerzeichen enthalten");
|
|
return;
|
|
}
|
|
|
|
if (!/^[a-z0-9-]+$/.test(value)) {
|
|
displayMsg(2, "Der Slug darf nur Kleinbuchstaben, Zahlen und Bindestriche enthalten");
|
|
return;
|
|
}
|
|
}
|
|
|
|
$.ajax({
|
|
url: '/intern/scripts/wettkaempfe/ajax-update-wettkampf.php',
|
|
type: "POST",
|
|
data: {
|
|
csrf_token,
|
|
id: dataId,
|
|
value,
|
|
inputType
|
|
},
|
|
success: function(response) {
|
|
if (!response.success) {
|
|
displayMsg(0, response.message || "Wert konnte nicht geändert werden");
|
|
return;
|
|
}
|
|
|
|
displayMsg(1, "Wert geändert");
|
|
|
|
},
|
|
error: () => {
|
|
displayMsg(0, "Fehler beim Ändern des Wertes");
|
|
}
|
|
});
|
|
|
|
});
|
|
|
|
$(document).on('click', '.activateSpan', async function() {
|
|
const $btn = $(this);
|
|
const dataId = $btn.data('id');
|
|
|
|
if (!await displayConfirm(`Das wechseln des Wettkampfes lädt alle Daten in der Kampfrichteransicht und RankLive neu.`)) return;
|
|
|
|
$.ajax({
|
|
url: '/intern/scripts/wettkaempfe/ajax-update-aktiv-wettkampf.php',
|
|
type: "POST",
|
|
data: {
|
|
csrf_token,
|
|
id: dataId
|
|
},
|
|
success: function(response) {
|
|
if (!response.success) {
|
|
displayMsg(0, response.message || "Aktiver Wettkampf konnte nicht geändert werden");
|
|
return;
|
|
}
|
|
|
|
const $tbody = $btn.closest('tbody');
|
|
|
|
// 1. Show ALL activation triggers in the table again
|
|
$tbody.find('.activateSpan').removeClass('hidden');
|
|
|
|
// 2. Hide only the trigger that was just clicked
|
|
$btn.addClass('hidden');
|
|
|
|
// 3. Find the single currently active swatch and turn it inactive
|
|
$tbody.find('.statusSpan.activeWk')
|
|
.removeClass('activeWk')
|
|
.addClass('inactiveWk')
|
|
.text('Inaktiv');
|
|
|
|
// 4. Find the swatch in the CURRENT row and turn it active
|
|
// (Using .closest('tr') ensures we look inside the same row)
|
|
$btn.closest('tr')
|
|
.find('.statusSpan')
|
|
.removeClass('inactiveWk')
|
|
.addClass('activeWk')
|
|
.text('Aktiv');
|
|
|
|
displayMsg(1, "Aktiver Wettkampf wurde gewechselt");
|
|
|
|
},
|
|
error: () => {
|
|
displayMsg(0, "Fehler beim Ändern des aktiven Wettkampfes");
|
|
}
|
|
});
|
|
});
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
<?php endif; ?>
|