From d274d5988ca257a79e06be0e1fe7fdc9336e45cb Mon Sep 17 00:00:00 2001 From: Linus Maximilian Nilson Date: Fri, 30 Jan 2026 14:51:36 +0000 Subject: [PATCH 01/13] Update konficastle-workshopwahl.php --- konficastle-workshopwahl.php | 134 +++++++++++++++++------------------ 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/konficastle-workshopwahl.php b/konficastle-workshopwahl.php index 8e71ad4..4a3b691 100644 --- a/konficastle-workshopwahl.php +++ b/konficastle-workshopwahl.php @@ -1,68 +1,68 @@ - Date: Fri, 30 Jan 2026 16:36:41 +0100 Subject: [PATCH 02/13] update README --- .github/copilot-instructions.production.md | 37 +++++++++++++++++ README.md | 48 ++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 .github/copilot-instructions.production.md diff --git a/.github/copilot-instructions.production.md b/.github/copilot-instructions.production.md new file mode 100644 index 0000000..fff5999 --- /dev/null +++ b/.github/copilot-instructions.production.md @@ -0,0 +1,37 @@ +# Copilot Instructions for Workshop-Wahlen (Production) + +## Project Overview + +This WordPress plugin manages workshop elections for Konfi-Castle events. It provides an admin backend (elections, workshops, participants, teamers, assignments) and a participant frontend. + +## Architecture & Components +- **Main file:** `konficastle-workshopwahl.php` – Initializes hooks, loads assets, admin menus. +- **Backend:** + - `includes/` with modules for elections, workshops, participants, teamers, assignments, data management, force assignment + - Core assignment logic: `includes/zuteilungslogik.php` +- **Frontend:** + - Shortcodes: `[konficastle_workshopwahl wahl=ID]`, `[konficastle_workshop_ergebnis wahl=ID]` +- **Database:** Tables are created via `install.php`, prefix: `kc_` + +## Key Patterns & Workflows +- **Admin tabs:** Navigation via `kc_admin_tabs()` +- **Naming:** Functions and tables use `kc_` prefix +- **Force assignments:** Manual assignments take precedence +- **Test data:** Only user ID 1 can generate via admin (`admin-data.php`) +- **CSV export:** Possible via admin assignments +- **Teamer password:** Managed via admin, hash in WP options + +## Examples & Entry Points +- **Admin menu:** `konficastle-workshopwahl.php`, `includes/admin-wahlen.php` +- **Assignment logic:** `includes/zuteilungslogik.php` +- **Frontend form:** `includes/frontend-form.php` + +## Notes for AI Agents +- Always use `$wpdb->prefix` for DB tables +- Backend logic is modular, each entity has its own file +- No complex JS logic in frontend, validation is server-side +- For changes to assignment logic: use test scenarios via test data admin page + +--- + +See README.md for further details. \ No newline at end of file diff --git a/README.md b/README.md index 78379fd..157bba0 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,50 @@ # Workshop-Wahlen +## Überblick + +Dieses WordPress-Plugin ermöglicht die Verwaltung und Durchführung von Workshop-Wahlen für Konfi-Castle-Events. Es bietet ein vollständiges Backend für Admins (Wahlen, Workshops, Teilnehmer, Teamer, Zuteilungen) und ein Frontend-Formular für Teilnehmer. + +## Architektur & Hauptkomponenten + +- **Haupt-Plugin-Datei:** `konficastle-workshopwahl.php` – Registriert Hooks, lädt Assets, initialisiert Admin-Menüs. +- **Backend-Module (im `includes/`-Verzeichnis):** + - `admin-wahlen.php`, `admin-workshops.php`, `admin-teilnehmer.php`, `admin-teamer.php`, `admin-zuteilungen.php`, `admin-data.php`, `force-zuteilung.php`: Jeweils eigene Admin-Seiten für die Verwaltung der zugehörigen Entitäten. + - `zuteilungslogik.php`: Kernlogik für die automatische Zuteilung von Teilnehmern zu Workshops (inkl. Force-Zuteilungen und Kapazitätsprüfung). +- **Frontend:** + - `frontend-form.php`: Shortcode `[konficastle_workshopwahl wahl=ID]` für das Teilnehmer-Formular. + - `frontend-ergebnis.php`: Shortcode `[konficastle_workshop_ergebnis wahl=ID]` für Ergebnisanzeige. +- **Styles & Assets:** + - `assets/`: Enthält CSS für Admin und Frontend. + +## Datenbank & Installation + +- Tabellen werden über `install.php` beim Aktivieren angelegt (z.B. `kc_wahlen`, `kc_workshops`, `kc_teilnehmer`, `kc_zuteilung`, ...). +- Tabellenpräfix wird dynamisch über `$wpdb->prefix` verwendet. + +## Entwickler-Workflows + +- **Testdaten:** Über die Admin-Seite "Datenverwaltung" (`admin-data.php`) können Testdaten generiert werden (nur User ID 1). +- **CSV-Export:** Zuteilungen können über die Admin-Seite exportiert werden (`admin-zuteilungen.php`). +- **Zuteilungslogik:** Anpassungen an der Kernlogik erfolgen in `zuteilungslogik.php`. +- **Shortcodes:** + - `[konficastle_workshopwahl wahl=ID]` – Teilnehmer-Frontend + - `[konficastle_workshop_ergebnis wahl=ID]` – Ergebnisanzeige + +## Besondere Konventionen & Hinweise + +- **Namensschema:** Alle Plugin-Funktionen und Tabellen sind mit `kc_` (Konfi-Castle) prefixiert. +- **Admin-Tabs:** Navigation zwischen Admin-Seiten über `kc_admin_tabs()`. +- **Force-Zuteilungen:** Manuelle Zuweisungen haben Vorrang vor automatischer Logik. +- **Teamer-Passwort:** Verwaltung über eigene Admin-Seite, Passwort-Hash in WP-Optionen. +- **Frontend-Validierung:** Erfolgt serverseitig, keine komplexe JS-Logik im Frontend. + +## Einstiegspunkte & Beispiele + +- **Admin-Menüstruktur:** Siehe `konficastle-workshopwahl.php` und `includes/admin-wahlen.php`. +- **Zuteilungslogik:** Siehe `includes/zuteilungslogik.php` (Funktionen wie `kc_run_zuteilung`). +- **Frontend-Formular:** Siehe `includes/frontend-form.php` (Shortcode-Handler). + +--- + +Für Detailfragen zu Datenbankstruktur, Shortcodes oder Zuteilungslogik siehe die jeweiligen Dateien im `includes/`-Verzeichnis. + From 0375602e69018bff87bcd898841036bafbb17a5c Mon Sep 17 00:00:00 2001 From: Linus Maximilian Nilson Date: Fri, 30 Jan 2026 16:28:39 +0000 Subject: [PATCH 03/13] Delete .github/copilot-instructions.production.md --- .github/copilot-instructions.production.md | 37 ---------------------- 1 file changed, 37 deletions(-) delete mode 100644 .github/copilot-instructions.production.md diff --git a/.github/copilot-instructions.production.md b/.github/copilot-instructions.production.md deleted file mode 100644 index fff5999..0000000 --- a/.github/copilot-instructions.production.md +++ /dev/null @@ -1,37 +0,0 @@ -# Copilot Instructions for Workshop-Wahlen (Production) - -## Project Overview - -This WordPress plugin manages workshop elections for Konfi-Castle events. It provides an admin backend (elections, workshops, participants, teamers, assignments) and a participant frontend. - -## Architecture & Components -- **Main file:** `konficastle-workshopwahl.php` – Initializes hooks, loads assets, admin menus. -- **Backend:** - - `includes/` with modules for elections, workshops, participants, teamers, assignments, data management, force assignment - - Core assignment logic: `includes/zuteilungslogik.php` -- **Frontend:** - - Shortcodes: `[konficastle_workshopwahl wahl=ID]`, `[konficastle_workshop_ergebnis wahl=ID]` -- **Database:** Tables are created via `install.php`, prefix: `kc_` - -## Key Patterns & Workflows -- **Admin tabs:** Navigation via `kc_admin_tabs()` -- **Naming:** Functions and tables use `kc_` prefix -- **Force assignments:** Manual assignments take precedence -- **Test data:** Only user ID 1 can generate via admin (`admin-data.php`) -- **CSV export:** Possible via admin assignments -- **Teamer password:** Managed via admin, hash in WP options - -## Examples & Entry Points -- **Admin menu:** `konficastle-workshopwahl.php`, `includes/admin-wahlen.php` -- **Assignment logic:** `includes/zuteilungslogik.php` -- **Frontend form:** `includes/frontend-form.php` - -## Notes for AI Agents -- Always use `$wpdb->prefix` for DB tables -- Backend logic is modular, each entity has its own file -- No complex JS logic in frontend, validation is server-side -- For changes to assignment logic: use test scenarios via test data admin page - ---- - -See README.md for further details. \ No newline at end of file From b77b1fe0fb44cab4337111cf117c327123adfe10 Mon Sep 17 00:00:00 2001 From: Blitz08 Date: Sat, 31 Jan 2026 10:53:03 +0100 Subject: [PATCH 04/13] frontend: hide results when wahl is freigegeben in shortcode --- includes/frontend-ergebnis.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/includes/frontend-ergebnis.php b/includes/frontend-ergebnis.php index b169c1a..92f8e24 100644 --- a/includes/frontend-ergebnis.php +++ b/includes/frontend-ergebnis.php @@ -6,7 +6,11 @@ add_shortcode('konficastle_workshop_ergebnis', function($atts) { 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 + // Zeige Ergebnisse nur, wenn die Wahl NICHT freigegeben ist. + // Ist die Wahl freigegeben, soll das Ergebnis-Shortcode nichts ausgeben (Formular wird stattdessen angezeigt). + if (!empty($wahl->freigegeben)) { + return ''; + } // Workshops für diese Wahl holen $workshops = $wpdb->get_results( From c33eb3eaac0e26e3786ec4896e349ad8fda3ce6d Mon Sep 17 00:00:00 2001 From: Blitz08 Date: Sat, 31 Jan 2026 11:02:25 +0100 Subject: [PATCH 05/13] Rechtschribfelher Korigiert --- includes/admin-wahlen.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin-wahlen.php b/includes/admin-wahlen.php index e10dc5f..38762b6 100644 --- a/includes/admin-wahlen.php +++ b/includes/admin-wahlen.php @@ -352,7 +352,7 @@ function kc_wahlen_page() { echo ''; echo "
"; echo ""; - echo ""; + echo ""; echo "
"; echo ''.($wahl->freigegeben ? "freigegeben" : "geschlossen").''; echo ''; From a4719e9c587b3271f61c0b73fa691f00664239ce Mon Sep 17 00:00:00 2001 From: Blitz08 Date: Sat, 31 Jan 2026 11:15:34 +0100 Subject: [PATCH 06/13] =?UTF-8?q?loeschen=20zu=20l=C3=B6schen=20ge=C3=A4nd?= =?UTF-8?q?ert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/admin-teamer.php | 2 +- includes/admin-teilnehmer.php | 2 +- includes/admin-wahlen.php | 2 +- includes/admin-workshops.php | 2 +- includes/force-zuteilung.php | 36 +++++++++++++++++------------------ 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/includes/admin-teamer.php b/includes/admin-teamer.php index e40934b..2b4631e 100644 --- a/includes/admin-teamer.php +++ b/includes/admin-teamer.php @@ -131,7 +131,7 @@ function kc_teamer_page() { ".esc_html($tm->nachname)." Bearbeiten - Loeschen + Löschen "; } diff --git a/includes/admin-teilnehmer.php b/includes/admin-teilnehmer.php index b4caf65..f30ae23 100644 --- a/includes/admin-teilnehmer.php +++ b/includes/admin-teilnehmer.php @@ -299,7 +299,7 @@ function kc_teilnehmer_page() { ".$w3_disp." Bearbeiten - Loeschen + Löschen "; } diff --git a/includes/admin-wahlen.php b/includes/admin-wahlen.php index 38762b6..0fda077 100644 --- a/includes/admin-wahlen.php +++ b/includes/admin-wahlen.php @@ -363,7 +363,7 @@ function kc_wahlen_page() { echo 'Zuteilung anzeigen'; $nonce = wp_create_nonce('kc_run_zuteilung_' . intval($wahl->id)); echo 'Zuteilung starten'; - echo 'Loeschen'; + echo 'Löschen'; echo ''; echo ''; } diff --git a/includes/admin-workshops.php b/includes/admin-workshops.php index 80e7400..a03c672 100644 --- a/includes/admin-workshops.php +++ b/includes/admin-workshops.php @@ -542,7 +542,7 @@ function kc_workshops_page() { ". $wahl_str ." Bearbeiten - Loeschen + Löschen "; } diff --git a/includes/force-zuteilung.php b/includes/force-zuteilung.php index 019d290..a310bed 100644 --- a/includes/force-zuteilung.php +++ b/includes/force-zuteilung.php @@ -4,14 +4,14 @@ function kc_force_zuteilung_page() { $prefix = $wpdb->prefix; kc_admin_tabs('kc_force_zuteilung'); - // Force-Zuteilung löschen + // Force-Zuteilung l�schen if (isset($_GET['delete_force'])) { $fid = intval($_GET['delete_force']); $wpdb->delete("{$prefix}kc_force_zuteilung", ['id' => $fid]); - echo '
Force-Zuteilung gelöscht!
'; + echo '
Force-Zuteilung gel�scht!
'; } - // Force speichern (neu/ändern) + // Force speichern (neu/�ndern) if (isset($_POST['kc_force_save'])) { $data = [ 'teilnehmer_id' => intval($_POST['teilnehmer_id']), @@ -29,7 +29,7 @@ function kc_force_zuteilung_page() { } } - // Listen für Dropdowns + // Listen f�r Dropdowns $teilnehmer_liste = $wpdb->get_results("SELECT * FROM {$prefix}kc_teilnehmer ORDER BY nachname, vorname"); $workshop_liste = $wpdb->get_results("SELECT * FROM {$prefix}kc_workshops ORDER BY name"); $wahlen = $wpdb->get_results("SELECT id, name FROM {$prefix}kc_wahlen WHERE deleted=0 ORDER BY name"); @@ -45,7 +45,7 @@ function kc_force_zuteilung_page() {
- '; + '; foreach($wahlen as $w) { echo ''; @@ -70,7 +70,7 @@ function kc_force_zuteilung_page() {
- '; + '; foreach($teilnehmer_liste as $t) { echo '
'; From e34ce64906886ac3c92219fdb5eafa9810c32173 Mon Sep 17 00:00:00 2001 From: Blitz08 Date: Sat, 31 Jan 2026 11:37:11 +0100 Subject: [PATCH 09/13] force zuteilung form anpassung --- includes/force-zuteilung.php | 70 ++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/includes/force-zuteilung.php b/includes/force-zuteilung.php index 8e6dd75..37f6209 100644 --- a/includes/force-zuteilung.php +++ b/includes/force-zuteilung.php @@ -111,43 +111,45 @@ function kc_force_zuteilung_page() { foreach ($wahlen as $w) $wahl_phases[intval($w->id)] = intval($w->anzahl_einheiten); echo ''; - echo ''; + // Initialize existing phase selects based on their selected wahl + $("[name='phase']").each(function(){ + var $phase = $(this); + var $form = $phase.closest("form"); + var $wahl = $form.find("#kc-force-wahl-dropdown"); + var current = $phase.val(); + refreshPhaseSelect($wahl, $phase, current); + }); +}); + +JS; echo '
'; return; } From b312cae4734f39d686d4d3a6c6a153f1d5b2c6c0 Mon Sep 17 00:00:00 2001 From: Blitz08 Date: Sat, 31 Jan 2026 11:39:54 +0100 Subject: [PATCH 10/13] admin: make phase a select and let JS populate options per Wahl --- includes/force-zuteilung.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/includes/force-zuteilung.php b/includes/force-zuteilung.php index 37f6209..94f24d5 100644 --- a/includes/force-zuteilung.php +++ b/includes/force-zuteilung.php @@ -70,10 +70,12 @@ function kc_force_zuteilung_page() { echo ''; echo ''; - // Phase + // Phase (select so JS can populate based on Wahl) echo '
'; echo ''; - echo ''; + echo ''; echo '
'; // Workshop @@ -185,10 +187,12 @@ JS; echo ''; echo ''; - // Phase + // Phase (select so JS can populate based on Wahl) echo '
'; echo ''; - echo ''; + echo ''; echo '
'; // Workshop From eb7afe06ffea8066b9f63ad16efbcc525d12a6c2 Mon Sep 17 00:00:00 2001 From: Blitz08 Date: Sat, 31 Jan 2026 11:42:46 +0100 Subject: [PATCH 11/13] admin: read phase-count from Wahl option data-einheiten; fallback to mapping --- includes/force-zuteilung.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/includes/force-zuteilung.php b/includes/force-zuteilung.php index 94f24d5..72ff6b9 100644 --- a/includes/force-zuteilung.php +++ b/includes/force-zuteilung.php @@ -64,8 +64,7 @@ function kc_force_zuteilung_page() { echo ''; echo ''; @@ -121,8 +120,9 @@ jQuery(function($){ $("#kc-force-workshop-dropdown").select2({placeholder:"Workshop auswählen…",allowClear:true}); function refreshPhaseSelect($wahlSelect, $phaseSelect, current) { - var wid = parseInt($wahlSelect.val(),10); - var max = (wid && kcWahlPhases[wid]) ? parseInt(kcWahlPhases[wid],10) : 1; + // prefer data attribute on the selected option; fall back to kcWahlPhases mapping + var selOpt = $wahlSelect.find('option:selected'); + var max = parseInt(selOpt.data('einheiten') || kcWahlPhases[parseInt($wahlSelect.val(),10)] || 1, 10); $phaseSelect.empty(); for(var i=1;i<=max;i++){ var opt = $("