From e703f41f32633341c019825c8285025c50228e84 Mon Sep 17 00:00:00 2001 From: Sreya Saju <68282466+sreyasaju@users.noreply.github.com> Date: Thu, 2 Jul 2026 15:36:44 +0300 Subject: [PATCH 1/2] feat: add 'Made by a teen' banner to shop items - Adds teen_creator_url to ShopItems via migration - Updates ShopItemCardComponent to render the banner - Includes styling and tests Closes #692 --- .../components/_shop-item-card.scss | 28 +++++++++++++++++++ .../shop_item_card_component.html.erb | 8 +++++- app/components/shop_item_card_component.rb | 9 ++++-- app/models/shop_item.rb | 1 + app/views/shop/items/_item_card.html.erb | 3 +- app/views/shop/items/_recently_added.html.erb | 3 +- ...2214_add_teen_creator_url_to_shop_items.rb | 5 ++++ db/schema.rb | 3 +- test/fixtures/shop_items.yml | 1 + test/models/shop_item_test.rb | 1 + 10 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20260701212214_add_teen_creator_url_to_shop_items.rb diff --git a/app/assets/stylesheets/components/_shop-item-card.scss b/app/assets/stylesheets/components/_shop-item-card.scss index a7a6ca28a..e53cdb332 100644 --- a/app/assets/stylesheets/components/_shop-item-card.scss +++ b/app/assets/stylesheets/components/_shop-item-card.scss @@ -66,6 +66,24 @@ var(--color-brand-highlight) transparent; } } + + &--teen-creator { + background: var(--color-brand-orange); + color: var(--color-space-bg); + cursor: pointer; + transition: filter 0.2s ease; + + &::after { + border-color: var(--color-brand-orange) transparent + var(--color-brand-orange) transparent; + } + + &:hover, + &:focus-visible { + filter: brightness(1.05); + outline: none; + } + } } &__star { @@ -279,4 +297,14 @@ display: none; } } + + &--stacked-ribbons { + .shop-item-card__ribbon--teen-creator { + top: 48px; + } + + .shop-item-card__sale-badge { + top: 84px; + } + } } diff --git a/app/components/shop_item_card_component.html.erb b/app/components/shop_item_card_component.html.erb index 1552cdfbc..4403f862a 100644 --- a/app/components/shop_item_card_component.html.erb +++ b/app/components/shop_item_card_component.html.erb @@ -1,4 +1,4 @@ -
New <% end %> + <% if teen_creator? %> + <%= link_to teen_creator_url, target: "_blank", rel: "noopener", class: "shop-item-card__ribbon shop-item-card__ribbon--teen-creator" do %> + Made by a teen! + <% end %> + <% end %> + <% if on_sale %> <%= sale_percentage %>% OFF <% end %> diff --git a/app/components/shop_item_card_component.rb b/app/components/shop_item_card_component.rb index aab0f0b20..09ebe520e 100644 --- a/app/components/shop_item_card_component.rb +++ b/app/components/shop_item_card_component.rb @@ -8,9 +8,9 @@ class ShopItemCardComponent < ViewComponent::Base # surface the popup in place instead of routing to a separate screen. OPEN_VERIFY_MODAL = "document.getElementById('idv-verify-modal')?.showModal()".freeze - attr_reader :item_id, :name, :description, :hours, :price, :image_url, :item_type, :balance, :enabled_regions, :regional_price, :logged_in, :tutorial_spotlight, :cta_mode, :remaining_stock, :limited, :on_sale, :sale_percentage, :original_price, :created_at, :show_bow, :show_time_ago, :purchase_count, :is_new, :enabled_until, :locked_by_achievement, :required_achievement_names, :required_achievement_hints, :mission_locked, :unlocking_mission_names, :wishlisted + attr_reader :item_id, :name, :description, :hours, :price, :image_url, :item_type, :balance, :enabled_regions, :regional_price, :logged_in, :tutorial_spotlight, :cta_mode, :remaining_stock, :limited, :on_sale, :sale_percentage, :original_price, :created_at, :show_bow, :show_time_ago, :purchase_count, :is_new, :enabled_until, :locked_by_achievement, :required_achievement_names, :required_achievement_hints, :mission_locked, :unlocking_mission_names, :wishlisted, :teen_creator_url - def initialize(item_id:, name:, description:, hours:, price:, image_url:, item_type: nil, balance: nil, enabled_regions: [], regional_price: nil, logged_in: true, interactive: true, tutorial_spotlight: false, cta_mode: :order, remaining_stock: nil, limited: false, on_sale: false, sale_percentage: nil, original_price: nil, created_at: nil, show_bow: false, show_time_ago: false, purchase_count: nil, is_new: false, enabled_until: nil, locked_by_achievement: false, required_achievement_names: [], required_achievement_hints: [], mission_locked: false, unlocking_mission_names: [], wishlisted: false) + def initialize(item_id:, name:, description:, hours:, price:, image_url:, item_type: nil, balance: nil, enabled_regions: [], regional_price: nil, logged_in: true, interactive: true, tutorial_spotlight: false, cta_mode: :order, remaining_stock: nil, limited: false, on_sale: false, sale_percentage: nil, original_price: nil, created_at: nil, show_bow: false, show_time_ago: false, purchase_count: nil, is_new: false, enabled_until: nil, locked_by_achievement: false, required_achievement_names: [], required_achievement_hints: [], mission_locked: false, unlocking_mission_names: [], wishlisted: false, teen_creator_url: nil) @item_id = item_id @name = name @description = description @@ -41,6 +41,7 @@ def initialize(item_id:, name:, description:, hours:, price:, image_url:, item_t @mission_locked = mission_locked @unlocking_mission_names = unlocking_mission_names @wishlisted = wishlisted + @teen_creator_url = teen_creator_url end def lock_overlay_html @@ -122,4 +123,8 @@ def cta_price_icon return nil if display_price.to_i.zero? "icons/stardust.png" end + + def teen_creator? + teen_creator_url.present? + end end diff --git a/app/models/shop_item.rb b/app/models/shop_item.rb index ca0b0a9c4..cde109c1e 100644 --- a/app/models/shop_item.rb +++ b/app/models/shop_item.rb @@ -53,6 +53,7 @@ # source_region :string # special :boolean # stock :integer +# teen_creator_url :string # ticket_cost :integer # type :string # unlisted :boolean default(FALSE) diff --git a/app/views/shop/items/_item_card.html.erb b/app/views/shop/items/_item_card.html.erb index 701289dca..e68f917b3 100644 --- a/app/views/shop/items/_item_card.html.erb +++ b/app/views/shop/items/_item_card.html.erb @@ -52,5 +52,6 @@ required_achievement_hints: item_achievement_infos.map(&:description), mission_locked: item_mission_locked, unlocking_mission_names: item_unlocking_missions, - wishlisted: wishlisted_item_ids.include?(item.id) + wishlisted: wishlisted_item_ids.include?(item.id), + teen_creator_url: item.teen_creator_url ) %> diff --git a/app/views/shop/items/_recently_added.html.erb b/app/views/shop/items/_recently_added.html.erb index 5bc15ed18..eddd2d4c3 100644 --- a/app/views/shop/items/_recently_added.html.erb +++ b/app/views/shop/items/_recently_added.html.erb @@ -35,7 +35,8 @@ required_achievement_names: item_achievement_infos.map(&:name), required_achievement_hints: item_achievement_infos.map(&:description), mission_locked: item_mission_locked, - unlocking_mission_names: item_unlocking_missions + unlocking_mission_names: item_unlocking_missions, + teen_creator_url: item.teen_creator_url ) %> <% end %>
diff --git a/db/migrate/20260701212214_add_teen_creator_url_to_shop_items.rb b/db/migrate/20260701212214_add_teen_creator_url_to_shop_items.rb new file mode 100644 index 000000000..57e449280 --- /dev/null +++ b/db/migrate/20260701212214_add_teen_creator_url_to_shop_items.rb @@ -0,0 +1,5 @@ +class AddTeenCreatorUrlToShopItems < ActiveRecord::Migration[8.1] + def change + add_column :shop_items, :teen_creator_url, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index c433799dd..0cc5839bc 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.1].define(version: 2026_06_30_165531) do +ActiveRecord::Schema[8.1].define(version: 2026_07_01_212214) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" enable_extension "vector" @@ -1066,6 +1066,7 @@ t.string "source_region" t.boolean "special" t.integer "stock" + t.string "teen_creator_url" t.integer "ticket_cost" t.string "type" t.boolean "unlisted", default: false diff --git a/test/fixtures/shop_items.yml b/test/fixtures/shop_items.yml index 86b4183ae..9556afd25 100644 --- a/test/fixtures/shop_items.yml +++ b/test/fixtures/shop_items.yml @@ -59,6 +59,7 @@ # source_region :string # special :boolean # stock :integer +# teen_creator_url :string # ticket_cost :integer # type :string # unlisted :boolean default(FALSE) diff --git a/test/models/shop_item_test.rb b/test/models/shop_item_test.rb index f2bc0ea0b..078a00666 100644 --- a/test/models/shop_item_test.rb +++ b/test/models/shop_item_test.rb @@ -53,6 +53,7 @@ # source_region :string # special :boolean # stock :integer +# teen_creator_url :string # ticket_cost :integer # type :string # unlisted :boolean default(FALSE) From 62872f2c9900053246f10d4f2dcc02da2c447fbd Mon Sep 17 00:00:00 2001 From: Sreya Saju <68282466+sreyasaju@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:40:31 +0300 Subject: [PATCH 2/2] style: fix scss formatting with prettier --- app/assets/stylesheets/components/_shop-item-card.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/components/_shop-item-card.scss b/app/assets/stylesheets/components/_shop-item-card.scss index e53cdb332..24d3210d1 100644 --- a/app/assets/stylesheets/components/_shop-item-card.scss +++ b/app/assets/stylesheets/components/_shop-item-card.scss @@ -300,9 +300,9 @@ &--stacked-ribbons { .shop-item-card__ribbon--teen-creator { - top: 48px; + top: 48px; } - + .shop-item-card__sale-badge { top: 84px; }