Add more detailed zone occupy info to simplified item preview page

Adapting what the Impress 2020 UI does, but in Ruby instead!

I feel like this is case is really starting to show the power of doing
this stuff in Rails instead of via an API… we can *really* take
advantage of our models and our handy idioms at all points. This is
just so much less *code* than this feature takes in Node + GraphQL +
React.
This commit is contained in:
Emi Matchu 2024-09-03 12:55:10 -07:00
parent e0f9a27adc
commit 36f8efadbf
5 changed files with 47 additions and 4 deletions

View file

@ -183,3 +183,7 @@ body.items-show
.no-zones
font-style: italic
opacity: .85
.zone-species-info
font-style: italic
text-decoration: underline dotted

View file

@ -89,6 +89,10 @@ class ItemsController < ApplicationController
worn_items: [@item],
)
@preview_error = validate_preview
@all_appearances = @item.appearances
@appearances_by_occupied_zone = @item.appearances_by_occupied_zone.
sort_by { |z, a| z.label }
end
format.gif do

View file

@ -222,6 +222,14 @@ module ItemsHelper
cookies["DTIOutfitViewerIsPlaying"] == "true"
end
def item_zone_partial_fit?(appearances_in_zone, all_appearances)
appearances_in_zone.size < all_appearances.size
end
def item_zone_species_list(appearances_in_zone)
appearances_in_zone.map(&:species).uniq.map(&:human_name).sort.join(", ")
end
private
def pet_type_image(pet_type, emotion, size)

View file

@ -276,7 +276,7 @@ class Item < ApplicationRecord
end
@restricted_zone_ids
end
def occupied_zone_ids
occupied_zones.map(&:id)
end
@ -502,11 +502,16 @@ class Item < ApplicationRecord
Appearance = Struct.new(:item, :body, :swf_assets) do
include ActiveModel::Serializers::JSON
delegate :present?, :empty?, to: :swf_assets
delegate :species, to: :body
def attributes
{item:, body:, swf_assets:}
end
def occupied_zone_ids
swf_assets.map(&:zone_id).uniq.sort
end
def restricted_zone_ids
return [] if empty?
([item] + swf_assets).map(&:restricted_zone_ids).flatten.uniq.sort
@ -550,6 +555,22 @@ class Item < ApplicationRecord
Item.appearances_for([self], target, ...)[id]
end
def appearances_by_occupied_zone_id
{}.tap do |h|
appearances.each do |appearance|
appearance.occupied_zone_ids.each do |zone_id|
h[zone_id] ||= []
h[zone_id] << appearance
end
end
end
end
def appearances_by_occupied_zone
zones_by_id = occupied_zones.to_h { |z| [z.id, z] }
appearances_by_occupied_zone_id.transform_keys { |zid| zones_by_id[zid] }
end
# Given a list of items, return how they look on the given target (either a
# pet type or an alt style).
def self.appearances_for(items, target, swf_asset_includes: [])

View file

@ -36,10 +36,16 @@
.item-zones-info
%section
%h3 Occupies
- if @item.occupied_zones.present?
- if @appearances_by_occupied_zone.present?
%ul
- @item.occupied_zones.sort_by(&:label).each do |zone|
%li= zone.label
- @appearances_by_occupied_zone.each do |zone, appearances_in_zone|
%li
= zone.label
- if item_zone_partial_fit? appearances_in_zone, @all_appearances
%span.zone-species-info{
title: item_zone_species_list(appearances_in_zone)
}
(#{appearances_in_zone.size} species)
- else
%span.no-zones (None)