feat(admin): complete product management

Sprint 21.

- archived (soft archive/restore, distinct from visible) with an
  include-archived list filter
- barcode field alongside sku
- variants: lightweight name|price|quantity list, same textarea-parse
  convention as specifications/attributes
- relatedProductIds: checkbox picker in the editor
- gallery images now added/removed via the shared MediaPickerComponent
  instead of a raw URL textarea
- read-only discounted-price preview in the editor
- infinite-scroll toggle on the list (loadMore() appends a page instead
  of replacing it; pagination UI swaps for a Load more button)
- category dropdown now sourced from AdminCategoriesGateway (Sprint 20)
  instead of AdminProductsLocalGateway's own BackofficeDataService seed

docs/ADMIN.md + docs/BACKEND.md updated with the new field list and the
known trade-off that related-products search is scoped to the currently
loaded page, not the full catalog.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sdarbinyan
2026-07-15 10:31:00 +04:00
parent 6a8c4a549a
commit 60c63a0d2a
15 changed files with 207 additions and 17 deletions

View File

@@ -197,6 +197,17 @@ src/app/features/admin/categories/
seed), not `AdminCategoriesGateway` - unifying them is Sprint 21 scope
(`docs/SPRINT-PLAN.md`).
## Sprint 21 - Product Management completion
- **Categories now real**: `AdminProductsLocalGateway` seeds its category dropdown from `AdminCategoriesLocalGateway.loadCategories()` (Sprint 20) instead of raw `BackofficeDataService.loadCategories()` - product `categoryId` now points at real admin-managed categories.
- **Archive/restore**: `AdminProduct.archived` (soft, distinct from `visible`). List has an "include archived" filter + per-row Archive/Restore action; archived products excluded by default (mirrors categories' `deletedAt`/restore pattern).
- **Barcode**: added alongside `sku`.
- **Variants**: lightweight `AdminProductVariant[]` (`name`/`price`/`quantity`), edited as `name|price|quantity` lines (same textarea-parse convention as `specifications`/`attributes`). Not a full options-matrix variant system - scoped to what the model/backend contract actually needs today.
- **Related products**: `relatedProductIds: string[]`, checkbox picker in the editor sourced from `AdminProductFormComponent`'s `allProducts` input - which is `AdminProductsFacade.products()`, i.e. whatever page is currently loaded in the facade (usually primed by navigating from the list). Not a full catalog search; fine for the current mock-data scale, worth revisiting if `AdminProductsLocalGateway` is ever swapped for a real API with more than a page of products.
- **Gallery**: `media.gallery` now built via the shared `MediaPickerComponent` (add/remove thumbnails) instead of a raw URL textarea; `media.images`/`media.videos` unchanged (still textarea, out of this ticket's scope).
- **Preview**: simple read-only line in the editor showing computed discounted price.
- **Infinite scroll**: `AdminProductsFacade.infiniteScroll` toggle - when on, `loadMore()` appends the next page to `products()` instead of replacing it; pagination UI swaps for a "Load more" button. Off by default (existing paginated behavior unchanged).
## Known gaps / backend needs
- **Dashboard metrics endpoint.** Categories/Products counts are computed

View File

@@ -85,9 +85,9 @@ Backend must also support content moderation/validation on publish (disallow dan
## 6. Products
**Current behavior:** `features/admin/products/` is fully built (list + editor pages) against `AdminProductsLocalGateway` (swappable via an injection token, same pattern as everywhere else) — i.e. it's ready for a real API gateway, but one has never been implemented.
**Current behavior (Sprint 21):** `features/admin/products/` is fully built (list + editor pages) against `AdminProductsLocalGateway` (swappable via an injection token, same pattern as everywhere else) — i.e. it's ready for a real API gateway, but one has never been implemented. Sprint 21 added `barcode`, `archived` (soft archive/restore), `variants` (`{name, price, quantity}[]`), `relatedProductIds`, and wired the category dropdown to `AdminCategoriesGateway` (see item 5) instead of its own seed.
**Needed:** product CRUD endpoints matching the existing storefront product contract (`itemID`, `name`, `price`, `currency`, `categoryID`, `visible`, `discount`, `images`, `badges`, `media`, `specificationGroups`, `variantOptions`, `relatedCollections` — see the Product Engagement / Product Experience 2.0 fields folded from prior sprint reports).
**Needed:** product CRUD endpoints matching the current `AdminProduct` shape (`src/app/features/admin/products/models/admin-product.model.ts`) — `itemID`, `name`, `price`, `currency`, `categoryID`, `visible`, `archived`, `discount`, `images`, `badges`, `media`, `specifications`/`attributes`, `variants`, `relatedProductIds`, plus a bulk endpoint matching `PATCH /items/bulk`-style semantics for `applyBulkVisibility`/`applyBulkDelete`.
**Frontend files:** implement `AdminProductsApiGateway` alongside the existing `AdminProductsLocalGateway` and rebind the injection token — `features/admin/products/pages/*` and the facade do not change.

View File

@@ -24,12 +24,13 @@ Notify user: **from Sprint 20 (Categories) once product↔category link + admin
- Commit: `feat(admin): complete category management`
- Note: `admin/products`' category dropdown still uses its own `AdminProductsGateway.loadCategories()`, not this new gateway — unification deferred to Sprint 21 (documented in BACKEND.md).
## Sprint 21 — Product Management completion
- [ ] Audit gaps vs list: duplicate/archive already exist? verify; add missing (archive state, restore draft, related products, variant editor, price/currency/discount editor, inventory/SKU/barcode fields already present—confirm)
- [ ] Wire products to real AdminCategoriesGateway (replace ad-hoc category options)
- [ ] Gallery via MediaPickerComponent, translation editor, preview, infinite-scroll option on list
- [ ] Update `docs/ADMIN.md`, `docs/BACKEND.md`
## Sprint 21 — Product Management completion ✅ done
- [x] Audit + add missing: `archived` (soft, list filter + archive/restore action), `barcode`, `variants` (lightweight name|price|quantity), `relatedProductIds` (checkbox picker)
- [x] Wired products to real `AdminCategoriesGateway` (`AdminProductsLocalGateway` now seeds from `AdminCategoriesLocalGateway`, replacing its own `BackofficeDataService` category seed)
- [x] Gallery via `MediaPickerComponent` (add/remove thumbnails); translation editor already existed (Sprint pre-19); preview (computed discounted price); infinite-scroll toggle on list (`facade.loadMore()` appends vs pagination)
- [x] Updated `docs/ADMIN.md` (new Sprint 21 section), `docs/BACKEND.md` (item 6 rewritten with real field list)
- Commit: `feat(admin): complete product management`
- Known trade-off: related-products picker sources from whatever page is currently loaded in `AdminProductsFacade.products()`, not a full catalog search — documented in ADMIN.md, fine at current mock scale.
## Sprint 22 — Media System hardening
- [ ] Folder support, tags, search in Media Manager