Rollen (Admin/Mitglied), Seite Kooperationen, Textanpassungen

- Gemeinsame Zugänge mit Rollen: Admin darf alles, Mitglied nutzt Kalender,
  Fahrtplaner, Treffpunkte und bearbeitet Mitglieder (kein Hinzufügen,
  Löschen, Import, keine Patches, keine Statistik-Korrektur)
- Server prüft die Rechte (403), Konten ohne Rolle gelten als Admin
- npm run user: add <name> [admin|mitglied], role <name> <rolle>
- Neue öffentliche Seite Kooperationen mit Titelbild, Anführer,
  Social-Media-Links und Beschreibung, Pflege durch Admin
- Kopfzeile bleibt bei mittlerer Breite einzeilig
- Texte auf Wunsch gekürzt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
guyg1474andClaude Opus 5.5 committed 2026-10-12 19:47:03 +02:00
1 parent f46016487d
commit 819219fb2d
18 files changed
+661 -106

No files matched your search

+21 -5
View File
@@ -1,7 +1,10 @@
import { $, api, esc, sortByName, seatsLabel, showError, renderHeader } from './common.js';
import { $, api, esc, sortByName, seatsLabel, showError, renderHeader, isAdmin } from './common.js';
renderHeader('gruppe');
// Admin: Mitglieder hinzufügen, löschen, importieren. Mitglied-Zugang: nur bearbeiten.
// Der Server prüft das ebenfalls – hier wird nur ausgeblendet, was ohnehin abgelehnt würde.
let admin = false;
let members = [];
let points = [];
const form = $('#member-form');
@@ -31,6 +34,8 @@ function resetForm() {
$('#member-seats-wrap').hidden = true;
$('#member-cancel').hidden = true;
$('#member-form-title').textContent = 'Mitglied hinzufügen';
// Ohne Admin-Rechte gibt es das Formular nur zum Bearbeiten
$('#member-form-card').hidden = !admin;
}
$('#member-cancel').addEventListener('click', resetForm);
@@ -70,8 +75,9 @@ function edit(id) {
$('#member-seats-wrap').hidden = !m.hasCar;
$('#member-cancel').hidden = false;
$('#member-form-title').textContent = 'Mitglied bearbeiten';
$('#member-name').focus();
window.scrollTo({ top: 0, behavior: 'smooth' });
$('#member-form-card').hidden = false;
$('#member-form-card').scrollIntoView({ behavior: 'smooth', block: 'start' });
$('#member-name').focus({ preventScroll: true });
}
async function remove(id) {
@@ -98,7 +104,7 @@ function render() {
<span class="badge">${m.hasCar ? `Auto · ${seatsLabel(m.seats)}${m.alwaysDrives ? ' · fährt immer' : ''}` : 'kein Auto'}</span>
<span class="actions">
<button class="link" data-edit="${m.id}">Bearbeiten</button>
<button class="link danger" data-del="${m.id}">Löschen</button>
${admin ? `<button class="link danger" data-del="${m.id}">Löschen</button>` : ''}
</span>
</li>`).join('');
}
@@ -213,4 +219,14 @@ async function load() {
render();
}
load().then(loadPoints).catch(showError);
async function init() {
admin = await isAdmin();
$('#members-role-hint').hidden = admin;
$('#import-btn').hidden = !admin;
if (!admin) $('#backup-text').textContent = 'Gruppe als JSON-Datei sichern.';
resetForm();
await load();
await loadPoints();
}
init().catch(showError);