From 289044e26f650d4affea193643fdc7591bbca4c0 Mon Sep 17 00:00:00 2001 From: syntaxbullet Date: Sat, 28 Mar 2026 16:56:45 +0100 Subject: [PATCH] docs: add inventory display redesign spec Co-Authored-By: Claude Opus 4.6 (1M context) --- .../2026-03-28-inventory-display-redesign.md | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 docs/superpowers/specs/2026-03-28-inventory-display-redesign.md diff --git a/docs/superpowers/specs/2026-03-28-inventory-display-redesign.md b/docs/superpowers/specs/2026-03-28-inventory-display-redesign.md new file mode 100644 index 0000000..80e7567 --- /dev/null +++ b/docs/superpowers/specs/2026-03-28-inventory-display-redesign.md @@ -0,0 +1,117 @@ +# Inventory Display Redesign + +## Overview + +Redesign the `/inventory` command from a basic embed listing to a polished Components V2 experience with rarity indicators, paginated list view, item detail view with artwork, and inline item management actions. + +## Rarity Emoji Mapping + +Add a `squareEmoji` field to `RARITY_CONFIG` in `shared/lib/rarity.ts`: + +| Rarity | squareEmoji | Existing emoji | Color hex | +|--------|-------------|----------------|-----------| +| C | ๐ŸŸค | ๐Ÿ“ฆ | 0x95A5A6 | +| R | ๐Ÿ”ต | ๐Ÿ“ฆ | 0x3498DB | +| SR | ๐ŸŸฃ | โœจ | 0x9B59B6 | +| SSR | ๐ŸŸก | ๐ŸŒŸ | 0xF1C40F | + +Non-item rarities (CURRENCY, XP, NOTHING) do not get square emojis. The existing `emoji` field remains unchanged (used by lootbox results). + +## List View + +The `/inventory [user]` command renders a Components V2 message: + +1. **Header** โ€” `TextDisplayBuilder`: `# ๐Ÿ“ฆ {username}'s Inventory` with subtitle showing total item count. +2. **Separator** +3. **Item rows** (5 per page) โ€” Each item is a `TextDisplayBuilder` line: `{squareEmoji} **{Item Name}** โ€” {Rarity Label} ยท {Type} ยท ร—{quantity}` +4. **Separator** +5. **Select menu** โ€” `StringSelectMenuBuilder` populated with the 5 items on the current page. Placeholder: "Select an item for details". Each option shows item name and rarity label. +6. **Navigation row** โ€” `ActionRowBuilder`: `โ—€ Previous` (disabled on page 1), disabled `Page X/Y` indicator button, `Next โ–ถ` (disabled on last page). + +**Container:** `ContainerBuilder` with accent color from the highest-rarity item on the current page. + +**Sorting:** Items sorted by rarity descending (SSR โ†’ SR โ†’ R โ†’ C), then alphabetically within the same rarity. + +**Empty state:** If inventory is empty, show: "No items yet. Visit the shop or complete quests to earn items!" + +**Collector:** `createMessageComponentCollector` with 2-minute idle timeout. On timeout, disable all interactive components. + +## Detail View + +Shown when a user selects an item from the dropdown or uses `/inventory view `: + +1. **Header section** โ€” `SectionBuilder`: + - `TextDisplayBuilder`: `{squareEmoji} **{Item Name}**` with subtitle `-# {Rarity Label} ยท {Type}` + - `ThumbnailBuilder` with the item's `iconUrl` +2. **Artwork** โ€” `MediaGalleryBuilder` displaying the item's `imageUrl` +3. **Description** โ€” `TextDisplayBuilder` with the item's `description` +4. **Separator** +5. **Stats row** โ€” `TextDisplayBuilder`: `Owned: **ร—{quantity}**` and `Value: **{price} ๐Ÿช™**` (or "Not tradeable" if price is null) +6. **Action buttons** โ€” `ActionRowBuilder`: + - `โ—€ Back` (primary) โ€” returns to list view at the same page + - `๐Ÿงช Use` (success) โ€” only shown if item type is CONSUMABLE with effects defined + - `๐Ÿ—‘ Discard` (danger) โ€” drops one unit of the item + +**Container:** `ContainerBuilder` with accent color matching the item's rarity color. + +### Use Button Flow + +Calls `inventoryService.useItem()` and shows the result inline. Then returns to the detail view with updated quantity. If quantity reaches 0, returns to the list view. + +### Discard Flow + +1. Clicking `๐Ÿ—‘ Discard` replaces the action row with a confirmation: "Discard 1ร— {Item Name}?" with `Confirm` (danger) and `Cancel` (secondary) buttons. +2. On confirm: calls `inventoryService.removeItem(userId, itemId, 1)`, returns to detail view with updated quantity. If quantity reaches 0, returns to list view. +3. On cancel: returns to the normal detail view action buttons. + +## `/inventory view ` Subcommand + +Adds a `view` subcommand with a required `item` string option that has autocomplete. Autocomplete queries the user's inventory items (reusing the pattern from `getAutocompleteItems`). Goes directly to the detail view. The Back button returns to the full paginated list at page 1. + +## Item Selection Entry Points + +Two ways to reach the detail view: +- **Select menu dropdown** on the inventory list โ€” for browsing +- **`/inventory view `** subcommand โ€” for direct access when the user knows the item name + +Both render the same detail view. + +## Interaction Custom IDs + +All custom IDs include the invoking user's ID to prevent other users from interacting: + +| Custom ID | Purpose | +|-----------|---------| +| `inv_select_{userId}` | Item select menu | +| `inv_prev_{userId}` | Previous page button | +| `inv_next_{userId}` | Next page button | +| `inv_back_{userId}` | Back to list from detail | +| `inv_use_{userId}` | Use item button | +| `inv_discard_{userId}` | Discard item button | +| `inv_discard_confirm_{userId}` | Confirm discard | +| `inv_discard_cancel_{userId}` | Cancel discard | + +## File Changes + +### Modified + +- **`shared/lib/rarity.ts`** โ€” Add `squareEmoji` field to `RARITY_CONFIG` entries for C, R, SR, SSR. +- **`bot/commands/inventory/inventory.ts`** โ€” Rewrite to CV2 with pagination collector. Add `view` subcommand with autocomplete. Command setup and collector logic live here. +- **`bot/modules/inventory/inventory.view.ts`** โ€” Replace `getInventoryEmbed` with `getInventoryListMessage` (builds the paginated CV2 list) and add `getItemDetailMessage` (builds the detail CV2 view). `getLootboxResultMessage` is untouched. + +### New + +- **`bot/modules/inventory/inventory.interaction.ts`** โ€” Handles all inventory interaction routing: select menu item selection, pagination buttons, back navigation, use item, discard + confirmation flow. + +### Unchanged + +- `shared/modules/inventory/inventory.service.ts` โ€” Already provides `getInventory`, `useItem`, `removeItem`, `getAutocompleteItems`. +- Database schema โ€” All required fields (`iconUrl`, `imageUrl`, `description`, `rarity`, `type`, `price`) already exist on the items table. + +## Pagination Details + +- **Items per page:** 5 +- **Page calculation:** `totalPages = Math.ceil(items.length / 5)` +- **Page clamping:** `safePage = Math.min(page, totalPages - 1)` to handle items being consumed while browsing +- **Collector timeout:** 2 minutes idle, matching the quest system pattern +- **On timeout:** Edit message to disable all buttons and the select menu