MS-FE-2: Gruppen/Personen UI umsetzen #102

Closed
opened 2026-06-23 23:03:56 +02:00 by niboer · 0 comments
Owner

Uebersicht

Frontend-UI fuer Haushaltsverwaltung (Groups) und Personenverwaltung. Baut auf den MS-FE-1-Platzhalter-Routen (/app/groups, /app/groups/[groupId]) und der bereits implementierten Personen-Liste und Self-Service-Seite auf.

API-Grundlage (Backend bereits fertig)

Alle benoetigten Backend-Endpunkte sind in MS-BE-API-1 (#112-#115) implementiert und getestet:

  • GET /api/v1/groups + POST /api/v1/groups
  • GET/PUT/DELETE /api/v1/groups/{group_id}
  • GET/POST /api/v1/groups/{group_id}/members + DELETE .../members/{person_id}
  • POST /api/v1/groups/{group_id}/join-request + PUT .../join-request/{person_id}
  • GET /api/v1/persons, GET/PUT /api/v1/persons/{person_id}
  • POST /api/v1/persons/{person_id}/archive
  • POST /api/v1/persons/{person_id}/switch-group

Vorhandene Frontend-Struktur (MS-FE-1)

  • Gruppenliste (/app/groups): +page.server.ts mit load-Funktion (fetch /api/v1/groupsGroup[]), +page.svelte mit EmptyState und MS-FE-2-Hinweis
  • Gruppendetail (/app/groups/[groupId]): load-Funktion (fetch /api/v1/groups/{id}Group), Page mit EmptyState
  • Personenliste (/app/persons): DataTable mit Name/Status/Erstellt am, Links zu Self-Service
  • Personendetail (/app/persons/[personId]): Self-Service mit Einladungen, Confirm/Decline, Formularfeldern
  • Tests: groups.test.ts (Platzhalter-Tests), persons.test.ts (Grundfunktionen)

Schritt-fuer-Schritt-Plan (5 Commits)

Commit 1: chore(frontend): Orval-Typen fuer MS-FE-2 regeneriert

Aenderungen:

  • npm run generate:api ausfuehren → frontend/src/lib/api/generated.ts aktualisieren
  • Sicherstellen, dass Group, GroupMember, CreateGroup, JoinRequestAction etc. korrekt generiert sind
  • ggf. bestehende Typ-Importe in +page.server.ts-Dateien anpassen

Tests:

  • Bestehende groups.test.ts und persons.test.ts laufen weiterhin gruen
  • Optional: Test, der die Orval-Exporte auf Vollstaendigkeit prueft (analog api-conventions.test.ts)

Lint/Check: npm run test && npm run check


Commit 2: feat(frontend): Gruppenliste mit Create/Edit/Delete umgesetzt

Aenderungen an /app/groups/+page.svelte:

  • EmptyState durch DataTable ersetzen
  • Spalten: Name, Mitglieder-Anzahl, Erstellt am, Aktionen
  • "Neuen Haushalt anlegen"-Button in PageHeader-children (nur bei eingeloggten Usern, da POST /api/v1/groups nur requireAuth braucht)
  • Create-Dialog (shadcn-svelte Dialog): Formular mit Namensfeld, Submit-Button
  • Edit-Dialog: Nur sichtbar mit requireCompositeRole('edit-group')-Permission
  • Delete-Dialog: Bestaetigungsdialog, nur mit edit-group-Permission
  • Aktionen nutzen Form Actions (?/create, ?/update, ?/delete) mit use:enhance

Aenderungen an /app/groups/+page.server.ts:

  • load-Funktion: Zusaetzlich GroupMember[] pro Gruppe laden (via separatem fetch oder aggregiert)
  • error-Handling: Fehler pro Aktion unterscheidbar machen
  • Actions: create, update, delete mit Validierung und API-Calls

Tests (groups.test.ts erweitern):

  • Load-Funktion: Gruppendaten mit Member-Info, Error-Handling
  • Create-Action: Erfolg (POST 201), Fehler (400/401), leeres Namensfeld
  • Update-Action: Erfolg (PUT 200), Fehler (403 ohne edit-group), 404
  • Delete-Action: Erfolg (DELETE 204), Fehler (403)
  • Page-Rendering: DataTable-Spalten, Dialog-Existenz im Source-Code

Commit 3: feat(frontend): Gruppendetail mit Mitgliederverwaltung und Join-Requests

Aenderungen an /app/groups/[groupId]/+page.svelte:

  • Gruppen-Info-Bereich (Name, Erstellt von/am)
  • Mitglieder-Tabelle (DataTable): Name, Status (approved/pending), Beitrittsdatum, Aktionen
  • "Mitglied hinzufuegen"-Dialog: Person-Suche (oder Dropdown aller Personen ohne Haushalt), POST members
  • Mitglied entfernen: Bestaetigungsdialog, DELETE members (eigene Person immer erlaubt, fremde nur mit edit-group)
  • Join-Request-Bereich: Ausstehende Anfragen auflisten (Person, Datum), Approve/Reject-Buttons
  • Edit-Name-Dialog (nur edit-group)
  • Delete-Group-Button (nur edit-group)

Aenderungen an /app/groups/[groupId]/+page.server.ts:

  • load-Funktion: Group + Members + Join-Requests (pending) laden
  • Actions: addMember, removeMember, approveJoin, rejectJoin, updateGroup, deleteGroup

Tests (groups.test.ts erweitern):

  • Load-Funktion: Group + Members + pending requests
  • Add-Member: Erfolg (POST 201), Fehler (Person bereits in Gruppe/400)
  • Remove-Member: Erfolg (DELETE 204), eigene Person, fremde mit edit-group
  • Join-Request: Approve (PUT 200), Reject (PUT 200 mit loeschen)
  • Update/Delete Group analog Commit 2
  • Page-Rendering: DataTable-Spalten, Dialoge, Join-Request-Sektion

Commit 4: feat(frontend): Personenliste mit Archivierungs-Filter erweitert

Aenderungen an /app/persons/+page.svelte:

  • Filter-Buttons/Tabs: "Alle" / "Aktiv" / "Archiviert"
  • Query-Parameter ?archived=true|false an API weiterreichen
  • Aktionen-Spalte mit "Archivieren"-Button (nur eigene Person, da requireOwnData)
  • Archivierungs-Status deutlicher hervorheben

Aenderungen an /app/persons/+page.server.ts:

  • Query-Parameter archived aus URL-Params lesen und an API-Request weiterreichen
  • Optional: Eigene personId erkennen (via /api/v1/persons/me) um "Archivieren"-Button nur bei eigener Person zu zeigen

Tests (persons.test.ts erweitern):

  • load-Funktion: ?archived=true wird weitergeleitet, default (kein Filter) = alle
  • Archivierungs-Action: Erfolg (POST archive 200), Error-Handling
  • Page-Rendering: Filter-Tabs, Aktionen-Spalte

Commit 5: feat(frontend): Personendetail um Haushaltsinfo und Self-Archivierung (closes #102)

Aenderungen an /app/persons/[personId]/+page.svelte:

  • Gruppen/Haushalts-Info-Karte: "Aktueller Haushalt: [Name]" mit Link zu /app/groups/[groupId]
  • Falls kein Haushalt: "Keinem Haushalt zugeordnet" mit Hinweis
  • "Account archivieren"-Button (nur eigene Person): Bestaetigungsdialog
  • Nach Archivierung: Hinweis "Dieser Account ist archiviert" + "Wiederherstellung nur durch Admin"
  • Lade zusaetzlich groupId + groupName in der load-Funktion

Aenderungen an /app/persons/[personId]/+page.server.ts:

  • load-Funktion: Zusaetzlich Group-Mitgliedschaft laden (GET /api/v1/groups/{personId}/members oder ueber Person-Endpunkt)
  • Action: archive (POST /api/v1/persons/{person_id}/archive)

Tests (self-service.test.ts erweitern):

  • Load-Funktion: Gruppen-Info wird geladen, Optional (null bei keinem Haushalt)
  • Archivierungs-Action: Erfolg (POST 200), Error (bereits archiviert/400)
  • Page-Rendering: Gruppen-Karte, Archivierungs-Button, Archivierungs-Status

Autorisierungs-Matrix (preHandler fuer Frontend-Aktionen)

UI-Aktion API-Endpunkt preHandler
Gruppen auflisten GET /api/v1/groups requireAuth + requireConsent
Gruppe anlegen POST /api/v1/groups requireAuth
Gruppe bearbeiten PUT /api/v1/groups/{id} requireAuth + edit-group
Gruppe loeschen DELETE /api/v1/groups/{id} requireAuth + edit-group
Mitglieder auflisten GET .../members requireAuth
Mitglied hinzufuegen POST .../members requireAuth + requireGroupMember
Mitglied entfernen (selbst) DELETE .../members/{pid} requireAuth + requireOwnData
Mitglied entfernen (fremd) DELETE .../members/{pid} requireAuth + edit-group
Join-Request stellen POST .../join-request requireAuth
Join-Request bearbeiten PUT .../join-request/{pid} requireAuth + requireGroupMember
Person auflisten GET /api/v1/persons requireAuth + requireConsent
Person archivieren (selbst) POST .../archive requireAuth + requireOwnData

Abhaengigkeiten und Randbedingungen

  • Kein neues DB-Schema noetig — alle benoetigten Tabellen und Endpunkte existieren
  • Kein neuer Orval-Lauf nach Commit 1 — die generierten Typen bleiben konstant
  • Permissions im Frontend pruefbar via request.user.roles aus dem JWT (fuer edit-group-Pruefung)
  • i18n wird nicht in MS-FE-2 implementiert — gehoert zu MS-FE-6 (#106). Deutsche UI-Texte werden hartcodiert (analog bestehender Personen-Seiten)
  • Die design.md-Referenzen auf §8.11.x sind veraltet — der Abschnitt wurde bei der letzten Bereinigung entfernt. README.md-Referenzen sollten bei Gelegenheit bereinigt werden.
## Uebersicht Frontend-UI fuer Haushaltsverwaltung (Groups) und Personenverwaltung. Baut auf den MS-FE-1-Platzhalter-Routen (`/app/groups`, `/app/groups/[groupId]`) und der bereits implementierten Personen-Liste und Self-Service-Seite auf. ## API-Grundlage (Backend bereits fertig) Alle benoetigten Backend-Endpunkte sind in MS-BE-API-1 (#112-#115) implementiert und getestet: - `GET /api/v1/groups` + `POST /api/v1/groups` - `GET/PUT/DELETE /api/v1/groups/{group_id}` - `GET/POST /api/v1/groups/{group_id}/members` + `DELETE .../members/{person_id}` - `POST /api/v1/groups/{group_id}/join-request` + `PUT .../join-request/{person_id}` - `GET /api/v1/persons`, `GET/PUT /api/v1/persons/{person_id}` - `POST /api/v1/persons/{person_id}/archive` - `POST /api/v1/persons/{person_id}/switch-group` ## Vorhandene Frontend-Struktur (MS-FE-1) - **Gruppenliste** (`/app/groups`): `+page.server.ts` mit load-Funktion (fetch `/api/v1/groups` → `Group[]`), `+page.svelte` mit EmptyState und MS-FE-2-Hinweis - **Gruppendetail** (`/app/groups/[groupId]`): load-Funktion (fetch `/api/v1/groups/{id}` → `Group`), Page mit EmptyState - **Personenliste** (`/app/persons`): DataTable mit Name/Status/Erstellt am, Links zu Self-Service - **Personendetail** (`/app/persons/[personId]`): Self-Service mit Einladungen, Confirm/Decline, Formularfeldern - **Tests**: `groups.test.ts` (Platzhalter-Tests), `persons.test.ts` (Grundfunktionen) ## Schritt-fuer-Schritt-Plan (5 Commits) ### Commit 1: `chore(frontend): Orval-Typen fuer MS-FE-2 regeneriert` **Aenderungen:** - `npm run generate:api` ausfuehren → `frontend/src/lib/api/generated.ts` aktualisieren - Sicherstellen, dass `Group`, `GroupMember`, `CreateGroup`, `JoinRequestAction` etc. korrekt generiert sind - ggf. bestehende Typ-Importe in `+page.server.ts`-Dateien anpassen **Tests:** - Bestehende `groups.test.ts` und `persons.test.ts` laufen weiterhin gruen - Optional: Test, der die Orval-Exporte auf Vollstaendigkeit prueft (analog `api-conventions.test.ts`) **Lint/Check:** `npm run test && npm run check` --- ### Commit 2: `feat(frontend): Gruppenliste mit Create/Edit/Delete umgesetzt` **Aenderungen an `/app/groups/+page.svelte`:** - EmptyState durch DataTable ersetzen - Spalten: Name, Mitglieder-Anzahl, Erstellt am, Aktionen - "Neuen Haushalt anlegen"-Button in PageHeader-children (nur bei eingeloggten Usern, da `POST /api/v1/groups` nur requireAuth braucht) - Create-Dialog (shadcn-svelte Dialog): Formular mit Namensfeld, Submit-Button - Edit-Dialog: Nur sichtbar mit `requireCompositeRole('edit-group')`-Permission - Delete-Dialog: Bestaetigungsdialog, nur mit `edit-group`-Permission - Aktionen nutzen Form Actions (`?/create`, `?/update`, `?/delete`) mit `use:enhance` **Aenderungen an `/app/groups/+page.server.ts`:** - load-Funktion: Zusaetzlich `GroupMember[]` pro Gruppe laden (via separatem fetch oder aggregiert) - `error`-Handling: Fehler pro Aktion unterscheidbar machen - Actions: `create`, `update`, `delete` mit Validierung und API-Calls **Tests (`groups.test.ts` erweitern):** - Load-Funktion: Gruppendaten mit Member-Info, Error-Handling - Create-Action: Erfolg (POST 201), Fehler (400/401), leeres Namensfeld - Update-Action: Erfolg (PUT 200), Fehler (403 ohne edit-group), 404 - Delete-Action: Erfolg (DELETE 204), Fehler (403) - Page-Rendering: DataTable-Spalten, Dialog-Existenz im Source-Code --- ### Commit 3: `feat(frontend): Gruppendetail mit Mitgliederverwaltung und Join-Requests` **Aenderungen an `/app/groups/[groupId]/+page.svelte`:** - Gruppen-Info-Bereich (Name, Erstellt von/am) - Mitglieder-Tabelle (DataTable): Name, Status (approved/pending), Beitrittsdatum, Aktionen - "Mitglied hinzufuegen"-Dialog: Person-Suche (oder Dropdown aller Personen ohne Haushalt), POST members - Mitglied entfernen: Bestaetigungsdialog, DELETE members (eigene Person immer erlaubt, fremde nur mit edit-group) - Join-Request-Bereich: Ausstehende Anfragen auflisten (Person, Datum), Approve/Reject-Buttons - Edit-Name-Dialog (nur edit-group) - Delete-Group-Button (nur edit-group) **Aenderungen an `/app/groups/[groupId]/+page.server.ts`:** - load-Funktion: Group + Members + Join-Requests (pending) laden - Actions: `addMember`, `removeMember`, `approveJoin`, `rejectJoin`, `updateGroup`, `deleteGroup` **Tests (`groups.test.ts` erweitern):** - Load-Funktion: Group + Members + pending requests - Add-Member: Erfolg (POST 201), Fehler (Person bereits in Gruppe/400) - Remove-Member: Erfolg (DELETE 204), eigene Person, fremde mit edit-group - Join-Request: Approve (PUT 200), Reject (PUT 200 mit loeschen) - Update/Delete Group analog Commit 2 - Page-Rendering: DataTable-Spalten, Dialoge, Join-Request-Sektion --- ### Commit 4: `feat(frontend): Personenliste mit Archivierungs-Filter erweitert` **Aenderungen an `/app/persons/+page.svelte`:** - Filter-Buttons/Tabs: "Alle" / "Aktiv" / "Archiviert" - Query-Parameter `?archived=true|false` an API weiterreichen - Aktionen-Spalte mit "Archivieren"-Button (nur eigene Person, da `requireOwnData`) - Archivierungs-Status deutlicher hervorheben **Aenderungen an `/app/persons/+page.server.ts`:** - Query-Parameter `archived` aus URL-Params lesen und an API-Request weiterreichen - Optional: Eigene personId erkennen (via `/api/v1/persons/me`) um "Archivieren"-Button nur bei eigener Person zu zeigen **Tests (`persons.test.ts` erweitern):** - load-Funktion: `?archived=true` wird weitergeleitet, default (kein Filter) = alle - Archivierungs-Action: Erfolg (POST archive 200), Error-Handling - Page-Rendering: Filter-Tabs, Aktionen-Spalte --- ### Commit 5: `feat(frontend): Personendetail um Haushaltsinfo und Self-Archivierung (closes #102)` **Aenderungen an `/app/persons/[personId]/+page.svelte`:** - Gruppen/Haushalts-Info-Karte: "Aktueller Haushalt: [Name]" mit Link zu `/app/groups/[groupId]` - Falls kein Haushalt: "Keinem Haushalt zugeordnet" mit Hinweis - "Account archivieren"-Button (nur eigene Person): Bestaetigungsdialog - Nach Archivierung: Hinweis "Dieser Account ist archiviert" + "Wiederherstellung nur durch Admin" - Lade zusaetzlich groupId + groupName in der load-Funktion **Aenderungen an `/app/persons/[personId]/+page.server.ts`:** - load-Funktion: Zusaetzlich Group-Mitgliedschaft laden (GET /api/v1/groups/{personId}/members oder ueber Person-Endpunkt) - Action: `archive` (POST /api/v1/persons/{person_id}/archive) **Tests (`self-service.test.ts` erweitern):** - Load-Funktion: Gruppen-Info wird geladen, Optional (null bei keinem Haushalt) - Archivierungs-Action: Erfolg (POST 200), Error (bereits archiviert/400) - Page-Rendering: Gruppen-Karte, Archivierungs-Button, Archivierungs-Status --- ## Autorisierungs-Matrix (preHandler fuer Frontend-Aktionen) | UI-Aktion | API-Endpunkt | preHandler | |---|---|---| | Gruppen auflisten | `GET /api/v1/groups` | `requireAuth + requireConsent` | | Gruppe anlegen | `POST /api/v1/groups` | `requireAuth` | | Gruppe bearbeiten | `PUT /api/v1/groups/{id}` | `requireAuth + edit-group` | | Gruppe loeschen | `DELETE /api/v1/groups/{id}` | `requireAuth + edit-group` | | Mitglieder auflisten | `GET .../members` | `requireAuth` | | Mitglied hinzufuegen | `POST .../members` | `requireAuth + requireGroupMember` | | Mitglied entfernen (selbst) | `DELETE .../members/{pid}` | `requireAuth + requireOwnData` | | Mitglied entfernen (fremd) | `DELETE .../members/{pid}` | `requireAuth + edit-group` | | Join-Request stellen | `POST .../join-request` | `requireAuth` | | Join-Request bearbeiten | `PUT .../join-request/{pid}` | `requireAuth + requireGroupMember` | | Person auflisten | `GET /api/v1/persons` | `requireAuth + requireConsent` | | Person archivieren (selbst) | `POST .../archive` | `requireAuth + requireOwnData` | ## Abhaengigkeiten und Randbedingungen - **Kein neues DB-Schema noetig** — alle benoetigten Tabellen und Endpunkte existieren - **Kein neuer Orval-Lauf** nach Commit 1 — die generierten Typen bleiben konstant - **Permissions im Frontend pruefbar** via `request.user.roles` aus dem JWT (fuer edit-group-Pruefung) - **i18n wird nicht in MS-FE-2 implementiert** — gehoert zu MS-FE-6 (#106). Deutsche UI-Texte werden hartcodiert (analog bestehender Personen-Seiten) - **Die design.md-Referenzen auf §8.11.x sind veraltet** — der Abschnitt wurde bei der letzten Bereinigung entfernt. README.md-Referenzen sollten bei Gelegenheit bereinigt werden.
Sign in to join this conversation.
No description provided.