9.7 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 18-global-items-public-profiles | 04 | execute | 3 |
|
|
false |
|
|
Purpose: Delivers the client-side experience for GLOB-03 (search), GLOB-04 (linking), and GLOB-05 (detail with owner count). Output: useGlobalItems hook, catalog browse page, detail page, GlobalItemCard, LinkToGlobalItem component
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/18-global-items-public-profiles/18-CONTEXT.md @.planning/phases/18-global-items-public-profiles/18-RESEARCH.md @.planning/phases/18-global-items-public-profiles/18-02-SUMMARY.md@src/client/hooks/useItems.ts @src/client/lib/api.ts @src/client/routes/collection/index.tsx
GET /api/global-items?q=string -> GlobalItem[] GET /api/global-items/:id -> { ...GlobalItem, ownerCount: number } POST /api/items/:id/link { globalItemId: number } -> ItemGlobalLink (201) DELETE /api/items/:id/link -> 200type GlobalItem = { id, brand, model, category, weightGrams, priceCents, imageUrl, description, createdAt } type GlobalItemWithOwnerCount = GlobalItem & { ownerCount: number }
Task 1: Global item hooks and catalog pages src/client/hooks/useGlobalItems.ts, src/client/routes/global-items/index.tsx, src/client/routes/global-items/$globalItemId.tsx, src/client/components/GlobalItemCard.tsx src/client/hooks/useItems.ts, src/client/lib/api.ts, src/client/routes/collection/index.tsx **useGlobalItems.ts** hook: Create at `src/client/hooks/useGlobalItems.ts`. Follow existing hook pattern from useItems.ts.-
useGlobalItems(query?: string)—useQuerywith key["global-items", query], fetchesapiGet<GlobalItem[]>("/api/global-items" + (query ? "?q=" + encodeURIComponent(query) : "")). Use 300ms debounced query value for search (or accept debounce at the component level). -
useGlobalItem(id: number | null)—useQuerywith key["global-items", id], fetchesapiGet<GlobalItemWithOwnerCount>("/api/global-items/${id}"),enabled: id != null. -
useLinkItem()—useMutationcallingapiPost("/api/items/${itemId}/link", { globalItemId }). On success, invalidate["items"]and["global-items"]query keys. -
useUnlinkItem()—useMutationcallingapiDelete("/api/items/${itemId}/link"). On success, invalidate same keys.
GlobalItemCard.tsx: Create at src/client/components/GlobalItemCard.tsx. Card displaying brand, model, category badge, weight (formatted as g/kg), price (formatted from cents). Links to /global-items/${item.id} detail page. Show image thumbnail if imageUrl exists. Light/airy Tailwind styling matching existing collection cards.
global-items/index.tsx: Catalog browse/search page.
- Search input at top with placeholder "Search gear by brand or model..."
- Debounce input by 300ms before passing to
useGlobalItems(debouncedQuery) - Grid of GlobalItemCard components (responsive: 1 col mobile, 2 cols md, 3 cols lg)
- Loading skeleton while fetching
- Empty state: "No items found" or "Search the global gear catalog"
- TanStack Router:
createFileRoute("/global-items/")with component export
global-items/$globalItemId.tsx: Detail page.
- TanStack Router:
createFileRoute("/global-items/$globalItemId")with params loader - Fetch single item with
useGlobalItem(Number(globalItemId)) - Display: brand, model, category, weight, price, description, image (full size)
- Show owner count badge: "{N} users own this" or "Be the first to add this"
- Back link to catalog
bun run lint 2>&1 | tail -5
<acceptance_criteria>
- grep -q "useGlobalItems" src/client/hooks/useGlobalItems.ts
- grep -q "useGlobalItem" src/client/hooks/useGlobalItems.ts
- grep -q "useLinkItem" src/client/hooks/useGlobalItems.ts
- test -f src/client/routes/global-items/index.tsx
- test -f "src/client/routes/global-items/$globalItemId.tsx"
- test -f src/client/components/GlobalItemCard.tsx </acceptance_criteria> Global catalog page shows searchable grid of items. Detail page shows specs, image, and owner count. Hooks handle all data fetching and mutations. Lint passes.
A component that allows linking a user's personal item to a global catalog entry. Design as a small modal/popover or inline search:
- Trigger: A "Link to catalog" button shown on item detail or edit view. If already linked, show "Linked to {brand} {model}" with an unlink option.
- When triggered, show a search input that calls
useGlobalItems(query)with debounce. - Display matching global items as clickable options.
- On select, call
useLinkItem()mutation with itemId and globalItemId. - Show success state: linked item name with a link to the global item detail page.
- Unlink: If already linked, show the linked global item with an "Unlink" button that calls
useUnlinkItem().
Keep it simple — a dropdown/combobox pattern works well. Use Tailwind for styling. Match the light/airy aesthetic of existing components.
Wire this component into the item edit form or item detail view at the appropriate place (after the existing form fields, or as a separate section below item details). bun run lint 2>&1 | tail -5 <acceptance_criteria> - grep -q "LinkToGlobalItem" src/client/components/LinkToGlobalItem.tsx - grep -q "useLinkItem|linkItem" src/client/components/LinkToGlobalItem.tsx - grep -q "useUnlinkItem|unlinkItem" src/client/components/LinkToGlobalItem.tsx </acceptance_criteria> Users can search the global catalog from within their item view, link/unlink their item, and see the current link status. Lint passes.
Task 3: Verify global catalog UI none Human verification of the global item catalog UI. Review what was built: browse page with search, detail page with owner count, and link/unlink from collection items.Steps to verify:
- Start dev server:
bun run dev - Navigate to
/global-items— should see catalog with seed items in a grid - Type "revelate" in search — should filter to matching items
- Click a global item — detail page shows brand, model, specs, "0 users own this"
- Go to your collection, open an item, find "Link to catalog" control
- Search for a global item and link it — should show linked status
- Return to global item detail — owner count should now show "1 user owns this"
- Unlink the item — owner count returns to 0 bun run build 2>&1 | tail -3 User approves global catalog UI: search works, detail page shows owner count, link/unlink flow is functional.
<success_criteria> Global catalog is browsable and searchable. Item detail shows owner count. Users can link/unlink personal items to global entries. All pages render correctly with Tailwind styling. </success_criteria>
After completion, create `.planning/phases/18-global-items-public-profiles/18-04-SUMMARY.md`