diff --git a/docs/superpowers/specs/2026-08-03-team-erstellen-design.md b/docs/superpowers/specs/2026-08-03-team-erstellen-design.md new file mode 100644 index 0000000..e9b7f23 --- /dev/null +++ b/docs/superpowers/specs/2026-08-03-team-erstellen-design.md @@ -0,0 +1,113 @@ +# 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() req` → `req.user.id` an den Service +durchgereicht. + +### 2. Backend: `teams.service.ts#createNewTeam` + +Aktuell (Zeile 166-178) wird nur `Team` + Default-`TeamSetting`s (`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`).