feat(#331): Listen-Reihenfolge persistieren + UI-Reorder via ↑↓ #342

Merged
admin-mrrm merged 1 commit from feat/331-listen-reorder into main 2026-05-19 20:20:33 +02:00
Owner

Closes #331

Was

Globale Listen-Reihenfolge via position-Feld auf lists plus Reorder-UI in der Übersicht.

Backend

  • Migration 0016 fügt position (int NOT NULL DEFAULT 0) zur lists-Tabelle (das Issue war hier ungenau — die Spalte gabs bisher nur auf list_items)
  • listForOwner ordnet jetzt nach position, createdAt als Tiebreaker
  • POST /lists/reorder Endpoint: nimmt { orderedIds: string[] } und schreibt 0..n-1 in einer Transaktion; 404 wenn fremde IDs dabei sind
  • create() vergibt nextListPosition (max+1 pro Owner), neue Listen landen unten
  • shared-types: position in listSchema + reorderListsDtoSchema

Frontend

  • api-client.lists.reorder() + useReorderLists-Hook mit optimistischem Update und Rollback bei Fehler
  • ListsOverviewScreen bekommt ↑/↓-Buttons pro Zeile; reorder bewegt nachbarschaftlich in der globalen Reihenfolge (auch unter typeFilter)
  • Funktioniert direkt in /listen, /einkaufen und /todo

Bewusst nicht im Scope

  • Echte Drag-and-Drop-UX (Mobile: react-native-draggable-flatlist, Web: @dnd-kit) — Reorder funktioniert jetzt einheitlich cross-platform via Buttons, ohne Lib-Pflege. DnD-UX kann als Folge-Issue auf dieses Fundament aufsetzen.

Tests

  • 7 neue Integration-Tests in lists.int-spec.ts: aufsteigende position, Sortierung, Reorder, Persistenz, fremde IDs (404), leeres Array (400), neue Liste am Ende
  • Adapter-Test in feature-shopping-list aktualisiert (List.position als Required-Feld; flacher ShoppingList-Typ strippt es weiterhin)
  • pnpm -r typecheck , pnpm -r test , pnpm test:integration (56 tests)

Test plan

  • Backend Integration-Tests (21 lists tests, 9 transfer-missing, 56 total)
  • pnpm -r typecheck
  • pnpm -r test
  • Web: in /listen Liste mit ↑/↓ verschieben → bleibt nach Reload
  • Mobile: dasselbe in der Drawer-Listenübersicht
Closes #331 ## Was Globale Listen-Reihenfolge via `position`-Feld auf `lists` plus Reorder-UI in der Übersicht. ### Backend - Migration 0016 fügt `position` (int NOT NULL DEFAULT 0) zur `lists`-Tabelle (das Issue war hier ungenau — die Spalte gabs bisher nur auf `list_items`) - `listForOwner` ordnet jetzt nach `position`, `createdAt` als Tiebreaker - `POST /lists/reorder` Endpoint: nimmt `{ orderedIds: string[] }` und schreibt 0..n-1 in einer Transaktion; 404 wenn fremde IDs dabei sind - `create()` vergibt nextListPosition (max+1 pro Owner), neue Listen landen unten - shared-types: `position` in `listSchema` + `reorderListsDtoSchema` ### Frontend - `api-client.lists.reorder()` + `useReorderLists`-Hook mit optimistischem Update und Rollback bei Fehler - `ListsOverviewScreen` bekommt ↑/↓-Buttons pro Zeile; reorder bewegt nachbarschaftlich in der globalen Reihenfolge (auch unter `typeFilter`) - Funktioniert direkt in `/listen`, `/einkaufen` und `/todo` ### Bewusst nicht im Scope - **Echte Drag-and-Drop-UX** (Mobile: `react-native-draggable-flatlist`, Web: `@dnd-kit`) — Reorder funktioniert jetzt einheitlich cross-platform via Buttons, ohne Lib-Pflege. DnD-UX kann als Folge-Issue auf dieses Fundament aufsetzen. ## Tests - 7 neue Integration-Tests in `lists.int-spec.ts`: aufsteigende `position`, Sortierung, Reorder, Persistenz, fremde IDs (404), leeres Array (400), neue Liste am Ende - Adapter-Test in feature-shopping-list aktualisiert (List.position als Required-Feld; flacher `ShoppingList`-Typ strippt es weiterhin) - `pnpm -r typecheck` ✅, `pnpm -r test` ✅, `pnpm test:integration` (56 tests) ✅ ## Test plan - [x] Backend Integration-Tests (21 lists tests, 9 transfer-missing, 56 total) - [x] pnpm -r typecheck - [x] pnpm -r test - [ ] Web: in `/listen` Liste mit ↑/↓ verschieben → bleibt nach Reload - [ ] Mobile: dasselbe in der Drawer-Listenübersicht
feat(#331): Listen-Reihenfolge persistieren + UI-Reorder via ↑↓
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
e0c269f8fe
Backend
- Migration 0016: position-Spalte auf lists (int NOT NULL DEFAULT 0)
- listForOwner sortiert nach position, createdAt (Tiebreaker)
- create() vergibt nextListPosition (max+1 pro Owner)
- Neuer Endpoint POST /lists/reorder mit { orderedIds: string[] }, schreibt
  position 0..n-1 in einer Transaktion; 404 wenn IDs nicht dem Owner gehören
- shared-types: position-Feld auf listSchema, reorderListsDtoSchema
- Integration-Tests (7 neu): aufsteigende position beim Anlegen, GET sortiert,
  Reorder ändert Reihenfolge, persistent nach Reload, 404 für fremde Liste,
  400 für leeres Array, neue Liste landet am Ende

Frontend
- api-client.lists.reorder(orderedIds)
- useReorderLists-Hook mit optimistischem Update + Rollback bei Fehler
- ListsOverviewScreen: ↑/↓-Buttons pro Zeile reorder die globale Position
  (auch wenn typeFilter aktiv ist — Reorder bewegt die Liste in der globalen
  Anordnung, nachbarschaftlich zur sichtbaren Position)
- Reorder funktioniert in Listen-, Einkaufen- und Todo-Bereich identisch
- Echte Drag-and-Drop-UX (Mobile: react-native-draggable-flatlist, Web:
  @dnd-kit) bleibt als Folge-Issue für späteren UX-Polish offen

feature-shopping-list-Adapter strippt position (nicht Teil der flachen
ShoppingList-Projektion).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
admin-mrrm/mrrmlabapp!342
No description provided.