Files
teamwallet/docs/superpowers/specs/2026-08-03-team-erstellen-design.md
Bastian Wagner 560fcfc11a docs: add design spec for team creation via UI
Brainstormed with the user: any logged-in user should be able to
self-service create a team and becomes its captain, via a dialog on
team-select. Team deletion/archiving is scoped out as a separate
follow-up feature.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 15:03:59 +02:00

5.9 KiB

Team erstellen über die UI

Status: approved Datum: 2026-08-03

Kontext

Teams können in TeamWallet heute nur über einen bestehenden Backend-Endpoint (POST /api/v1/teams, teams.controller.ts) angelegt werden, der ausschließlich globalen Admins vorbehalten ist (@Roles([RoleEnum.admin])). Im modernen Angular-Frontend (myteamwallet_frontend_modern) existiert dafür keine UI: core/team/teams-api.ts hat keine createTeam-Methode, und features/team-select/team-select.html zeigt einem User ohne Teams nur den Hinweistext „Du bist noch keinem Team zugeordnet." ohne jede Handlungsoption.

Ziel: jeder eingeloggte User soll selbstständig ein neues Team gründen können und wird dabei automatisch dessen Kapitän. Das schließt eine der offensichtlichsten Lücken im Produkt (Selbstregistrierung eines Teams) und folgt demselben Muster, das an anderer Stelle im Code bereits als fehlend dokumentiert ist (docs/plans/admin-user-management.md merkt an, dass Admins auch noch keine User anlegen können — ein verwandtes, aber bewusst getrenntes Folge-Thema).

Entscheidungen aus dem Brainstorming

  • Berechtigung: jeder eingeloggte User (RoleEnum.user) darf ein Team erstellen, nicht nur Admins. Der Guard auf POST /teams wird entsprechend gelockert.
  • Automatische Mitgliedschaft: der Ersteller wird automatisch Kapitän (captain, Rollen-ID 3) des neuen Teams — die niedrigste Rollen-ID, die TeamAccessService.assertManager bereits als „Manager" behandelt (id >= 3). Es gibt kein explizites „Owner"-Konzept, captain ist die naheliegende Top-Rolle für den Ersteller.
  • Formularumfang: nur der Teamname wird abgefragt (CreateTeamDTO bleibt { name: string }). Alias wird weiterhin automatisch aus dem Timestamp generiert, alles Weitere ist später über die Team-Einstellungen anpassbar.
  • UI-Einstiegspunkt: Button „Team erstellen" ist in team-select dauerhaft sichtbar — auch wenn der User bereits Teams hat (nicht nur im Leerzustand), um auch das Anlegen weiterer Teams (z. B. zweite Mannschaft) zu ermöglichen.
  • UI-Pattern: Dialog/Modal statt eigener Route, passend zum bestehenden MatDialog-Muster im Repo (z. B. features/team/more/penalties/penalties.ts) und angemessen für ein einzelnes Eingabefeld.
  • Out of Scope: Team löschen/archivieren ist ein eigenständiges Folge-Feature (andere Berechtigungen/Risiken, z. B. Umgang mit bestehenden Spielern/Transaktionen) und wird separat geplant.

Architektur / Komponenten

1. Backend: teams.controller.ts

Guard auf POST /teams von @Roles([RoleEnum.admin]) auf [RoleEnum.user, RoleEnum.admin] erweitern — Muster wie an anderen Stellen desselben Controllers (z. B. Zeilen 113-114, 122-123). Der aufrufende User wird wie überall im Controller über @Req() reqreq.user.id an den Service durchgereicht.

2. Backend: teams.service.ts#createNewTeam

Aktuell (Zeile 166-178) wird nur Team + Default-TeamSettings (generateBasicTeamSettings) angelegt; es entsteht kein Player-Datensatz, der User bleibt kein Mitglied des neuen Teams.

Erweiterung: nach dem Speichern von Team und Settings zusätzlich einen Player erzeugen — verknüpft mit dem aufrufenden User (userId) und teamRole = captain (per rolesRepository.findOneBy({ id: 3 })). Vorgehen spiegelt die bestehende Join-Erzeugung in createNewPlayer() (Zeilen 122-164), dort wird bereits Player inkl. TeamRole-Verknüpfung für andere Spieler angelegt.

Audit-Logging (this.logger.info({ event: 'team_create', ... })) bleibt erhalten.

3. Backend: dto/create-team.dto.ts

Unverändert ({ name: string }).

4. Frontend: core/team/teams-api.ts

Neue Methode createTeam(name: string)POST /teams, analog zu den bestehenden Methoden wie createPlayer.

5. Frontend: neue Dialog-Komponente

Kleine Standalone-Komponente mit Reactive Form (FormBuilder/ReactiveFormsModule, MatFormFieldModule), ein Pflichtfeld „Teamname" — nach dem Muster von features/team/members/members.ts (Form-Aufbau) kombiniert mit dem MatDialog-Öffnungsmuster aus features/team/more/penalties/penalties.ts.

6. Frontend: features/team-select/team-select.ts / .html

Button „Team erstellen" dauerhaft im Template ergänzen (nicht nur im Leerzustand-Block). Klick öffnet den Dialog über MatDialog; bei erfolgreichem Abschluss MyTeamsStore neu laden und per Router direkt in das neu erstellte Team navigieren.

Fehlerbehandlung

  • Serverseitige Validierungsfehler (z. B. leerer/zu langer Name) werden als Formularfehler im Dialog angezeigt, der Dialog bleibt offen.
  • Netzwerk-/Serverfehler laufen über den bestehenden Snackbar/Toast-Mechanismus des Repos, wie bei anderen Create-Flows (z. B. createPlayer).

Testing

  • Backend (teams.service.spec.ts): createNewTeam() legt zusätzlich zu Team und Settings einen Player mit teamRole = captain und Verknüpfung zum aufrufenden User an.
  • Backend (teams.controller.spec.ts bzw. e2e): POST /teams ist für RoleEnum.user erlaubt (nicht mehr nur für RoleEnum.admin).
  • Frontend: Komponententest für den neuen Dialog (analog penalties.spec.ts) — Formularvalidierung, Aufruf von teamsApi.createTeam.
  • Frontend: Test, dass team-select nach erfolgreicher Erstellung MyTeamsStore neu lädt und in das neue Team navigiert.
  • Manuelle Verifikation: als normaler User (nicht Admin) über team-select ein Team anlegen — Aufruf sollte gelingen, User landet automatisch als Kapitän im neuen Team; Swagger-Aufruf von POST /teams als normaler User bestätigt den gelockerten Guard.

Out of Scope

  • Team löschen/archivieren (eigenes Folge-Feature).
  • Auswahl der initialen Rolle des Erstellers (immer captain, keine Wahlmöglichkeit).
  • Eigene Alias-Vergabe durch den User (weiterhin automatisch generiert).
  • Selbstständiges Anlegen von Usern durch Admins (verwandte, aber separate Lücke, siehe docs/plans/admin-user-management.md).