All checks were successful
Deploy Workshop-Wahlen (DEV / PROD) / deploy (push) Successful in 13s
238 lines
11 KiB
PHP
238 lines
11 KiB
PHP
<?php
|
|
add_shortcode('konficastle_workshop_ergebnis', function($atts) {
|
|
$atts = shortcode_atts(['wahl'=>null], $atts);
|
|
$wahl_id = intval($atts['wahl']);
|
|
|
|
global $wpdb;
|
|
$wahl = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}kc_wahlen WHERE id=$wahl_id");
|
|
if(!$wahl) return '';
|
|
// Keine Warnmeldung im Frontend anzeigen, Ergebnisse weiterhin darstellen
|
|
|
|
// Workshops für diese Wahl holen
|
|
$workshops = $wpdb->get_results(
|
|
"SELECT ws.id, ws.name
|
|
FROM {$wpdb->prefix}kc_workshops ws
|
|
JOIN {$wpdb->prefix}kc_wahl_workshops ww ON ws.id = ww.workshop_id
|
|
WHERE ww.wahl_id = ".intval($wahl_id)
|
|
);
|
|
$ws_names = [];
|
|
$ws_ids = [];
|
|
foreach($workshops as $ws) {
|
|
$ws_names[$ws->id] = $ws->name;
|
|
$ws_ids[] = intval($ws->id);
|
|
}
|
|
|
|
// Zuteilungen holen
|
|
$rows = $wpdb->get_results(
|
|
"SELECT * FROM {$wpdb->prefix}kc_zuteilung WHERE wahl_id=".intval($wahl_id)
|
|
);
|
|
|
|
// Gruppieren nach Workshop, sortieren nach Teilnehmerzahl
|
|
$workshop_groups = [];
|
|
$nicht_zugeteilt = [];
|
|
$phases = [];
|
|
foreach($rows as $row) {
|
|
// Einträge ohne Phase komplett ignorieren
|
|
if ($row->phase === null || $row->phase === '') {
|
|
continue;
|
|
}
|
|
$phaseNum = intval($row->phase);
|
|
$phases[$phaseNum] = true;
|
|
if ($row->workshop_id && isset($ws_names[$row->workshop_id])) {
|
|
$workshop_groups[$row->workshop_id][] = $row;
|
|
} else {
|
|
$nicht_zugeteilt[] = $row;
|
|
}
|
|
}
|
|
uasort($workshop_groups, function($a, $b) {
|
|
return count($a) - count($b);
|
|
});
|
|
|
|
$phases = array_keys($phases);
|
|
sort($phases, SORT_NUMERIC);
|
|
|
|
// Teamer pro Workshop und Phase laden (mit Hierarchie: Phase-spezifisch > Wahl-weit > Feste)
|
|
$ws_teamers = [];
|
|
if (!empty($ws_ids)) {
|
|
// Für JEDEN Workshop einzeln laden
|
|
foreach($ws_ids as $ws_id) {
|
|
foreach($phases as $phase) {
|
|
// 1. Versuche Phase-spezifische Teamer zu laden
|
|
$trows = $wpdb->get_results($wpdb->prepare(
|
|
"SELECT t.vorname, t.nachname FROM {$wpdb->prefix}kc_workshop_teamer wt
|
|
JOIN {$wpdb->prefix}kc_teamer t ON wt.teamer_id = t.id
|
|
WHERE wt.workshop_id = %d AND wt.wahl_id = %d AND wt.phase = %d",
|
|
$ws_id, $wahl_id, $phase
|
|
));
|
|
|
|
// 2. Falls nicht: Versuche Wahl-weite Teamer zu laden
|
|
if (empty($trows)) {
|
|
$trows = $wpdb->get_results($wpdb->prepare(
|
|
"SELECT t.vorname, t.nachname FROM {$wpdb->prefix}kc_workshop_teamer wt
|
|
JOIN {$wpdb->prefix}kc_teamer t ON wt.teamer_id = t.id
|
|
WHERE wt.workshop_id = %d AND wt.wahl_id = %d AND wt.phase IS NULL",
|
|
$ws_id, $wahl_id
|
|
));
|
|
}
|
|
|
|
// 3. Falls nicht: Lade Feste Teamer
|
|
if (empty($trows)) {
|
|
$trows = $wpdb->get_results($wpdb->prepare(
|
|
"SELECT t.vorname, t.nachname FROM {$wpdb->prefix}kc_workshop_teamer wt
|
|
JOIN {$wpdb->prefix}kc_teamer t ON wt.teamer_id = t.id
|
|
WHERE wt.workshop_id = %d AND wt.wahl_id IS NULL AND wt.phase IS NULL",
|
|
$ws_id
|
|
));
|
|
}
|
|
|
|
if (!empty($trows)) {
|
|
$key = intval($ws_id) . '_' . intval($phase);
|
|
$ws_teamers[$key] = [];
|
|
foreach ($trows as $tr) {
|
|
$ws_teamers[$key][] = trim($tr->vorname.' '.$tr->nachname);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Versuche, Teilnehmer-IDs aus Cookie zu lesen (falls vorhanden)
|
|
$my_ids = [];
|
|
$cookie_name = 'kc_my_part_' . intval($wahl_id);
|
|
if (!empty($_COOKIE[$cookie_name])) {
|
|
$decoded = json_decode(stripslashes($_COOKIE[$cookie_name]), true);
|
|
if (is_array($decoded)) $my_ids = array_map('intval', $decoded);
|
|
}
|
|
|
|
ob_start();
|
|
// Inline styles, angepasst an konfi-castle.com Look (dezent, grün/türkis Akzent)
|
|
echo '<style>
|
|
.kc-result{font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;color:#222;}
|
|
.kc-result h3{margin-top:0;text-align:center;color:#154a3b;}
|
|
.kc-phase{margin:18px 0;padding:12px;border-radius:12px;background:#fbfffe;border:1px solid #e6f3ee;}
|
|
/* Responsive Kachel-Layout: auto-fit with minmax so cards wrap based on viewport */
|
|
.kc-result .kc-inner { max-width:1100px; margin:0 auto; padding:0 14px; box-sizing:border-box; }
|
|
.kc-workshops-grid{display:grid;grid-template-columns:repeat(auto-fit, minmax(260px, 1fr));gap:14px;margin-top:12px;align-items:start;}
|
|
.kc-workshop-card{background:#ffffff;border-radius:12px;overflow:hidden;border:1px solid #e9f4f0;box-shadow:0 2px 6px rgba(8,38,28,0.04);width:100%;}
|
|
/* Zentrierter, prominenter Titelbereich in der Mitte oben der Kachel */
|
|
.kc-workshop-card .title{background:linear-gradient(90deg, rgba(45,166,106,0.04), rgba(13,89,71,0.02));display:flex;flex-wrap:wrap;align-items:center;justify-content:center;padding:18px 12px;font-weight:800;color:#0d5947;font-size:1.06rem;letter-spacing:0.2px;border-bottom:1px solid rgba(229,244,240,0.8);gap:12px;}
|
|
.kc-workshop-card .title .count{color:#6b6b6b;font-weight:600;font-size:0.9rem;margin-left:6px;}
|
|
.kc-workshop-card .title .teamers{font-weight:600;color:#145a47;font-size:0.9rem;opacity:0.92;}
|
|
.kc-workshop-card .title .teamers small{font-weight:500;color:#4c7a6a;opacity:0.9;font-size:0.85rem;margin-left:6px;}
|
|
/* Content-Bereich unter dem Titel mit etwas mehr Luft */
|
|
.kc-workshop-card .content{padding:12px 18px 18px 18px;}
|
|
.kc-participants{display:grid;grid-template-columns:1fr 1fr;gap:6px 12px;font-size:0.95rem;color:#2b2b2b;}
|
|
.kc-participant{padding:6px 8px;border-radius:6px;background:transparent;}
|
|
.kc-participant.me{background:#fffbe6;border:1px solid #ffeab2;}
|
|
.kc-notassigned{background:#fff6f6;border:1px solid #ffd2d2;padding:12px;border-radius:10px;margin-top:12px;}
|
|
/* Auf sehr kleinen Bildschirmen die Teilnehmer ebenfalls einspaltig */
|
|
@media(max-width:700px){ .kc-participants{grid-template-columns:1fr;} }
|
|
</style>';
|
|
|
|
echo '<div class="kc-result">';
|
|
echo '<h3>Ergebnis für diese Wahl</h3>';
|
|
|
|
// Falls persönliche IDs vorhanden: zeige persönliche Zuteilung oben
|
|
$personal_shown = false;
|
|
if (!empty($my_ids)) {
|
|
// Suche Zuteilungen für meine IDs
|
|
$my_rows = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}kc_zuteilung WHERE wahl_id=".intval($wahl_id)." AND id IN (" . implode(',', array_map('intval', $my_ids)) . ")");
|
|
if (!empty($my_rows)) {
|
|
// Entferntes <br> nach "Deine Zuteilung"
|
|
echo '<div style="background:#e8f9ef;border-left:6px solid #2da66a;padding:12px 14px;margin-bottom:12px;border-radius:8px;">';
|
|
echo '<b>Deine Zuteilung</b><ul style="margin:6px 0 0 16px;">';
|
|
foreach($my_rows as $mr) {
|
|
$wslabel = ($mr->workshop_id && isset($ws_names[$mr->workshop_id])) ? $ws_names[$mr->workshop_id] : ($mr->workshop_id ? 'ID '.$mr->workshop_id : 'Nicht zugeteilt');
|
|
echo '<li>'.esc_html($mr->vorname.' '.$mr->nachname).' (Phase '.intval($mr->phase).') — '.esc_html($wslabel).'</li>';
|
|
}
|
|
echo '</ul></div>';
|
|
$personal_shown = true;
|
|
}
|
|
}
|
|
|
|
// Für jede Phase: Workshops nebeneinander darstellen
|
|
foreach($phases as $phase) {
|
|
echo '<div class="kc-phase">';
|
|
echo '<h4 style="margin:6px 0;text-align:center;">Phase '.intval($phase).'</h4>';
|
|
echo '<div class="kc-workshops-grid">';
|
|
// Sammle nur Workshops mit Teilnehmern in dieser Phase
|
|
$display = [];
|
|
foreach($ws_names as $ws_id => $ws_name) {
|
|
$teilnehmer = [];
|
|
if (isset($workshop_groups[$ws_id])) {
|
|
foreach($workshop_groups[$ws_id] as $t) {
|
|
if (intval($t->phase) === intval($phase)) $teilnehmer[] = $t;
|
|
}
|
|
}
|
|
$count = count($teilnehmer);
|
|
if ($count === 0) continue; // nur Workshops mit TN anzeigen
|
|
$display[] = [
|
|
'id' => $ws_id,
|
|
'name' => $ws_name,
|
|
'teilnehmer' => $teilnehmer,
|
|
'count' => $count
|
|
];
|
|
}
|
|
|
|
// Nach Teilnehmerzahl aufsteigend sortieren (kleinste oben, größte unten)
|
|
usort($display, function($a, $b) {
|
|
return $a['count'] - $b['count'];
|
|
});
|
|
|
|
// Ausgabe der sortierten Kacheln
|
|
foreach($display as $d) {
|
|
$ws_name = $d['name'];
|
|
$teilnehmer = $d['teilnehmer'];
|
|
$count = $d['count'];
|
|
|
|
// Sortiere so, dass persönliche Teilnehmer zuerst kommen
|
|
if (!empty($my_ids) && !empty($teilnehmer)) {
|
|
usort($teilnehmer, function($a, $b) use ($my_ids) {
|
|
$a_my = in_array(intval($a->id), $my_ids);
|
|
$b_my = in_array(intval($b->id), $my_ids);
|
|
if ($a_my && !$b_my) return -1;
|
|
if (!$a_my && $b_my) return 1;
|
|
return 0;
|
|
});
|
|
}
|
|
|
|
echo '<div class="kc-workshop-card">';
|
|
// Teamernamen (falls vorhanden) anzeigen - mit Phase-Key
|
|
$teamer_html = '';
|
|
$teamer_key = intval($d['id']) . '_' . intval($phase);
|
|
if (!empty($ws_teamers[$teamer_key])) {
|
|
$teamer_html = '<span class="teamers">'.esc_html(implode(', ', $ws_teamers[$teamer_key])).'</span>';
|
|
}
|
|
echo '<div class="title">'.esc_html($ws_name).' '. $teamer_html .'<span class="count">('.$count.' TN)</span></div>';
|
|
echo '<div class="content">';
|
|
echo '<div class="kc-participants">';
|
|
foreach($teilnehmer as $t) {
|
|
$is_me = in_array(intval($t->id), $my_ids);
|
|
$name = esc_html($t->vorname.' '.$t->nachname);
|
|
$label = $name . ' <span style="color:#6b6b6b;font-size:85%;">('.intval($t->phase).')</span>';
|
|
echo '<div class="kc-participant'.($is_me ? ' me' : '').'">'. $label .'</div>';
|
|
}
|
|
echo '</div>'; // kc-participants
|
|
echo '</div>'; // content
|
|
echo '</div>';
|
|
}
|
|
|
|
echo '</div>'; // kc-workshops-grid
|
|
echo '</div>'; // kc-phase
|
|
}
|
|
|
|
// Extra: Nicht zugeteilt
|
|
if (!empty($nicht_zugeteilt)) {
|
|
echo '<div class="kc-notassigned">';
|
|
echo '<b>Nicht zugeteilt:</b><br>';
|
|
echo '<ul style="margin:6px 0 0 18px;">';
|
|
foreach($nicht_zugeteilt as $t) {
|
|
echo '<li>'.esc_html($t->vorname.' '.$t->nachname).' (Phase '.intval($t->phase).')</li>';
|
|
}
|
|
echo '</ul></div>';
|
|
}
|
|
|
|
echo '</div>'; // kc-result
|
|
return ob_get_clean();
|
|
});
|
|
?>
|