Files
dashfront/TODO.md
seb 2dd14bac91 Add category rename and drag-and-drop reordering in edit mode
- Edit toggle behind the "Kategorien" title enables an edit mode.
- In edit mode all category tiles become inline rename fields (no outline,
  distinct background, small margins); articles and "new article" are hidden.
- Rename via PATCH /api/category/:id; reorder via PUT /api/category/order
  (parentId + categoryIds) with SortableJS.
- Only call backend when order actually changed; revert DOM order on error
  so further dragging keeps working.
- Redux: renameCategory + reorderCategories thunks, renameMode state.
2026-08-02 19:43:38 +02:00

4.3 KiB
Raw Blame History

TODO — nächster Schritt (Brands / Artikelfelder)

dashback hat die HTTP-Routen geliefert (siehe ../dashback/TODO.md). Alle Endpoints stehen. companyId kommt immer aus der Auth-Session (nicht aus ?companyId=), gesteuert über google_auth.setSelectedCompany. Hier die UI bauen.

Endpoints

UI-Bedarf HTTP Request Response
Brand-Liste GET /api/brand – { brands: Brand[] }
Brand anlegen / updaten PUT /api/brand { name, gsprpinfo? } { brand: Brand }
Brand löschen DELETE /api/brand/:id – 204
EANs setzen (replace-all) PUT /api/article/:sku/eans { eans: string[] } { article } (Detail)
Brand setzen / entfernen PUT /api/article/:sku/brand { brandId: number | null } { article } (Detail)
Gewicht setzen PUT /api/article/:sku/weight { weight: number } { article } (Detail)
Kategorien setzen (replace-all) PUT /api/article/:sku/categories { categoryIds: number[] } { article } (Detail)
Kategorie umbenennen PATCH /api/category/:id { name } { category: { id, name, slug } }
Kategorie-Reihenfolge PUT /api/category/order { parentId, categoryIds: number[] } { categoryIds }
Detail liefert neue Felder GET /api/article/:sku – { article } mit eans, categoryIds, weight, brand

Brand = { id, name, gsprpinfo \| null }.

Alle PUT/PATCH-Endpoints der Artikel liefern dasselbe Shape wie GET /api/article/:sku.

Umsetzung

API-Client (src/api/index.js)

  • Alle Calls über den bestehenden Client (credentials: 'include') — Frontend spricht nur HTTP, nie direkt den Store.
  • Neuen Methoden für: brand.list / brand.upsert / brand.delete und article.setEansBySku / article.setBrandIdBySku / article.setWeightBySku / article.setCategoryIdsBySku sowie category.rename.
  • Kein companyId in Request/Pfad/Query senden — die Company kommt aus der Session.

Brand-UI

  • Liste: lädt GET /api/brand und zeigt name (+ optional gsprpinfo).
  • Anlegen/Updaten: ein Formular (Name + optional GSPRP-Info). Upsert matcht per name — gleicher Name ⇒ Update, sonst Create. Leeres/fehlendes name ⇒ API 400 Invalid brand.
  • Löschen: Bestätigung; 409 Brand in use als Fehler anzeigen (Brand ist noch an Artikeln).
  • Hängt an selectedCompanyId: bei Company-Wechsel Liste neu laden / leeren.

Artikel-Detail-Felder

  • EANs: Mehrfach-Eingabe (Liste). Replace-all: leere Liste löscht alle. 400 Invalid eans bei leeren/duplizierten Einträgen.
  • Brand: Dropdown aus GET /api/brand; „Keine Brand“ ⇒ brandId: null. Deal nur mit Brands derselben Company (sonst 404 Brand not found).
  • Gewicht: Zahlenfeld, >= 0. 400 Invalid weight sonst.
  • Kategorien: Mehrfachauswahl aus der Category-Tree; nur Kategorien derselben Company (sonst 400 Invalid categoryIds). Leere Liste entfernt alle.
  • Kategorie umbenennen: Inline/Formular im Category-Tree → PATCH /api/category/:id mit { name }. Leeres name ⇒ 400 Name required. Nach Save das zurückgegebene { id, name, slug } im Baum aktualisieren.
  • Kategorie-Reihenfolge (Drag & Drop): nach Sortierung → PUT /api/category/order mit { parentId, categoryIds } (die neuen Kind-IDs in gewünschter Reihenfolge). parentId ist der aktuelle Elternknoten. 400 Invalid category order bei falscher Menge/Duplikaten; nur Children desselben Elternteils angeben.
  • Nach jedem Save das zurückgegebene Detail-Objekt in den Store übernehmen.

Fehlerbehandlung

  • Fehler als Toast/Formular-Fehler abbilden:
    • Brand in use (409), Invalid eans / Invalid weight / Invalid categoryIds / Invalid brand (400)
    • Brand not found / Article not found / Category not found (404)
    • Name required (400) bei leerem Kategorienamen
    • No company selected (400) → Company-Wechsel-Flow
    • Not authorized (403)

Referenz

  • API-Doku: ../dashback/docs/api/README.md und ../dashback/docs/api/routes/
    • brand/list.md, brand/upsert.md, brand/delete.md
    • article/set-eans.md, article/set-brand.md, article/set-weight.md, article/set-categories.md
    • category/rename.md
  • Company-Scope: google_auth.setSelectedCompany (Store) — siehe ../dashdbschema/README.md.