stammtisch-hersbruck/TODO.md
Daniel Michelberger 4fa0de8753 feat: Logo pro Team, auch als Wasserzeichen im Seitenhintergrund
teams.logo nimmt eine Datei auf; hochgeladen wird sie in den
Team-Einstellungen. Ohne eigenes Logo bleibt das Wappen aus static/ als
Rueckfalloption - fuer den Stammtisch Hersbruck aendert sich damit nichts,
fuer jedes weitere Team waere es fremdes Vereinswappen gewesen.

Dasselbe Logo liegt gedreht und sehr blass in der rechten unteren Ecke der
Seite. Es haengt fest im Bildschirm, faengt keine Klicks ab und ist fuer
Screenreader nicht vorhanden; im Dunkelmodus etwas kraeftiger, sonst
verschwaende es im dunklen Grund.

In TODO.md ausserdem der Plan fuer Ausfahrten: Sie werden kein zweites
Konzept neben Events, sondern Schalter daran - timing, participation
(offen/bestaetigung/geschlossen) und Serien, die echte Einzeltermine
erzeugen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014dh9W1i7aLSdPYJzQPid5o
2026-09-02 15:42:04 +02:00

141 lines
6.2 KiB
Markdown

# Offene Punkte
Stand: 2026-09-02. Was hier steht, ist bewusst nicht erledigt — entweder weil
es eine Entscheidung braucht oder weil es außerhalb des Repos passiert.
## Entscheidungen
### Trail-Status: dürfen Mitglieder melden?
Anzeige und Herkunft (`status_changed`, `status_by`) sind fertig. Ändern darf
den Status weiterhin nur, wer Pate oder Team-Admin ist — `trails.updateRule`
lässt nichts anderes zu.
Sollen alle Teammitglieder melden dürfen, braucht es eine Regel, die genau ein
Feld freigibt: `team.users.id ?= @request.auth.id` kombiniert mit
`@request.body.<feld>:isset = false` für **jedes** andere Feld. Das
funktioniert, wird aber lang und bricht still, sobald ein Feld dazukommt.
Deshalb erst nach ausdrücklicher Entscheidung.
### Fahrer: Kader oder Event-Teilnehmer?
`riders.event` bindet einen Fahrer an genau ein Event. Ein in den Einstellungen
angelegter Fahrer ohne Event steht deshalb nur im Verzeichnis und taucht in
keiner Zeitnahme auf; der Dialog hat dafür ein optionales Event-Feld.
Ein echter Team-Kader, aus dem man Fahrer in Events übernimmt, wäre eine
n:m-Beziehung — also eine Schema-Änderung, keine Oberflächenfrage.
### Mitglied per E-Mail einladen
Die alte Einladung über eine E-Mail-Suche ist entfallen und durch „Mitglied
anlegen" ersetzt. Sie konnte nie funktionieren: `users.listRule` gibt nur den
eigenen Datensatz frei, die Suche lief immer ins Leere.
Ein **bestehendes** fremdes Konto in ein Team zu holen braucht eine offenere
`listRule` (z. B. `@request.auth.id != ""`). Das erlaubt allerdings, alle
Konten der Instanz aufzulisten — deshalb bewusst nicht ohne Rücksprache.
### Ausfahrten: geplant, noch nicht gebaut
Ausfahrten werden **nicht** zu einem zweiten Konzept neben Events, sondern
Events bekommen Schalter. Ein Bikepark-Ausflug mit gestoppten Läufen ist beides
zugleich; eine Trennung wäre willkürlich und würde Datum, Rechte und Oberfläche
doppelt führen.
Geplant, in dieser Reihenfolge:
1. **`events.timing`** (bool). Runs und Zeitnahme erscheinen nur, wenn gesetzt.
Der wöchentliche Stammtisch braucht sie nicht.
2. **Teilnahme** als eigene Collection `event_participants` (Event, Person,
Status, Zeitpunkt) — nicht als Liste am Event, sonst hängen Status und
Zeitpunkt nirgends, und Gäste ohne Konto passen nicht hinein.
`events.participation` steuert, wie man hineinkommt:
| Wert | Bedeutung |
|---|---|
| `offen` | Jedes Teammitglied trägt sich selbst ein |
| `bestaetigung` | Anmeldung möglich, Ersteller oder Team-Admin bestätigt |
| `geschlossen` | Nur Ersteller oder Team-Admin trägt Teilnehmer ein |
3. **Serien** (`event_series`): Regel, Zeitraum und Vorlage; daraus entstehen
echte Einzeltermine. Bewusst nicht ein Datensatz mit Wiederholungsregel, aus
dem Termine nur gerechnet werden — sobald „wer kommt am 12.?" oder „diese
Woche fällt aus" beantwortet werden soll, braucht jeder Termin einen eigenen
Datensatz.
Offen: Sind Teilnehmer **Nutzerkonten** oder **Fahrer**? Für den Stammtisch
wären es Konten, für eine gemeinsame Ausfahrt eher Fahrer (die es auch ohne
Konto gibt). Beides zugleich geht, macht die Collection aber breiter.
## Vor dem nächsten Deploy
### `PUBLIC_CARTO_API_KEY` in Coolify setzen
Die Kartenkacheln kommen von CARTO. Der Schlüssel muss den Browser erreichen,
deshalb das `PUBLIC_`-Präfix — ohne das reicht SvelteKit ihn nicht weiter.
Gelesen wird er über `$env/dynamic/public`, das heißt: Die Variable muss in der
**Laufzeitumgebung** des `node build`-Prozesses stehen, nicht nur zur Buildzeit.
In Coolify als normale Umgebungsvariable eintragen genügt. Fehlt sie, laufen die
Kacheln ohne Schlüssel weiter — die Karte bleibt also sichtbar.
### Migrationen greifen beim nächsten Start
Sechs neue Migrationen liegen in `backend/pb_migrations/`:
- `1754500500_riders_user_and_admin_rules.js`
- `1754500600_events_dates_instead_of_status.js`
- `1754500700_trail_status_meta.js`
- `1754500800_trail_markers_custom.js`
- `1754500900_users_superadmin.js`
- `1754501000_teams_logo.js`
Solange sie nicht gelaufen sind, scheitert alles, was auf den neuen Regeln
aufbaut. Am deutlichsten beim Anlegen eines Mitglieds oder eines Fahrer-Logins:
**„Only superusers can perform this action"** — genau das sagt die noch
unveraenderte `users.createRule` (null = nur Superuser).
**Achtung:** Die mittlere entfernt `events.status` **samt seiner Werte**. Das
ist so gewollt (Events werden datiert statt bewertet), aber es ist ein
Datenverlust und nicht zurückzunehmen.
Ebenfalls neu: Fahrer anlegen, ändern und löschen darf ab dann nur noch die
Teamleitung. Mitglieder ohne Admin-Rolle verlieren diese Möglichkeit auch auf
der Event-Seite.
### Typen einmal neu erzeugen
`frontend/src/lib/types.d.ts` wurde bei den letzten Schema-Änderungen von Hand
ergänzt (`riders.user`, `trails.status_by`/`status_changed`,
`events.starts`/`ends` statt `status`). Grund: `pocketbase-typegen` braucht
native sqlite3-Bindings, die in der Arbeitsumgebung nicht gebaut werden durften.
```bash
cd frontend && npm run generate-pocketbase-types
```
Die Datei sollte danach unverändert bleiben. Tut sie es nicht, gilt das Ergebnis
des Generators.
### Logo des Stammtischs zuordnen
`teams.logo` gibt es ab `1754501000`. Solange nichts hinterlegt ist, zeigt die
App weiterhin das Wappen aus `static/` — für den Stammtisch Hersbruck sieht es
also unverändert aus. Wer es als Datei am Team haben will, lädt es nach dem
Deploy unter Einstellungen → Team → Logo hoch.
## Kleinigkeiten
- Der Melder eines Trail-Markers („wer") zeigt bis zum Deploy „Unbekannt". Die
gelockerte `users.viewRule` kommt mit `1754500500`.
- Die Rolle **Superadmin** existiert seit `1754500900` und ist für
stammtisch@dne.name gesetzt, gibt in der App aber noch keine besonderen
Rechte. Sie ist bewusst nur in PocketBase vergebbar: Die `updateRule` der
users-Collection schließt `superadmin` vom Selbstsetzen aus. Sobald klar ist,
was sie dürfen soll, kommen die Regeln dazu.
- Flag-Typen bleiben **teamspezifisch**. Ein neues Team bekommt beim Anlegen
den hartkodierten Standardsatz aus `trailFlags.svelte.ts`, den es danach frei
ändern kann. Eine appweite Verwaltung gibt es damit bewusst nicht.
- `NAMING.md` und `frontend/static/pedaler.svg` liegen bewusst nur lokal.