diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..62d2b7d --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,67 @@ +name: Deploy Workshop-Wahlen (DEV / PROD) + +on: + push: + branches: + - develop + - main + +jobs: + deploy: + runs-on: ubuntu-latest + + container: + image: docker.gitea.com/runner-images:ubuntu-latest + + steps: + # ===================== + # CHECKOUT + # ===================== + - name: Checkout Repository + uses: actions/checkout@v4 + + # ===================== + # DEBUG (kann später raus) + # ===================== + - name: Debug workspace + run: | + echo "PWD:" + pwd + echo "FILES:" + ls -la + + # ===================== + # DEV DEPLOY (FTP) + # ===================== + - name: Deploy to DEV via FTP + if: github.ref == 'refs/heads/develop' + run: | + apt-get update + apt-get install -y lftp + + lftp -u "${{ secrets.FTP_USER }},${{ secrets.FTP_PASS }}" ftp://${{ secrets.FTP_HOST }}:${{ secrets.FTP_PORT }} < maxWorkshops) { + valid = false; + errorMessages.push('Es dürfen maximal ' + maxWorkshops + ' Workshops gewählt werden.'); + } + } + + // Show error messages + var errorBox = form.querySelector('.kc-form-errors'); + if (!errorBox) { + errorBox = document.createElement('div'); + errorBox.className = 'kc-form-errors'; + form.prepend(errorBox); + } + errorBox.innerHTML = errorMessages.length ? '' : ''; + + if (!valid) { + e.preventDefault(); + } + }); +}); diff --git a/assets/frontend.css b/assets/frontend.css new file mode 100644 index 0000000..f569134 --- /dev/null +++ b/assets/frontend.css @@ -0,0 +1,175 @@ +.teamers { + color: #888; + font-size: 0.95em; + margin-left: 8px; + white-space: nowrap; +} +.kc-form-container { + box-sizing: border-box; + width: 100%; + max-width: 680px; + margin: 28px auto; + background: #f8fbe7; + border-left: 8px solid #b6d333; + border-radius: 14px; + box-shadow: 0 5px 22px #8eae291a; + padding: 28px 22px; + font-family: 'Segoe UI', Arial, sans-serif; +} + +.kc-form-container h2 { + color: #3b5323; + font-family: 'Montserrat', Arial, sans-serif; + font-size: 2em; + margin-top: 0; + margin-bottom: 0.5em; + letter-spacing: -1px; +} + +.kc-form-row { + margin-bottom: 22px; +} + +.kc-form-row label { + display: block; + font-weight: 700; + color: #1c3866; + margin-bottom: 7px; + font-size: 1.07em; +} + +.kc-form-row select { + box-sizing: border-box; + width: 100%; + padding: 10px; + border: 1.7px solid #d6e39f; + border-radius: 5px; + background: #fcffe9; + font-size: 1.09em; + margin-top: 3px; + transition: border .2s; +} + +.kc-form-row input[type="text"]:focus, + .kc-form-row select:focus { + outline: none; + border-color: #b6d333; + background: #fffde8; +} + +.kc-form-row input[type="submit"] { + background: #2f5393; + color: #fff; + padding: 13px 28px; + font-weight: bold; + font-size: 1.13em; + border: 0; + border-radius: 7px; + cursor: pointer; + margin-top: 6px; + box-shadow: 0 2px 8px #1c38661a; + transition: background .2s; +} +.kc-form-row input[type="submit"]:hover { + background: #1c3866; +} + +.kc-required { + color: #e42626; + font-weight: bold; +} +.kc-success-msg { + color: #288830; + background: #f2fbe2; + border-left: 4px solid #b6d333; + padding: 15px 15px 15px 22px; + margin-bottom: 25px; + font-size: 1.1em; + border-radius: 7px; +} +.kc-error-msg { + color: #a80000; + background: #ffeaea; + border-left: 4px solid #e12b2b; + padding: 15px 15px 15px 22px; + margin-bottom: 25px; + font-size: 1.1em; + border-radius: 7px; +} +@media (max-width: 900px) { + .kc-form-container {padding:20px 14px;} +} + +@media (max-width: 520px) { + .kc-form-container {padding:14px 10px;border-radius:10px;margin:14px 10px;} + .kc-form-container h2 {font-size:1.4em} + .kc-form-row {margin-bottom:14px} +} + +.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;} +.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(240px, 1fr)); + gap: 16px; + margin-top: 12px; + align-items: start; +} + +/* Responsive tuning: adapt card count per row */ +@media (max-width: 1024px) { + .kc-workshops-grid { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; } +} +@media (max-width: 768px) { + .kc-workshops-grid { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; } +} +@media (max-width: 560px) { + .kc-workshops-grid { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; } +} +@media (max-width: 420px) { + .kc-workshops-grid { grid-template-columns: 1fr; gap: 8px; } +} +.kc-workshop-card { + box-sizing: border-box; + min-width: 0; + background:#ffffff; + border-radius:12px; + overflow:hidden; + border:1px solid #e9f4f0; + box-shadow:0 2px 6px rgba(8,38,28,0.04); + width:100%; +} + +.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;} +.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; + white-space: normal; + display: block; + max-width: 100%; + overflow: visible; + text-overflow: unset; + margin: 0; +} +.kc-participant.me { + background: #fffbe6; + border: 1px solid #ffeab2; + color: inherit; + font-weight: bold; +} +.kc-notassigned{background:#fff6f6;border:1px solid #ffd2d2;padding:12px;border-radius:10px;margin-top:12px;} +@media(max-width:700px){ .kc-participants{grid-template-columns:1fr;} } diff --git a/assets/kc-admin.css b/assets/kc-admin.css new file mode 100644 index 0000000..ed22b63 --- /dev/null +++ b/assets/kc-admin.css @@ -0,0 +1,205 @@ +.kc-admin-tabs { + margin-bottom: 28px; + border-bottom: 2px solid #e0e6ef; + background: #f8fbe7; + border-radius: 18px 18px 0 0; + box-shadow: 0 1px 10px #b6d33321; + padding: 8px 18px 0 18px; +} +.kc-tabnav { + display: inline-block; + padding: 12px 32px 11px 32px; + border-radius: 12px 12px 0 0; + font-weight: 700; + font-size: 1.12em; + margin-right: 7px; + box-shadow: 0 2px 11px #b6d33318; + text-decoration: none; + background: #f8fbe7; + color: #4176be; + border: none; + outline: none; + transition: all .18s; + letter-spacing: 0.5px; +} +.kc-tabnav-active, +.kc-tabnav:focus, +.kc-tabnav:hover { + background: linear-gradient(90deg, #326dd2 0%, #b6d333 100%); + color: #fff !important; + box-shadow: 0 6px 24px #326dd241; + font-weight: 800; + letter-spacing: 1px; +} +.kc-admin-table-wrap { + box-sizing: border-box; + background: #fff; + border-radius: 17px; + box-shadow: 0 4px 28px #326dd21c, 0 1.5px 7px #b6d33324; + padding: 28px 22px 30px 22px; + margin: 28px 0; + /* allow children to overflow (tables may scroll), don't clip action buttons */ + overflow: visible; +} + +/* Collapsible details styling for admin Zuteilungen */ +details.kc-wahl-details, details.kc-phase-details { + background: #fff; + border: 1px solid #e9eef6; + border-radius: 10px; + padding: 8px; + margin-bottom: 12px; +} +details.kc-wahl-details > summary, details.kc-phase-details > summary { + list-style: none; + cursor: pointer; + padding: 8px 10px; +} +details.kc-wahl-details[open] > summary, details.kc-phase-details[open] > summary { + background: linear-gradient(90deg,#f2f9ff 0%, #f6fff5 100%); + border-radius: 8px; +} +/* Wahl summary layout */ +details.kc-wahl-details > summary { display: flex; align-items: center; justify-content: space-between; } +details.kc-wahl-details > summary .kc-wahl-title { font-weight:700; color:#2b5f9a; } +details.kc-wahl-details > summary .kc-wahl-actions { margin-left: 12px; } +details.kc-wahl-details .kc-wahl-actions .kc-btn { margin-left:8px; } + +/* Workshop card inside phase */ +.kc-workshop-card { + background: #f9f9f9; + padding: 10px; + margin: 8px 0; + border-radius: 8px; + box-shadow: 0 1px 6px #00000012; +} +.kc-workshop-card table { margin-top:8px; } +.kc-workshop-card b { font-size: 1.05em; } +.kc-workshop-card .kc-count { color:#555; font-size:0.92em; } + +.kc-unassigned { + background: #fff6f6; + border-left: 4px solid #f2b0b0; + padding: 10px; + margin-top: 8px; + border-radius: 6px; +} + +/* Smaller tweaks for details summaries inside admin area */ +details summary { outline: none; } +details summary::-webkit-details-marker { display: none; } +details summary:before { content: '\25B6'; display:inline-block; transform:rotate(90deg); margin-right:8px; } +details[open] summary:before { transform: rotate(0deg); } +.kc-admin-table { + width: 100%; + border-collapse: separate; + border-spacing: 0; + margin-bottom: 28px; + background: #fafdff; + border-radius: 13px; + overflow: auto; /* horizontal scroll on small screens */ + box-shadow: 0 2px 12px #b6d33313; +} +.kc-admin-table th, .kc-admin-table td { + padding: 13px 18px; + text-align: left; + font-size: 1.07em; + vertical-align: middle; +} +.kc-admin-table thead { + background: #eaf6ff; + color: #4176be; + font-weight: 800; +} +.kc-admin-table tbody tr { + border-bottom: 1px solid #eef3fa; +} +.kc-admin-table tbody tr:nth-child(even) { + background: #f8fbe7; +} +.kc-admin-table tbody tr:hover { + background: #e0ebf6; + transition: background 0.2s; +} +.kc-admin-table th { + font-weight: bold; + border-bottom: 2px solid #b6d33342; +} +.kc-admin-table .kc-actions { + white-space: nowrap; + display: flex; + gap: 8px; + align-items: center; + justify-content: flex-end; + flex-wrap: wrap; /* allow buttons to wrap on very small widths */ +} +.kc-btn { + background: linear-gradient(90deg,#4176be 40%, #b6d333 100%); + color: #fff; + padding: 10px 25px; + border-radius: 8px; + border: 0; + margin: 0 5px; + font-weight: 700; + cursor: pointer; + display: inline-block; + text-decoration: none; + font-size: 1.04em; + box-shadow: 0 1.5px 6px #b6d33321; + transition: background .17s, box-shadow .19s; +} +.kc-btn.del { + background: #e12b2b !important; + color: #fff; +} +.kc-btn.edit { + background: #ff9800 !important; + color: #fff; +} +.kc-btn:hover { + opacity: 0.91; + background: linear-gradient(90deg,#26529e 40%, #97b321 100%); + color: #fff; + box-shadow: 0 3px 10px #4176be29; +} +.notice-success { + background: #f6ffed; + border-left: 6px solid #b6d333; + color: #1c5322; + padding: 13px 20px; + margin: 0 0 22px 0; + border-radius: 9px; + font-size: 1.08em; + font-weight: 500; +} +.notice-error { + background: #fff3f3; + border-left: 6px solid #e12b2b; + color: #9d1d2e; + padding: 13px 20px; + margin: 0 0 22px 0; + border-radius: 9px; + font-size: 1.08em; + font-weight: 500; +} +.kc-required { + color: #e42626; + font-weight: bold; + margin-left: 2px; +} +.kc-wahl-filter-btn.active{background:#4CAF50;color:#fff;} +.kc-phase-filter-btn.active{background:#1976d2;color:#fff;} +@media (max-width: 800px) { + .kc-admin-table-wrap {padding: 12px;} + .kc-admin-table th, .kc-admin-table td {padding: 8px 6px;} + .kc-btn {padding: 8px 13px;} +} + +@media (max-width: 600px) { + /* Make tables readable on mobile by switching to block rows */ + .kc-admin-table thead { display: none; } + .kc-admin-table, .kc-admin-table tbody, .kc-admin-table tr, .kc-admin-table td { display: block; width: 100%; } + .kc-admin-table tr { margin-bottom: 12px; border-bottom: 1px solid #eef3fa; } + .kc-admin-table td { text-align: left; padding: 10px 12px; white-space: normal; } + .kc-admin-table td:before { content: attr(data-label); font-weight:700; display:block; margin-bottom:6px; color:#4176be; } +} diff --git a/includes/frontend-ergebnis.php b/includes/frontend-ergebnis.php index 34b32e3..b169c1a 100644 --- a/includes/frontend-ergebnis.php +++ b/includes/frontend-ergebnis.php @@ -6,7 +6,7 @@ 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 ''; - if($wahl->freigegeben) return '
'; + // Keine Warnmeldung im Frontend anzeigen, Ergebnisse weiterhin darstellen // Workshops für diese Wahl holen $workshops = $wpdb->get_results( @@ -142,8 +142,8 @@ add_shortcode('konficastle_workshop_ergebnis', function($atts) { echo '
'; echo 'Deine Zuteilung
'; $personal_shown = true; @@ -209,8 +209,7 @@ add_shortcode('konficastle_workshop_ergebnis', function($atts) { foreach($teilnehmer as $t) { $is_me = in_array(intval($t->id), $my_ids); $name = esc_html($t->vorname.' '.$t->nachname); - $label = $name . ' ('.intval($t->phase).')'; - echo '
'. $label .'
'; + echo '
'. $name .'
'; } echo ''; // kc-participants echo ''; // content @@ -227,7 +226,7 @@ add_shortcode('konficastle_workshop_ergebnis', function($atts) { echo 'Nicht zugeteilt:
'; echo ''; } diff --git a/includes/frontend-form.php b/includes/frontend-form.php index a83effd..d0be839 100644 --- a/includes/frontend-form.php +++ b/includes/frontend-form.php @@ -16,7 +16,8 @@ add_shortcode('konficastle_workshopwahl', function($atts) { $wahl = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}kc_wahlen WHERE id=%d", $wahl_id)); if(!$wahl || !$wahl->freigegeben) { - return $debug_output . '
Die Workshopwahl ist aktuell nicht freigeschaltet.
'; + // Keine Fehlermeldung im Frontend anzeigen; Formular ausblenden + return ''; } // Ermittle erlaubte Workshops pro Phase für diese Wahl.