docs(37): capture phase context
This commit is contained in:
116
.planning/phases/37-admin-global-item-management/37-CONTEXT.md
Normal file
116
.planning/phases/37-admin-global-item-management/37-CONTEXT.md
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
# Phase 37: Admin — Global Item Management - Context
|
||||||
|
|
||||||
|
**Gathered:** 2026-04-19
|
||||||
|
**Status:** Ready for planning
|
||||||
|
|
||||||
|
<domain>
|
||||||
|
## Phase Boundary
|
||||||
|
|
||||||
|
Build the `/admin/items` list and `/admin/items/$id` edit page, wired into the Phase 36 admin shell. Admins can browse all global catalog items, open and edit any item's full field set, and delete items with an impact-aware confirmation. No new capabilities beyond browse/edit/delete.
|
||||||
|
|
||||||
|
</domain>
|
||||||
|
|
||||||
|
<decisions>
|
||||||
|
## Implementation Decisions
|
||||||
|
|
||||||
|
### List View
|
||||||
|
- **D-01:** Data table layout — dense rows with sortable columns. No card grid. No existing table component; implement with plain Tailwind-styled HTML table.
|
||||||
|
- **D-02:** Columns: Brand + Model | Category | Weight | Price | Tags (chip or count) | Owner Count | Actions.
|
||||||
|
- **D-03:** Server-side infinite scroll pagination — load next page as admin scrolls down. No explicit next/prev buttons. Consistent with IntersectionObserver scroll detection. 50 items per page is a sensible default.
|
||||||
|
|
||||||
|
### Edit Workflow
|
||||||
|
- **D-04:** Dedicated edit page at `/admin/items/$itemId` — full-page form, bookmarkable. Consistent with the item/catalog detail page pattern already in the app.
|
||||||
|
- **D-05:** Delete lives on the edit page only (not on the list). Admin must open an item to delete it.
|
||||||
|
|
||||||
|
### Brand / Manufacturer Field
|
||||||
|
- **D-06:** Dropdown of existing manufacturers (fetched from `/api/manufacturers`). Admin picks from the list — no free-text brand creation in this phase. Prevents accidental duplicate manufacturers.
|
||||||
|
|
||||||
|
### Delete Confirmation
|
||||||
|
- **D-07:** Impact-aware confirmation dialog: show item name + owner count before confirming. Example: "Delete Salsa Woodsmoke 700? 3 users have this in their collection. This cannot be undone." Owner count already available from `getGlobalItemWithOwnerCount`.
|
||||||
|
|
||||||
|
### Claude's Discretion
|
||||||
|
- Exact column sort order and default sort (brand asc is reasonable)
|
||||||
|
- Whether tags column shows chips or a count badge when many tags exist
|
||||||
|
- Form field layout on the edit page (single column vs. two-column grid for compact fields)
|
||||||
|
- How the infinite scroll trigger is implemented (IntersectionObserver sentinel div)
|
||||||
|
- Styling of the delete button (destructive red, positioned at bottom of edit form)
|
||||||
|
|
||||||
|
</decisions>
|
||||||
|
|
||||||
|
<canonical_refs>
|
||||||
|
## Canonical References
|
||||||
|
|
||||||
|
**Downstream agents MUST read these before planning or implementing.**
|
||||||
|
|
||||||
|
### Existing Service Layer
|
||||||
|
- `src/server/services/global-item.service.ts` — `searchGlobalItems`, `getGlobalItemWithOwnerCount`, `upsertGlobalItem`; DELETE function needs to be added here
|
||||||
|
- `src/server/routes/global-items.ts` — existing GET/POST endpoints (public); admin DELETE will go through `/api/admin/items` route
|
||||||
|
|
||||||
|
### Admin Infrastructure (Phase 36)
|
||||||
|
- `src/server/routes/admin.ts` — admin route stub; extend with item sub-routes here
|
||||||
|
- `src/server/middleware/auth.ts` — `requireAdmin` middleware already in place
|
||||||
|
- `src/client/routes/admin.tsx` — admin shell layout with `<Outlet />`; "Items" nav item needs to be enabled (remove `cursor-not-allowed`, add active link)
|
||||||
|
|
||||||
|
### Client Routes
|
||||||
|
- `src/client/routes/admin/index.tsx` — admin index placeholder; stays as-is
|
||||||
|
- TanStack Router file-based routing: create `admin/items.tsx` (list) and `admin/items/$itemId.tsx` (edit)
|
||||||
|
|
||||||
|
### Database Schema
|
||||||
|
- `src/db/schema.ts` — `globalItems`, `manufacturers`, `tags`, `globalItemTags` tables
|
||||||
|
|
||||||
|
### Existing Reusable Hooks / Patterns
|
||||||
|
- `src/client/hooks/` — React Query hooks pattern; add `useAdminGlobalItems` (infinite query) and `useAdminGlobalItem`
|
||||||
|
- `src/client/lib/api.ts` — `apiGet`, `apiDelete`, `apiPut` fetch wrappers
|
||||||
|
- `src/server/routes/manufacturers.ts` (or similar) — GET /api/manufacturers for the brand dropdown
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
- `.planning/REQUIREMENTS.md` — ADMN-02, ADMN-03, ADMN-04
|
||||||
|
|
||||||
|
</canonical_refs>
|
||||||
|
|
||||||
|
<code_context>
|
||||||
|
## Existing Code Insights
|
||||||
|
|
||||||
|
### Reusable Assets
|
||||||
|
- `getGlobalItemWithOwnerCount` service function: already returns `ownerCount` — reuse for delete confirmation and edit page header
|
||||||
|
- `upsertGlobalItem` service: handles create and update via `onConflictDoUpdate`; admin edit will call this directly (PUT /api/admin/items/:id)
|
||||||
|
- `ImageUpload` component (`src/client/components/`) — reuse for image field on edit page
|
||||||
|
- `useFormatters()` hook — reuse for weight/price display in the table
|
||||||
|
- LucideIcon `"package"` already in the admin sidebar "Items" entry — just enable it
|
||||||
|
|
||||||
|
### Established Patterns
|
||||||
|
- Infinite scroll: Phase 26 discovery feed used cursor pagination + React Query's `useInfiniteQuery` — same pattern here
|
||||||
|
- Edit forms: item/catalog detail pages use controlled form state with `apiPut`
|
||||||
|
- Destructive confirmation: confirm modals exist in the app (setup delete, etc.) — reuse the same modal pattern
|
||||||
|
- React Query invalidation: mutations call `queryClient.invalidateQueries` with relevant query keys
|
||||||
|
|
||||||
|
### Integration Points
|
||||||
|
- `src/client/routes/admin.tsx`: Change "Items" sidebar entry from `<div cursor-not-allowed>` to `<Link to="/admin/items">` with active styling
|
||||||
|
- `src/server/index.ts`: Register `adminItemRoutes` under `/api/admin/items`
|
||||||
|
- `src/server/routes/admin.ts`: Mount item sub-router
|
||||||
|
|
||||||
|
</code_context>
|
||||||
|
|
||||||
|
<specifics>
|
||||||
|
## Specific Ideas
|
||||||
|
|
||||||
|
- Table row click → navigate to `/admin/items/$itemId`
|
||||||
|
- Edit page has a back link "← Items" to return to the list
|
||||||
|
- Delete button at bottom of edit form, styled destructive red, triggers impact-aware modal
|
||||||
|
- Infinite scroll sentinel: a `<div ref={sentinelRef}>` at bottom of table; IntersectionObserver triggers next page fetch
|
||||||
|
|
||||||
|
</specifics>
|
||||||
|
|
||||||
|
<deferred>
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- Manufacturer creation from within the admin panel — admin can only pick existing manufacturers in this phase; creating new ones is out of scope
|
||||||
|
- Bulk delete / bulk edit from the list — admin-only single-item workflow for now
|
||||||
|
- Column sorting — mentioned as a potential feature but not in ADMN-02/03/04 success criteria; Claude's discretion whether to include basic sort
|
||||||
|
|
||||||
|
</deferred>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Phase: 37-admin-global-item-management*
|
||||||
|
*Context gathered: 2026-04-19*
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# Phase 37: Admin — Global Item Management - Discussion Log
|
||||||
|
|
||||||
|
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
|
||||||
|
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
|
||||||
|
|
||||||
|
**Date:** 2026-04-19
|
||||||
|
**Phase:** 37 — Admin — Global Item Management
|
||||||
|
**Areas discussed:** List view style, Edit workflow, Brand/manufacturer field, Delete confirmation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## List view style
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Data table | Dense rows with columns for brand, model, category, weight, price, tags, owner count. Sortable, scannable, admin-appropriate. | ✓ |
|
||||||
|
| Card grid | Consistent with public catalog. Reuses GearImage/card patterns but wastes space for data management. | |
|
||||||
|
| List rows (compact) | Single-line rows with brand/model + a few stats. Middle ground. | |
|
||||||
|
|
||||||
|
**User's choice:** Data table
|
||||||
|
|
||||||
|
**Table columns selected:** Brand + Model, Category + Weight + Price, Tags, Owner count
|
||||||
|
|
||||||
|
**Pagination:** Server-side infinite scroll — load next page on scroll, not explicit next/prev buttons
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Edit workflow
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Dedicated edit page /admin/items/$id | Full-page form, bookmarkable, consistent with detail page pattern. | ✓ |
|
||||||
|
| Slide-over drawer | Slides in over list, keeps list context. Requires new drawer component. | |
|
||||||
|
|
||||||
|
**User's choice:** Dedicated edit page
|
||||||
|
|
||||||
|
**Delete location:** Edit page only (not on list)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Brand/manufacturer field
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Dropdown of existing manufacturers | Admin picks from list fetched from /api/manufacturers. Safe, no duplicates. | ✓ |
|
||||||
|
| Free-text with auto-match | Admin types brand; matched or created on save. Risks duplicates. | |
|
||||||
|
|
||||||
|
**User's choice:** Dropdown of existing manufacturers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Delete confirmation
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Impact-aware | Show item name + owner count: "3 users have this in their collection. This cannot be undone." | ✓ |
|
||||||
|
| Simple confirmation | "Are you sure? This cannot be undone." No extra data. | |
|
||||||
|
|
||||||
|
**User's choice:** Impact-aware confirmation with owner count
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Claude's Discretion
|
||||||
|
|
||||||
|
- Column sort order and default sort
|
||||||
|
- Tags column display (chips vs count badge)
|
||||||
|
- Edit form field layout (single vs two-column)
|
||||||
|
- IntersectionObserver implementation for infinite scroll trigger
|
||||||
|
- Delete button styling and position on edit page
|
||||||
|
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- Manufacturer creation from within admin panel (out of scope for this phase)
|
||||||
|
- Bulk delete / bulk edit from the list
|
||||||
|
- Column sorting (not in success criteria; Claude's discretion)
|
||||||
Reference in New Issue
Block a user