impress/docs/wardrobe-v2-migration.md

203 lines
11 KiB
Markdown
Raw Normal View History

# Wardrobe V2 Migration Status
This document tracks the status of Wardrobe V2, a ground-up rewrite of the outfit editor using Rails + Turbo, replacing the React + GraphQL system embedded from Impress 2020.
## Goal
Replace the complex React outfit editor (`app/javascript/wardrobe-2020/`) with a simpler Rails/Turbo implementation that:
- Eliminates dependency on Impress 2020's GraphQL API
- Uses progressive enhancement (works without JavaScript)
- Leverages Web Components for interactive features
- Reduces frontend complexity and maintenance burden
- Eventually enables full deprecation of the Impress 2020 service
## Current Status
2026-02-05 18:04:49 -08:00
**Wardrobe V2 is in active development** on the `feature/wardrobe-v2` branch. It's accessible at `/wardrobe/v2` but is not yet linked from the main UI.
2026-02-05 18:04:49 -08:00
### What Works
2026-02-05 18:04:49 -08:00
- **Species/color/pose/style selection**: Full picker UI with visual pose thumbnails, availability indicators, canonical fallback, and alt style picker with tabbed UI
- **Item search**: Text search with auto-filtering by pet compatibility, pagination, add/remove items
- **Item display**: Grouped by zone with multi-zone simplification, incompatible items section, NC/NP badges
- **Outfit rendering**: Uses the shared `<outfit-viewer>` web component
- **Progressive enhancement**: Everything works without JS; web components add auto-submit and smoother interactions
- **Smooth navigation**: Idiomorph DOM morphing reuses `<outfit-viewer>` layers across full-page navigations
2026-02-05 20:47:05 -08:00
- **Outfit saving/loading**: Load saved outfits at `/outfits/:id/v2`, save changes (owner) or save copies (non-owner), editable outfit name, unsaved changes warning
2026-02-05 18:04:49 -08:00
### Key implementation files
2026-02-05 18:04:49 -08:00
Code lives in `app/controllers/wardrobe_controller.rb`, `app/views/wardrobe/`, `app/helpers/wardrobe_helper.rb`, and `app/assets/{stylesheets,javascripts}/wardrobe/`.
## Technical Approach
2026-02-05 18:04:49 -08:00
**Simplicity over polish**: Unlike many webapps, we value the simplicity of the codebase very highly, even at the expense of an ideal user experience. Start with simple solutions, even if the UX is clunky; then we'll iterate up as needed.
2026-02-05 18:04:49 -08:00
**URL as single source of truth**: All outfit state lives in URL params (`species`, `color`, `pose`, `style`, `objects[]`, `q[...]`). Every interaction is a GET request that generates a new URL. No client-side state management. Browser back/forward work naturally.
**Server-side rendering + Web Components**: All HTML is generated server-side. Lightweight web components (`<auto-submit-form>`, `<pose-picker-popover>`, `<tab-panel>`, `<outfit-viewer>`) add interactivity without framework overhead.
2026-02-05 18:04:49 -08:00
**Progressive enhancement**: Submit buttons appear when JS is slow/disabled. Web components enhance forms with auto-submit on change.
2026-02-05 18:04:49 -08:00
## Roadmap
2025-11-02 23:04:59 -08:00
### Phase 1: Core Functionality (MVP) ✅
All core features are implemented:
- **Species/color/pose selection** with visual pose picker, canonical fallback
- **Alt styles** with tabbed Expressions/Styles picker, compatibility filtering
- **Item search** with auto-filtering by pet/style compatibility, pagination
- **Closeted items** (worn vs. closeted vs. absent states, zone-based mutual exclusivity)
- **Outfit saving/loading** (save, save copy, rename, unsaved changes warning)
- **Progressive enhancement** throughout (works without JS, web components add interactivity)
### Phase 2: Detail-Oriented Experience
Additional information, additional search capabilities.
- **Item UX**: Item info links, zone badges, incompatibility tooltips
- **User features**: Closet/ownership/wishlist badges, filter search by owned/wanted
- **Search filters**: Can use the standard search syntax (`is:nc`, `occupies:background`, etc.)
- **Improved pagination**: Prev/next buttons, then a dropdown between them to choose an exact page
### Phase 3: Advanced Features
2026-02-05 18:04:49 -08:00
Feature parity with Wardrobe 2020 where valuable.
- **Preview controls**: Download as PNG, copy link, settings (hi-res mode, archive toggle), HTML5 conversion badge
- **Streamlined try-on**: If you try on a background from search, then change your mind, restore the previous background
- **Outfit auto-saving**: Save outfit changes automatically over time, rather than requiring clicking Save
- **Advanced search UI**: Consider using Wardrobe 2020's autocomplete-based UI, or an advanced search form, or something else
2026-02-05 18:04:49 -08:00
### Phase 4: Migration & Rollout
2026-02-05 18:04:49 -08:00
- Gradual rollout (staff → beta → default)
- Performance measurement and optimization (Turbo Frames for partial updates?)
- Visual polish and design refinement
- Remove wardrobe-2020 code and update Impress 2020 dependencies doc
### Deferred / Maybe Never
2026-02-05 18:04:49 -08:00
- Support mode features (can keep using old wardrobe)
- Known glitches system (complex, low value)
- Appearance version pinning (niche)
- UC pet support (being phased out)
## Open Questions
2026-02-05 18:04:49 -08:00
- Which Wardrobe 2020 features are actually essential vs. nice-to-have? (Need user feedback)
- How to handle the transition period (maintain both? redirect? feature flag?)
## References
2026-02-05 18:04:49 -08:00
- [Impress 2020 Dependencies](./impress-2020-dependencies.md) - What still depends on the Impress 2020 service
- [Customization Architecture](./customization-architecture.md) - Data model deep dive
2026-02-05 18:04:49 -08:00
- Wardrobe 2020 source: `app/javascript/wardrobe-2020/` (the authoritative reference for feature parity comparisons)
2026-02-15 19:53:23 -08:00
---
# Phase 2 Development Plan
## Commit 1: [WV2] Add item info links
Add a link on each item card that opens the item's detail page.
Files to modify:
- app/views/wardrobe/items/_item_card_content.html.haml — Add info link
- app/assets/stylesheets/wardrobe/show.css — Style it
Approach:
- Add link_to to /items/:id with an info icon/emoji, target: "_blank"
- Style: subtle, visible on hover/focus-within, always visible on touch (@media (hover: none))
## Commit 2: [WV2] Add zone badges to search results
Show which zones each item occupies in search result cards.
Files to modify:
- app/views/wardrobe/items/_item_card_content.html.haml — Conditionally render zone badges
- app/views/wardrobe/items/badges/_zones.html.haml (new partial) — Render zone label badges
- app/assets/stylesheets/wardrobe/show.css — Style zone badges (muted, small)
- app/controllers/wardrobe_controller.rb — Load item appearances for search results so zone data is available
Approach:
- Only show zone badges in search results (not outfit items, where the zone group header provides context)
- Pass a local variable (e.g. show_zones: true) from the search results template to item_card_content
- Use Item.appearances_for(items, pet_type) to batch-load appearances for search result items
- Render each item's occupied zone labels as small badges
- Zone data comes from the item's SwfAsset layers for the current pet's body_id
Design decision: Zone badges are omitted from outfit items. When an item occupies multiple zones, the outfit view shows it under multiple zone group headers, which is sufficient context. The rare case
where it could be misleading (e.g., item occupies Background+Foreground but only Background has conflicts) is niche enough to accept for now.
## Commit 3: [WV2] Add ownership and wishlist badges
Show "Own" / "Want" badges when a logged-in user has items in their closet lists.
Files to modify:
- app/controllers/wardrobe_controller.rb — Call assign_closeted_to_items! on all visible items
- app/views/wardrobe/items/badges/_closet.html.haml (new partial) — Own/Want badges
- app/views/wardrobe/items/_item_card_content.html.haml — Include closet badge partial
- app/assets/stylesheets/wardrobe/show.css or app/assets/stylesheets/application/item-badges.css — Badge colors
Approach:
- In controller: current_user.assign_closeted_to_items!(all_items) if user_signed_in? where all_items is the combined set of worn + closeted + search result items
- Badge partial: green "Own" badge if item.owned?, blue "Want" badge if item.wanted?
- No badges when not logged in
Existing code to reuse:
- User#assign_closeted_to_items! (app/models/user.rb:163)
- Badge styling patterns from app/assets/stylesheets/application/item-badges.css
## Commit 4: [WV2] Switch search to text-based filter syntax
Replace the structured search filter approach with from_text(), enabling the full search syntax (is:nc, occupies:background, user:owns, etc.) in a single text field.
Files to modify:
- app/controllers/wardrobe_controller.rb — Replace build_search_filters + from_params with from_text + auto-fit merge
- app/views/wardrobe/show.html.haml — Update search form to single q text param, update placeholder
Approach:
- Change the search form from q[name] to a single q string param
- Controller search logic:
@query = Item::Search::Query.from_text(params[:q], current_user)
results = @query.results
body_id = @outfit.alt_style&.body_id || @outfit.pet_type&.body_id
results = results.merge(Item.fits(body_id)) if body_id
@search_results = results.paginate(page: params[:page], per_page: 30)
- Remove build_search_filters method entirely
- Auto-fit filter applied at controller level via .merge(Item.fits(body_id)), completely separate from user's search text
- Handle Item::Search::Error gracefully (render error message in search results area)
- Update placeholder: "Search items… (try is:nc, occupies:hat, user:owns)"
- Update @search_mode to check params[:q].present? as a string
- Update pagination param from q[page] to page
## Commit 5: [WV2] Improve pagination with page dropdown
Replace will_paginate's view helpers with a custom prev/next + page dropdown control.
Files to modify:
- app/views/wardrobe/items/_search_results.html.haml — Replace will_paginate calls
- app/views/wardrobe/items/_pagination.html.haml (new partial) — Custom pagination UI
- app/assets/stylesheets/wardrobe/show.css — Style pagination bar
Approach:
- Layout: [← Prev] [Page <select> of N] [Next →]
- The <select> is inside an <auto-submit-form> for JS-enhanced page switching
- Prev/Next are regular links (work without JS)
- Without JS: select has a "Go" submit button (hidden when JS active via auto-submit-form:defined)
- Use will_paginate's collection methods (.current_page, .total_pages, .previous_page, .next_page) — keep .paginate() in controller, just replace the view rendering
- Single pagination bar (top of results, remove bottom duplicate)
## Verification
Test at localhost:3000/wardrobe/v2:
1. Info links: Hover over item cards → info link appears → click opens /items/:id in new tab
2. Zone badges: Search for items → results show zone badges (e.g., "Background", "Hat"). Outfit items do NOT show zone badges.
3. Ownership badges: Log in (test/test123) → search → items in closet show "Own"/"Want" badges. Log out → no badges.
4. Search syntax: Type is:nc sword → NC items matching "sword". Try occupies:background, user:owns, -is:pb, "exact phrase"
5. Search errors: Type user:owns when not logged in → friendly error. Type occupies:nonsense → friendly error.
6. Pagination: Search with many results → prev/next + page dropdown → select a page → navigates there