Wardrobe V2 initial proof-of-concept
This commit is contained in:
parent
4e2c99d4dd
commit
276cc1b5ea
5 changed files with 212 additions and 1 deletions
6
app/assets/javascripts/outfits/new_v2.js
Normal file
6
app/assets/javascripts/outfits/new_v2.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
// Wardrobe v2 - Simple Rails+Turbo outfit editor
|
||||
//
|
||||
// This page uses Turbo Frames for instant updates when changing species/color.
|
||||
// The outfit_viewer Web Component handles the pet rendering.
|
||||
|
||||
console.log("Wardrobe v2 loaded!");
|
||||
106
app/assets/stylesheets/outfits/new_v2.sass
Normal file
106
app/assets/stylesheets/outfits/new_v2.sass
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
body.wardrobe-v2
|
||||
margin: 0
|
||||
padding: 0
|
||||
height: 100vh
|
||||
overflow: hidden
|
||||
font-family: sans-serif
|
||||
|
||||
.wardrobe-container
|
||||
display: flex
|
||||
height: 100vh
|
||||
background: #000
|
||||
|
||||
@media (max-width: 800px)
|
||||
flex-direction: column
|
||||
|
||||
.outfit-preview-section
|
||||
flex: 1
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
background: #000
|
||||
position: relative
|
||||
min-height: 400px
|
||||
|
||||
outfit-viewer
|
||||
width: 100%
|
||||
height: 100%
|
||||
|
||||
.no-preview-message
|
||||
color: white
|
||||
text-align: center
|
||||
padding: 2rem
|
||||
font-size: 1.2rem
|
||||
|
||||
.outfit-controls-section
|
||||
width: 400px
|
||||
background: #fff
|
||||
padding: 2rem
|
||||
overflow-y: auto
|
||||
box-shadow: -2px 0 10px rgba(0, 0, 0, 0.3)
|
||||
|
||||
@media (max-width: 800px)
|
||||
width: 100%
|
||||
max-height: 40vh
|
||||
|
||||
h1
|
||||
margin-top: 0
|
||||
font-size: 1.75rem
|
||||
color: #448844
|
||||
|
||||
h2
|
||||
font-size: 1.25rem
|
||||
color: #448844
|
||||
margin-top: 2rem
|
||||
|
||||
.species-color-picker
|
||||
margin: 1.5rem 0
|
||||
|
||||
.form-group
|
||||
margin-bottom: 1rem
|
||||
|
||||
label
|
||||
display: block
|
||||
font-weight: bold
|
||||
margin-bottom: 0.5rem
|
||||
color: #333
|
||||
|
||||
select
|
||||
width: 100%
|
||||
padding: 0.5rem
|
||||
font-size: 1rem
|
||||
border: 1px solid #ccc
|
||||
border-radius: 4px
|
||||
font-family: inherit
|
||||
|
||||
&:focus
|
||||
outline: none
|
||||
border-color: #448844
|
||||
|
||||
.current-selection
|
||||
padding: 1rem
|
||||
background: #f0f0f0
|
||||
border-radius: 4px
|
||||
margin: 1rem 0
|
||||
|
||||
p
|
||||
margin: 0
|
||||
color: #666
|
||||
|
||||
strong
|
||||
color: #000
|
||||
|
||||
.worn-items
|
||||
margin-top: 2rem
|
||||
|
||||
ul
|
||||
list-style: none
|
||||
padding: 0
|
||||
margin: 0.5rem 0
|
||||
|
||||
li
|
||||
padding: 0.5rem
|
||||
background: #f9f9f9
|
||||
margin-bottom: 0.5rem
|
||||
border-radius: 4px
|
||||
color: #333
|
||||
|
|
@ -68,7 +68,7 @@ class OutfitsController < ApplicationController
|
|||
end
|
||||
|
||||
@species_count = Species.count
|
||||
|
||||
|
||||
@latest_contribution = Contribution.recent.first
|
||||
Contribution.preload_contributeds_and_parents([@latest_contribution].compact)
|
||||
|
||||
|
|
@ -77,6 +77,36 @@ class OutfitsController < ApplicationController
|
|||
@campaign = Fundraising::Campaign.current rescue nil
|
||||
end
|
||||
|
||||
def new_v2
|
||||
@colors = Color.alphabetical
|
||||
@species = Species.alphabetical
|
||||
|
||||
# Get selected species and color from params, or default to Blue Acara
|
||||
species_id = params[:species] || Species.find_by_name("Acara")&.id
|
||||
color_id = params[:color] || Color.find_by_name("Blue")&.id
|
||||
|
||||
# Find the pet type (species+color combination)
|
||||
@selected_species = Species.find_by(id: species_id)
|
||||
@selected_color = Color.find_by(id: color_id)
|
||||
@pet_type = PetType.find_by(species_id: species_id, color_id: color_id) if @selected_species && @selected_color
|
||||
|
||||
# Load items from the objects[] parameter
|
||||
item_ids = params[:objects] || []
|
||||
items = Item.where(id: item_ids)
|
||||
|
||||
# Build the outfit
|
||||
@outfit = Outfit.new(
|
||||
pet_state: @pet_type&.canonical_pet_state,
|
||||
worn_items: items,
|
||||
)
|
||||
|
||||
# Preload the manifests for all visible layers, so they load efficiently
|
||||
# in parallel rather than sequentially when rendering
|
||||
SwfAsset.preload_manifests(@outfit.visible_layers) if @outfit.pet_state
|
||||
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def show
|
||||
@outfit = Outfit.find(params[:id])
|
||||
|
||||
|
|
|
|||
68
app/views/outfits/new_v2.html.haml
Normal file
68
app/views/outfits/new_v2.html.haml
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
- title "Wardrobe v2"
|
||||
|
||||
!!! 5
|
||||
%html
|
||||
%head
|
||||
%meta{charset: 'utf-8'}
|
||||
%meta{name: 'viewport', content: 'width=device-width, initial-scale=1'}
|
||||
%title= yield :title
|
||||
%link{href: image_path('favicon.png'), rel: 'icon'}
|
||||
= stylesheet_link_tag "application/hanger-spinner"
|
||||
= stylesheet_link_tag "application/outfit-viewer"
|
||||
= page_stylesheet_link_tag "outfits/new_v2"
|
||||
= csrf_meta_tags
|
||||
= javascript_include_tag "application", async: true
|
||||
= javascript_include_tag "idiomorph", async: true
|
||||
= javascript_include_tag "outfit-viewer", async: true
|
||||
= javascript_include_tag "outfits/new_v2", async: true
|
||||
%body.wardrobe-v2
|
||||
= turbo_frame_tag "outfit-editor" do
|
||||
.wardrobe-container
|
||||
.outfit-preview-section
|
||||
- if @outfit.pet_state
|
||||
= outfit_viewer @outfit
|
||||
- elsif @pet_type.nil?
|
||||
.no-preview-message
|
||||
%p
|
||||
We haven't seen this kind of pet before! Try a different species/color
|
||||
combination.
|
||||
- else
|
||||
.no-preview-message
|
||||
%p Loading...
|
||||
|
||||
.outfit-controls-section
|
||||
%h1 Customize your pet
|
||||
|
||||
.species-color-picker
|
||||
= form_with url: wardrobe_v2_path, method: :get do |f|
|
||||
.form-group
|
||||
= label_tag :species, "Species:"
|
||||
= select_tag :species,
|
||||
options_from_collection_for_select(@species, "id", "human_name",
|
||||
@selected_species&.id),
|
||||
onchange: "this.form.requestSubmit()"
|
||||
|
||||
.form-group
|
||||
= label_tag :color, "Color:"
|
||||
= select_tag :color,
|
||||
options_from_collection_for_select(@colors, "id", "human_name",
|
||||
@selected_color&.id),
|
||||
onchange: "this.form.requestSubmit()"
|
||||
|
||||
-# Preserve item IDs in the URL
|
||||
- if params[:objects].present?
|
||||
- params[:objects].each do |item_id|
|
||||
= hidden_field_tag "objects[]", item_id
|
||||
|
||||
- if @outfit.pet_state
|
||||
.current-selection
|
||||
%p
|
||||
Currently showing:
|
||||
%strong= "#{@selected_color.human_name} #{@selected_species.human_name}"
|
||||
|
||||
- if @outfit.worn_items.any?
|
||||
.worn-items
|
||||
%h2 Items (#{@outfit.worn_items.size})
|
||||
%ul
|
||||
- @outfit.worn_items.each do |item|
|
||||
%li= item.name
|
||||
|
|
@ -10,6 +10,7 @@ OpenneoImpressItems::Application.routes.draw do
|
|||
# TODO: It's a bit silly that outfits/new points to outfits#edit.
|
||||
# Should we refactor the controller/view structure here?
|
||||
get '/outfits/new', to: 'outfits#edit', as: :wardrobe
|
||||
get '/outfits/new/v2', to: 'outfits#new_v2', as: :wardrobe_v2
|
||||
get '/wardrobe' => redirect('/outfits/new')
|
||||
get '/start/:color_name/:species_name' => 'outfits#start'
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue