All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 13s
557 lines
28 KiB
PHP
557 lines
28 KiB
PHP
<?php
|
||
function kc_teilnehmer_page() {
|
||
global $wpdb;
|
||
$prefix = $wpdb->prefix;
|
||
kc_admin_tabs('kc_teilnehmer');
|
||
// Alle Wahlen + Workshops für Dropdowns und Validierung
|
||
$all_wahlen = $wpdb->get_results("SELECT id, name, anzahl_einheiten FROM {$prefix}kc_wahlen WHERE deleted=0 ORDER BY id DESC");
|
||
$all_workshops = $wpdb->get_results("SELECT id, name FROM {$prefix}kc_workshops ORDER BY name");
|
||
|
||
// Map of wahl id => name for quick lookup
|
||
$wahl_name_map = [];
|
||
if (!empty($all_wahlen)) {
|
||
foreach ($all_wahlen as $w) {
|
||
$wahl_name_map[intval($w->id)] = $w->name;
|
||
}
|
||
}
|
||
|
||
// Map of workshop id => name for quick lookup in overview
|
||
$workshops_map = [];
|
||
if (!empty($all_workshops)) {
|
||
foreach ($all_workshops as $ws) {
|
||
$workshops_map[intval($ws->id)] = $ws->name;
|
||
}
|
||
}
|
||
|
||
// CSV-Export (alle Teilnehmer oder gefiltert nach Wahl/Phase)
|
||
if (isset($_GET['export_csv']) && current_user_can('manage_options')) {
|
||
$export_wahl_id = isset($_GET['wahl_id']) ? intval($_GET['wahl_id']) : 0;
|
||
$export_phase = isset($_GET['phase']) ? intval($_GET['phase']) : 0;
|
||
|
||
$sql = "SELECT * FROM {$prefix}kc_teilnehmer";
|
||
if ($export_wahl_id > 0 && $export_phase > 0) {
|
||
$sql .= $wpdb->prepare(" WHERE wahl_id=%d AND phase=%d", $export_wahl_id, $export_phase);
|
||
} elseif ($export_wahl_id > 0) {
|
||
$sql .= $wpdb->prepare(" WHERE wahl_id=%d", $export_wahl_id);
|
||
} elseif ($export_phase > 0) {
|
||
$sql .= $wpdb->prepare(" WHERE phase=%d", $export_phase);
|
||
}
|
||
$sql .= " ORDER BY wahl_id, phase, nachname, vorname";
|
||
$export_rows = $wpdb->get_results($sql);
|
||
|
||
$filename_suffix = '_alle';
|
||
if ($export_wahl_id > 0) {
|
||
$wahl_name_for_file = isset($wahl_name_map[$export_wahl_id]) ? $wahl_name_map[$export_wahl_id] : ('wahl_'.$export_wahl_id);
|
||
$wahl_slug = sanitize_title($wahl_name_for_file);
|
||
if ($wahl_slug === '') {
|
||
$wahl_slug = 'wahl_'.$export_wahl_id;
|
||
}
|
||
$filename_suffix = '_'.$wahl_slug;
|
||
if ($export_phase > 0) {
|
||
$filename_suffix .= '_phase_'.$export_phase;
|
||
}
|
||
} elseif ($export_phase > 0) {
|
||
$filename_suffix = '_phase_'.$export_phase;
|
||
}
|
||
header('Content-Type: text/csv; charset=utf-8');
|
||
header('Content-Disposition: attachment; filename="kc_teilnehmer'.$filename_suffix.'.csv"');
|
||
echo "\xEF\xBB\xBF";
|
||
|
||
$output = fopen('php://output', 'w');
|
||
$delimiter = ';';
|
||
fputcsv($output, ['Vorname','Nachname','Wahl','Phase','Wunsch 1','Wunsch 2','Wunsch 3'], $delimiter);
|
||
|
||
foreach ($export_rows as $tn) {
|
||
$w1_id = intval($tn->wunsch1);
|
||
$w2_id = intval($tn->wunsch2);
|
||
$w3_id = intval($tn->wunsch3);
|
||
|
||
$w1_disp = $w1_id && isset($workshops_map[$w1_id]) ? $workshops_map[$w1_id] : ($w1_id ? strval($w1_id) : '');
|
||
$w2_disp = $w2_id && isset($workshops_map[$w2_id]) ? $workshops_map[$w2_id] : ($w2_id ? strval($w2_id) : '');
|
||
$w3_disp = $w3_id && isset($workshops_map[$w3_id]) ? $workshops_map[$w3_id] : ($w3_id ? strval($w3_id) : '');
|
||
|
||
$wahl_name = isset($wahl_name_map[intval($tn->wahl_id)]) ? $wahl_name_map[intval($tn->wahl_id)] : '';
|
||
|
||
$vorname = preg_replace('/<[^>]*>/', '', $tn->vorname);
|
||
$nachname = preg_replace('/<[^>]*>/', '', $tn->nachname);
|
||
$wahl_name_clean = preg_replace('/<[^>]*>/', '', $wahl_name);
|
||
$w1_clean = preg_replace('/<[^>]*>/', '', $w1_disp);
|
||
$w2_clean = preg_replace('/<[^>]*>/', '', $w2_disp);
|
||
$w3_clean = preg_replace('/<[^>]*>/', '', $w3_disp);
|
||
|
||
fputcsv($output, [
|
||
$vorname,
|
||
$nachname,
|
||
$wahl_name_clean,
|
||
intval($tn->phase),
|
||
$w1_clean,
|
||
$w2_clean,
|
||
$w3_clean
|
||
], $delimiter);
|
||
}
|
||
|
||
fclose($output);
|
||
exit;
|
||
}
|
||
|
||
// Build map of wahl -> phases + workshops (for JS)
|
||
$wahl_map = [];
|
||
foreach($all_wahlen as $w) {
|
||
$wahl_map[intval($w->id)] = ['phases' => max(1,intval($w->anzahl_einheiten)), 'workshops' => []];
|
||
}
|
||
if (!empty($all_workshops)) {
|
||
foreach($all_workshops as $ws) {
|
||
$ww = $wpdb->get_col($wpdb->prepare("SELECT wahl_id FROM {$prefix}kc_wahl_workshops WHERE workshop_id=%d", $ws->id));
|
||
if (!empty($ww)) {
|
||
foreach($ww as $wid) {
|
||
if (isset($wahl_map[intval($wid)])) {
|
||
$wahl_map[intval($wid)]['workshops'][] = ['id'=>intval($ws->id),'name'=>$ws->name];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Teilnehmer l<>schen
|
||
if (isset($_GET['delete_teilnehmer'])) {
|
||
$tid = intval($_GET['delete_teilnehmer']);
|
||
$wpdb->delete("{$prefix}kc_teilnehmer", ['id' => $tid]);
|
||
echo '<div class="notice notice-success">Teilnehmer gel<65>scht!</div>';
|
||
}
|
||
|
||
// Teilnehmer speichern (neu/<2F>ndern)
|
||
if (isset($_POST['kc_teilnehmer_save'])) {
|
||
// sanitize inputs
|
||
$vorname = sanitize_text_field($_POST['vorname']);
|
||
$nachname = sanitize_text_field($_POST['nachname']);
|
||
$wahl_id_post = intval($_POST['wahl_id']);
|
||
$phase_post = intval($_POST['phase']);
|
||
$w1 = intval($_POST['wunsch1']);
|
||
$w2 = intval($_POST['wunsch2']);
|
||
$w3 = intval($_POST['wunsch3']);
|
||
|
||
// Server-side validation: duplicate name in same Wahl (exclude self on edit)
|
||
$norm_v = mb_strtolower(trim($vorname));
|
||
$norm_n = mb_strtolower(trim($nachname));
|
||
if (!empty($_POST['tid'])) {
|
||
$exclude_id = intval($_POST['tid']);
|
||
$exists = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$prefix}kc_teilnehmer WHERE LOWER(TRIM(vorname))=%s AND LOWER(TRIM(nachname))=%s AND wahl_id=%d AND id<>%d", $norm_v, $norm_n, $wahl_id_post, $exclude_id));
|
||
} else {
|
||
$exists = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$prefix}kc_teilnehmer WHERE LOWER(TRIM(vorname))=%s AND LOWER(TRIM(nachname))=%s AND wahl_id=%d", $norm_v, $norm_n, $wahl_id_post));
|
||
}
|
||
if ($exists && $exists > 0) {
|
||
echo '<div class="notice notice-error">Diese Kombination aus Vorname und Nachname existiert bereits für diese Wahl.</div>';
|
||
} else {
|
||
// validate phase within wahl
|
||
$wahl_row = $wpdb->get_row($wpdb->prepare("SELECT anzahl_einheiten FROM {$prefix}kc_wahlen WHERE id=%d", $wahl_id_post));
|
||
$max_ph = $wahl_row ? max(1,intval($wahl_row->anzahl_einheiten)) : 1;
|
||
if ($phase_post < 1 || $phase_post > $max_ph) {
|
||
echo '<div class="notice notice-error">Ungültige Phase für die gewählte Wahl.</div>';
|
||
} else {
|
||
// validate that selected workshops belong to the chosen wahl (if mapping exists)
|
||
$valid_ws = [];
|
||
$ww_rows = $wpdb->get_col($wpdb->prepare("SELECT workshop_id FROM {$prefix}kc_wahl_workshops WHERE wahl_id=%d", $wahl_id_post));
|
||
if (!empty($ww_rows)) foreach($ww_rows as $r) $valid_ws[] = intval($r);
|
||
// if mapping exists, enforce membership
|
||
$check_membership = function($wid) use ($valid_ws) {
|
||
if (empty($valid_ws)) return true; // no mapping -> allow
|
||
return in_array(intval($wid), $valid_ws);
|
||
};
|
||
if (!$check_membership($w1) || !$check_membership($w2) || !$check_membership($w3)) {
|
||
echo '<div class="notice notice-error">Einer oder mehrere ausgewählte Workshops gehören nicht zur gewählten Wahl.</div>';
|
||
} else {
|
||
$data = [
|
||
'vorname' => $vorname,
|
||
'nachname' => $nachname,
|
||
'wahl_id' => $wahl_id_post,
|
||
'phase' => $phase_post,
|
||
'wunsch1' => $w1,
|
||
'wunsch2' => $w2,
|
||
'wunsch3' => $w3
|
||
];
|
||
if (!empty($_POST['tid'])) {
|
||
$wpdb->update("{$prefix}kc_teilnehmer", $data, ['id'=>intval($_POST['tid'])]);
|
||
echo '<div class="notice notice-success">Teilnehmer aktualisiert!</div>';
|
||
} else {
|
||
$wpdb->insert("{$prefix}kc_teilnehmer", $data);
|
||
echo '<div class="notice notice-success">Teilnehmer angelegt!</div>';
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Teilnehmer bearbeiten
|
||
if (isset($_GET['edit_teilnehmer'])) {
|
||
$tid = intval($_GET['edit_teilnehmer']);
|
||
$tn = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$prefix}kc_teilnehmer WHERE id=%d", $tid));
|
||
echo '<div class="kc-admin-table-wrap">';
|
||
echo '<h2>Teilnehmer bearbeiten</h2>';
|
||
echo '<form method="post">';
|
||
echo '<input type="hidden" name="tid" value="'.intval($tn->id).'">';
|
||
echo '<input type="text" name="vorname" placeholder="Vorname" value="'.esc_attr($tn->vorname).'" required style="margin-bottom:8px;width:100%;padding:7px;">';
|
||
echo '<input type="text" name="nachname" placeholder="Nachname" value="'.esc_attr($tn->nachname).'" required style="margin-bottom:8px;width:100%;padding:7px;">';
|
||
|
||
// Wahl select
|
||
echo '<label style="display:block;margin:8px 0 4px 0;font-weight:700;">Wahl</label>';
|
||
echo '<select id="kc-wahl-select" name="wahl_id" required style="margin-bottom:8px;width:100%;padding:7px;">';
|
||
foreach($all_wahlen as $w) {
|
||
$selw = (intval($tn->wahl_id) === intval($w->id)) ? ' selected' : '';
|
||
echo '<option value="'.intval($w->id).'"'.$selw.'>'.esc_html($w->name).'</option>';
|
||
}
|
||
echo '</select>';
|
||
|
||
// Phase select (fallback content)
|
||
echo '<label style="display:block;margin:8px 0 4px 0;font-weight:700;">Phase</label>';
|
||
echo '<select id="kc-phase-select" name="phase" required style="margin-bottom:8px;width:100%;padding:7px;">';
|
||
$cur_phases = isset($wahl_map[intval($tn->wahl_id)]) ? $wahl_map[intval($tn->wahl_id)]['phases'] : 1;
|
||
for($i=1;$i<=$cur_phases;$i++){
|
||
$selp = (intval($tn->phase) === $i) ? ' selected' : '';
|
||
echo '<option value="'.intval($i).'"'.$selp.'>'.intval($i).'</option>';
|
||
}
|
||
echo '</select>';
|
||
|
||
// Wunsch selects
|
||
for ($k=1;$k<=3;$k++){
|
||
$cur = intval($tn->{'wunsch'.$k});
|
||
echo '<label style="display:block;margin:8px 0 4px 0;font-weight:700;">Wunsch '.intval($k).'</label>';
|
||
echo '<select id="kc-wunsch'.intval($k).'" name="wunsch'.intval($k).'" required style="margin-bottom:8px;width:100%;padding:7px;">';
|
||
echo '<option value="">Bitte Wähle einen Workshop aus</option>';
|
||
foreach($all_workshops as $ws) {
|
||
$sel = ($cur === intval($ws->id)) ? ' selected' : '';
|
||
echo '<option value="'.intval($ws->id).'"'.$sel.'>'.esc_html($ws->name).'</option>';
|
||
}
|
||
echo '</select>';
|
||
}
|
||
|
||
echo '<button name="kc_teilnehmer_save" class="kc-btn">Speichern</button>';
|
||
echo '<a href="?page=kc_teilnehmer" class="kc-btn del" style="margin-left:24px;">Abbrechen</a>';
|
||
echo '</form>';
|
||
|
||
// Provide JS map and init JS: restrict phases/workshops based on Wahl and init Select2
|
||
echo '<script>var KC_WAHL_MAP = '.json_encode($wahl_map, JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_AMP).';</script>';
|
||
echo '<script>
|
||
(function(){
|
||
function fillPhaseOptions(wid){
|
||
var ph = KC_WAHL_MAP[wid] ? KC_WAHL_MAP[wid].phases : 1;
|
||
var sel = document.getElementById("kc-phase-select"); if(!sel) return; sel.innerHTML = "";
|
||
for(var i=1;i<=ph;i++){ var o=document.createElement("option"); o.value=i; o.text=i; sel.appendChild(o); }
|
||
}
|
||
function fillWorkshopOptions(wid){
|
||
var list = KC_WAHL_MAP[wid] ? KC_WAHL_MAP[wid].workshops : [];
|
||
["kc-wunsch1","kc-wunsch2","kc-wunsch3"].forEach(function(sid){
|
||
var sel = document.getElementById(sid); if(!sel) return; var cur = sel.value; sel.innerHTML = "";
|
||
var empty = document.createElement("option"); empty.value = ""; empty.text = "Bitte Wähle einen Workshop aus"; sel.appendChild(empty);
|
||
list.forEach(function(w){ var o=document.createElement("option"); o.value = w.id; o.text = w.name; sel.appendChild(o); });
|
||
if(cur) sel.value = cur;
|
||
});
|
||
}
|
||
jQuery(function($){
|
||
try{ $("#kc-wunsch1,#kc-wunsch2,#kc-wunsch3,#kc-wahl-select,#kc-phase-select").select2({width: "100%"}); }catch(e){}
|
||
var wsel = document.getElementById("kc-wahl-select"); if(!wsel) return;
|
||
wsel.addEventListener("change", function(){ fillPhaseOptions(this.value); fillWorkshopOptions(this.value); try{ $("#kc-wunsch1,#kc-wunsch2,#kc-wunsch3,#kc-phase-select").trigger("change.select2"); }catch(e){} });
|
||
// initial fill
|
||
fillPhaseOptions(wsel.value); fillWorkshopOptions(wsel.value);
|
||
});
|
||
})();
|
||
</script>';
|
||
echo '</div>';
|
||
return;
|
||
}
|
||
|
||
// Neuer Teilnehmer anlegen
|
||
if (isset($_GET['new'])) {
|
||
echo '<div class="kc-admin-table-wrap">';
|
||
echo '<h2>Neuen Teilnehmer anlegen</h2>';
|
||
echo '<form method="post">';
|
||
echo '<input type="text" name="vorname" placeholder="Vorname" required style="margin-bottom:8px;width:100%;padding:7px;">';
|
||
echo '<input type="text" name="nachname" placeholder="Nachname" required style="margin-bottom:8px;width:100%;padding:7px;">';
|
||
|
||
echo '<label style="display:block;margin:8px 0 4px 0;font-weight:700;">Wahl</label>';
|
||
echo '<select id="kc-wahl-select" name="wahl_id" required style="margin-bottom:8px;width:100%;padding:7px;">';
|
||
foreach($all_wahlen as $w) {
|
||
echo '<option value="'.intval($w->id).'">'.esc_html($w->name).'</option>';
|
||
}
|
||
echo '</select>';
|
||
|
||
echo '<label style="display:block;margin:8px 0 4px 0;font-weight:700;">Phase</label>';
|
||
echo '<select id="kc-phase-select" name="phase" required style="margin-bottom:8px;width:100%;padding:7px;">';
|
||
$first_wahl = reset($all_wahlen);
|
||
$first_ph = $first_wahl ? max(1,intval($first_wahl->anzahl_einheiten)) : 1;
|
||
for($i=1;$i<=$first_ph;$i++) echo '<option value="'.intval($i).'">'.intval($i).'</option>';
|
||
echo '</select>';
|
||
|
||
for ($k=1;$k<=3;$k++){
|
||
echo '<label style="display:block;margin:8px 0 4px 0;font-weight:700;">Wunsch '.intval($k).'</label>';
|
||
echo '<select id="kc-wunsch'.intval($k).'" name="wunsch'.intval($k).'" required style="margin-bottom:8px;width:100%;padding:7px;">';
|
||
echo '<option value="">Bitte Wähle einen Workshop aus</option>';
|
||
foreach($all_workshops as $ws) {
|
||
echo '<option value="'.intval($ws->id).'">'.esc_html($ws->name).'</option>';
|
||
}
|
||
echo '</select>';
|
||
}
|
||
|
||
echo '<button name="kc_teilnehmer_save" class="kc-btn">Speichern</button>';
|
||
echo '<a href="?page=kc_teilnehmer" class="kc-btn del" style="margin-left:24px;">Abbrechen</a>';
|
||
echo '</form>';
|
||
// Init Select2 for nicer selects if available
|
||
echo '<script>jQuery(function($){try{ $("#kc-wunsch1,#kc-wunsch2,#kc-wunsch3,#kc-wahl-select,#kc-phase-select").select2({width:"100%"}); }catch(e){} });</script>';
|
||
echo '</div>';
|
||
return;
|
||
}
|
||
|
||
// Übersicht
|
||
// Map für Wahl-ID => Name ist bereits oben aufgebaut
|
||
$selected_export_wahl = isset($_GET['wahl_id']) ? intval($_GET['wahl_id']) : 0;
|
||
$selected_export_phase = isset($_GET['phase']) ? intval($_GET['phase']) : 0;
|
||
|
||
echo '<div class="kc-admin-table-wrap">';
|
||
echo '<h2 style="margin-top:0;">Alle Teilnehmer</h2>';
|
||
echo '<a id="kc-export-current-view" class="kc-btn" style="float:right;margin-right:8px;margin-bottom:12px;background:#2da66a;color:#fff;" href="?page=kc_teilnehmer&export_csv=1">CSV Export (Ansicht)</a>';
|
||
echo '<a class="kc-btn" style="float:right;margin-bottom:12px;" href="?page=kc_teilnehmer&new=1">+ Neuer Teilnehmer</a>';
|
||
|
||
// Manuelle Export-Auswahl (Wahl + Phase)
|
||
echo '<form method="get" id="kc-export-form" style="clear:both;margin:8px 0 12px 0;display:flex;gap:8px;align-items:center;flex-wrap:wrap;">';
|
||
echo '<input type="hidden" name="page" value="kc_teilnehmer">';
|
||
echo '<input type="hidden" name="export_csv" value="1">';
|
||
echo '<label for="kc-export-wahl" style="font-weight:600;">Export Wahl:</label>';
|
||
echo '<select id="kc-export-wahl" name="wahl_id" style="padding:6px 8px;min-width:180px;">';
|
||
echo '<option value="">Alle Wahlen</option>';
|
||
foreach($all_wahlen as $w) {
|
||
$selected = ($selected_export_wahl === intval($w->id)) ? ' selected' : '';
|
||
echo '<option value="'.intval($w->id).'"'.$selected.'>'.esc_html($w->name).'</option>';
|
||
}
|
||
echo '</select>';
|
||
echo '<label for="kc-export-phase" style="font-weight:600;">Phase:</label>';
|
||
echo '<select id="kc-export-phase" name="phase" data-current="'.intval($selected_export_phase).'" style="padding:6px 8px;min-width:140px;">';
|
||
echo '<option value="">Alle Phasen</option>';
|
||
echo '</select>';
|
||
echo '<button type="submit" class="kc-btn" style="background:#2da66a;color:#fff;">CSV Export (Auswahl)</button>';
|
||
echo '</form>';
|
||
|
||
// Wahl-Filter-Buttons sortiert nach KC1, KC2, KC3, dann Rest
|
||
$kc_buttons = [];
|
||
$rest_buttons = [];
|
||
foreach($all_wahlen as $w) {
|
||
$name = strtoupper($w->name);
|
||
if ($name === 'KC1' || $name === 'KC2' || $name === 'KC3') {
|
||
$kc_buttons[$name] = $w;
|
||
} else {
|
||
$rest_buttons[] = $w;
|
||
}
|
||
}
|
||
echo '<div style="margin:12px 0;clear:both;display:flex;gap:8px;align-items:center;flex-wrap:wrap;">'
|
||
.'<label style="font-weight:600;">Wahlen filtern:</label>';
|
||
echo '<button type="button" class="kc-btn kc-wahl-filter-btn" data-wahl-id="" style="padding:6px 10px;">Alle</button>';
|
||
foreach(["KC1","KC2","KC3"] as $kc) {
|
||
if(isset($kc_buttons[$kc])) {
|
||
$w = $kc_buttons[$kc];
|
||
echo '<button type="button" class="kc-btn kc-wahl-filter-btn" data-wahl-id="'.intval($w->id).'" style="padding:6px 10px;">'.esc_html($w->name).'</button>';
|
||
}
|
||
}
|
||
foreach($rest_buttons as $w) {
|
||
echo '<button type="button" class="kc-btn kc-wahl-filter-btn" data-wahl-id="'.intval($w->id).'" style="padding:6px 10px;">'.esc_html($w->name).'</button>';
|
||
}
|
||
echo '<span id="kc-wahl-filter-count" style="color:#666;font-size:90%;margin-left:12px;">Alle anzeigen</span>';
|
||
echo '</div>';
|
||
|
||
// Platzhalter für Phasen-Filter
|
||
echo '<div id="kc-phase-filter-row" style="display:none;margin:8px 0 16px 0;gap:8px;align-items:center;flex-wrap:wrap;"></div>';
|
||
|
||
// Teilnehmer laden und gruppieren nach Wahl und Phase
|
||
$teilnehmer = $wpdb->get_results("SELECT * FROM {$prefix}kc_teilnehmer ORDER BY wahl_id, phase, nachname, vorname");
|
||
$gruppen = [];
|
||
foreach ($teilnehmer as $tn) {
|
||
$wid = intval($tn->wahl_id);
|
||
$ph = intval($tn->phase);
|
||
$gruppen[$wid][$ph][] = $tn;
|
||
}
|
||
|
||
foreach ($gruppen as $wid => $phasen) {
|
||
$wahl_disp = isset($wahl_name_map[$wid]) ? esc_html($wahl_name_map[$wid]) : $wid;
|
||
$csv_wahl_url = add_query_arg([
|
||
'page' => 'kc_teilnehmer',
|
||
'export_csv' => 1,
|
||
'wahl_id' => intval($wid)
|
||
], admin_url('admin.php'));
|
||
// Gesamtanzahl Teilnehmer für diese Wahl berechnen
|
||
$gesamt = 0;
|
||
foreach ($phasen as $tns) $gesamt += count($tns);
|
||
echo '<details style="margin:10px 0 18px 0;border:1px solid #eaeaea;border-radius:6px;padding:8px;">';
|
||
echo '<summary style="font-weight:700;cursor:pointer;">'. $wahl_disp . ' <span style="color:#555;font-weight:600;">(' . $gesamt . ' TN)</span></summary>';
|
||
echo '<div style="text-align:right;margin:8px 0 4px 0;">';
|
||
echo '<a class="kc-btn" style="background:#2da66a;color:#fff;" href="'.esc_url($csv_wahl_url).'">CSV Export dieser Wahl</a>';
|
||
echo '</div>';
|
||
foreach ($phasen as $phase => $tns) {
|
||
echo '<details style="margin:10px 0 10px 0;border:1px solid #f0f0f0;border-radius:6px;padding:8px;">';
|
||
echo '<summary style="font-weight:600;">Phase '.intval($phase).' <span style="color:#555;font-weight:600;">('.count($tns).' TN)</span></summary>';
|
||
echo '<table class="kc-admin-table" style="margin:8px 0;">';
|
||
echo '<thead><tr><th>Vorname</th><th>Nachname</th><th>Wahl</th><th>Phase</th><th>Wunsch 1</th><th>Wunsch 2</th><th>Wunsch 3</th><th>Aktion</th></tr></thead><tbody>';
|
||
foreach ($tns as $tn) {
|
||
$w1_id = intval($tn->wunsch1);
|
||
$w2_id = intval($tn->wunsch2);
|
||
$w3_id = intval($tn->wunsch3);
|
||
$w1_disp = $w1_id && isset($workshops_map[$w1_id]) ? esc_html($workshops_map[$w1_id]) : ($w1_id ? intval($w1_id) : '<em style="color:#999;">Keine</em>');
|
||
$w2_disp = $w2_id && isset($workshops_map[$w2_id]) ? esc_html($workshops_map[$w2_id]) : ($w2_id ? intval($w2_id) : '<em style="color:#999;">Keine</em>');
|
||
$w3_disp = $w3_id && isset($workshops_map[$w3_id]) ? esc_html($workshops_map[$w3_id]) : ($w3_id ? intval($w3_id) : '<em style="color:#999;">Keine</em>');
|
||
$wahl_disp = isset($wahl_name_map[intval($tn->wahl_id)]) ? esc_html($wahl_name_map[intval($tn->wahl_id)]) : intval($tn->wahl_id);
|
||
echo "<tr data-wahl-id='".intval($tn->wahl_id)."'>
|
||
<td>".esc_html($tn->vorname)."</td>
|
||
<td>".esc_html($tn->nachname)."</td>
|
||
<td>".$wahl_disp."</td>
|
||
<td>".intval($tn->phase)."</td>
|
||
<td>".$w1_disp."</td>
|
||
<td>".$w2_disp."</td>
|
||
<td>".$w3_disp."</td>
|
||
<td class='kc-actions'>
|
||
<a class='kc-btn edit' href='?page=kc_teilnehmer&edit_teilnehmer={$tn->id}'>Bearbeiten</a>
|
||
<a class='kc-btn del' href='?page=kc_teilnehmer&delete_teilnehmer={$tn->id}' onclick=\"return confirm('Wirklich löschen?');\">Löschen</a>
|
||
</td>
|
||
</tr>";
|
||
}
|
||
echo '</tbody></table>';
|
||
echo '</details>';
|
||
}
|
||
echo '</details>';
|
||
}
|
||
// JS für Wahl- und Phasen-Filter
|
||
echo '<style>.kc-wahl-filter-btn.active{background:#4CAF50;color:#fff;} .kc-phase-filter-btn.active{background:#1976d2;color:#fff;}</style>';
|
||
echo '<script>
|
||
(function() {
|
||
var btns = Array.prototype.slice.call(document.querySelectorAll(".kc-wahl-filter-btn"));
|
||
var rows = Array.prototype.slice.call(document.querySelectorAll(".kc-admin-table tbody tr"));
|
||
var status = document.getElementById("kc-wahl-filter-count");
|
||
var phaseRow = document.getElementById("kc-phase-filter-row");
|
||
var exportBtn = document.getElementById("kc-export-current-view");
|
||
var exportWahlSelect = document.getElementById("kc-export-wahl");
|
||
var exportPhaseSelect = document.getElementById("kc-export-phase");
|
||
// Wahl-Map für Phasen
|
||
var wahlMap = '.json_encode($wahl_map, JSON_HEX_TAG|JSON_HEX_APOS|JSON_HEX_QUOT|JSON_HEX_AMP).';
|
||
var currentWahl = "";
|
||
var currentPhase = "";
|
||
|
||
function renderExportPhaseOptions(wahlId) {
|
||
if (!exportPhaseSelect) return;
|
||
var wanted = exportPhaseSelect.getAttribute("data-current") || exportPhaseSelect.value || "";
|
||
exportPhaseSelect.innerHTML = "";
|
||
|
||
var allOpt = document.createElement("option");
|
||
allOpt.value = "";
|
||
allOpt.text = "Alle Phasen";
|
||
exportPhaseSelect.appendChild(allOpt);
|
||
|
||
if (wahlId && wahlMap[wahlId]) {
|
||
var maxPh = wahlMap[wahlId].phases || 1;
|
||
for (var i = 1; i <= maxPh; i++) {
|
||
var o = document.createElement("option");
|
||
o.value = String(i);
|
||
o.text = String(i);
|
||
exportPhaseSelect.appendChild(o);
|
||
}
|
||
}
|
||
|
||
if (wanted && exportPhaseSelect.querySelector("option[value=\"" + wanted + "\"]")) {
|
||
exportPhaseSelect.value = wanted;
|
||
} else {
|
||
exportPhaseSelect.value = "";
|
||
}
|
||
exportPhaseSelect.setAttribute("data-current", "");
|
||
}
|
||
|
||
function updateExportButton() {
|
||
if (!exportBtn) return;
|
||
var href = "?page=kc_teilnehmer&export_csv=1";
|
||
if (currentWahl) href += "&wahl_id=" + encodeURIComponent(currentWahl);
|
||
if (currentPhase) href += "&phase=" + encodeURIComponent(currentPhase);
|
||
exportBtn.setAttribute("href", href);
|
||
}
|
||
|
||
function renderPhaseButtons(wahlId) {
|
||
phaseRow.innerHTML = "";
|
||
if (!wahlId || !wahlMap[wahlId]) { phaseRow.style.display = "none"; currentPhase = ""; return; }
|
||
var phases = wahlMap[wahlId].phases || 1;
|
||
var label = document.createElement("label");
|
||
label.textContent = "Phasen filtern:";
|
||
label.style.fontWeight = "600";
|
||
label.style.marginRight = "8px";
|
||
phaseRow.appendChild(label);
|
||
var allBtn = document.createElement("button");
|
||
allBtn.type = "button";
|
||
allBtn.className = "kc-btn kc-phase-filter-btn active";
|
||
allBtn.setAttribute("data-phase", "");
|
||
allBtn.style.padding = "6px 10px";
|
||
allBtn.textContent = "Alle";
|
||
phaseRow.appendChild(allBtn);
|
||
for(var i=1;i<=phases;i++){
|
||
var btn = document.createElement("button");
|
||
btn.type = "button";
|
||
btn.className = "kc-btn kc-phase-filter-btn";
|
||
btn.setAttribute("data-phase", i);
|
||
btn.style.padding = "6px 10px";
|
||
btn.textContent = i;
|
||
phaseRow.appendChild(btn);
|
||
}
|
||
phaseRow.style.display = "flex";
|
||
}
|
||
|
||
function applyFilter(wahlId, phase) {
|
||
var shown = 0;
|
||
rows.forEach(function(row) {
|
||
var rid = row.getAttribute("data-wahl-id");
|
||
var ph = row.querySelector("td:nth-child(4)").textContent.trim();
|
||
var show = false;
|
||
if (!wahlId) {
|
||
show = true;
|
||
} else if (!phase) {
|
||
show = (rid == wahlId);
|
||
} else {
|
||
show = (rid == wahlId && ph == phase);
|
||
}
|
||
row.style.display = show ? "" : "none";
|
||
if (show) shown++;
|
||
});
|
||
if (status) status.textContent = (wahlId ? (shown+" angezeigt") : "Alle anzeigen");
|
||
updateExportButton();
|
||
}
|
||
|
||
function attachPhaseEvents() {
|
||
var phaseBtns = Array.prototype.slice.call(document.querySelectorAll(".kc-phase-filter-btn"));
|
||
phaseBtns.forEach(function(btn) {
|
||
btn.addEventListener("click", function() {
|
||
phaseBtns.forEach(function(b){b.classList.remove("active");});
|
||
btn.classList.add("active");
|
||
currentPhase = btn.getAttribute("data-phase");
|
||
applyFilter(currentWahl, currentPhase);
|
||
});
|
||
});
|
||
}
|
||
|
||
btns.forEach(function(btn) {
|
||
btn.addEventListener("click", function() {
|
||
btns.forEach(function(b){b.classList.remove("active");});
|
||
btn.classList.add("active");
|
||
var wahlId = btn.getAttribute("data-wahl-id");
|
||
currentWahl = wahlId;
|
||
currentPhase = "";
|
||
renderPhaseButtons(wahlId);
|
||
applyFilter(wahlId, "");
|
||
attachPhaseEvents();
|
||
});
|
||
});
|
||
// Default: Alle aktiv
|
||
if(btns.length) btns[0].classList.add("active");
|
||
renderPhaseButtons("");
|
||
applyFilter("", "");
|
||
updateExportButton();
|
||
|
||
if (exportWahlSelect) {
|
||
renderExportPhaseOptions(exportWahlSelect.value);
|
||
exportWahlSelect.addEventListener("change", function() {
|
||
renderExportPhaseOptions(this.value);
|
||
});
|
||
}
|
||
})();
|
||
</script>';
|
||
echo '</div>';
|
||
}
|
||
?>
|