Skip to content

Commit

Permalink
Merge pull request #5874 from MadelineCollier/admin-user-items-page
Browse files Browse the repository at this point in the history
[Admin] Add new users admin items page
  • Loading branch information
MadelineCollier authored Oct 17, 2024
2 parents c3fea3e + c26cb64 commit fc2b820
Show file tree
Hide file tree
Showing 24 changed files with 378 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,7 @@
<% end %>
<%= page_with_sidebar_aside do %>
<%= render component("ui/panel").new(title: t("spree.lifetime_stats")) do %>
<%= render component("ui/details_list").new(
items: [
{ label: t("spree.total_sales"), value: @user.display_lifetime_value.to_html },
{ label: t("spree.order_count"), value: @user.order_count.to_i },
{ label: t("spree.average_order_value"), value: @user.display_average_order_value.to_html },
{ label: t("spree.member_since"), value: @user.created_at.to_date },
{ label: t(".last_active"), value: last_login(@user) },
]
) %>
<% end %>
<%= render component("users/stats").new(user: @user) %>
<% end %>
<% end %>
<% end %>
11 changes: 0 additions & 11 deletions admin/app/components/solidus_admin/users/addresses/component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,6 @@ def tabs
]
end

def last_login(user)
return t('.last_login.never') if user.try(:last_sign_in_at).blank?

t(
'.last_login.login_time_ago',
# @note The second `.try` is here for the specs and for setups that use a
# custom User class which may not have this attribute.
last_login_time: time_ago_in_words(user.try(:last_sign_in_at))
).capitalize
end

def bill_address(address, type)
if address.present? && type == "bill"
address
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ en:
items: Items
store_credit: Store Credit
last_active: Last Active
last_login:
login_time_ago: "%{last_login_time} ago"
never: Never
invitation_sent: Invitation sent
create_order_for_user: Create order for this user
update: Update
cancel: Cancel
Expand Down
12 changes: 1 addition & 11 deletions admin/app/components/solidus_admin/users/edit/component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,7 @@
<% end %>
<%= page_with_sidebar_aside do %>
<%= render component("ui/panel").new(title: t("spree.lifetime_stats")) do %>
<%= render component("ui/details_list").new(
items: [
{ label: t("spree.total_sales"), value: @user.display_lifetime_value.to_html },
{ label: t("spree.order_count"), value: @user.order_count.to_i },
{ label: t("spree.average_order_value"), value: @user.display_average_order_value.to_html },
{ label: t("spree.member_since"), value: @user.created_at.to_date },
{ label: t(".last_active"), value: last_login(@user) },
]
) %>
<% end %>
<%= render component("users/stats").new(user: @user) %>
<% end %>
<% end %>
<% end %>
10 changes: 0 additions & 10 deletions admin/app/components/solidus_admin/users/edit/component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,6 @@ def tabs
]
end

def last_login(user)
return t('.last_login.never') if user.try(:last_sign_in_at).blank?

t(
'.last_login.login_time_ago',
# @note The second `.try` is only here for the specs to work.
last_login_time: time_ago_in_words(user.try(:last_sign_in_at))
).capitalize
end

def role_options
Spree::Role.all.map do |role|
{ label: role.name, id: role.id }
Expand Down
4 changes: 0 additions & 4 deletions admin/app/components/solidus_admin/users/edit/component.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ en:
items: Items
store_credit: Store Credit
last_active: Last Active
last_login:
login_time_ago: "%{last_login_time} ago"
never: Never
invitation_sent: Invitation sent
create_order_for_user: Create order for this user
update: Update
cancel: Cancel
Expand Down
18 changes: 2 additions & 16 deletions admin/app/components/solidus_admin/users/index/component.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class SolidusAdmin::Users::Index::Component < SolidusAdmin::UsersAndRoles::Component
include SolidusAdmin::LastLoginHelper

def model_class
Spree.user_class
end
Expand Down Expand Up @@ -93,20 +95,4 @@ def columns
},
]
end

private

# @todo add logic to display "Invitation sent" when the user has not yet
# accepted the invitation and filled out account details. To be implemented
# in conjunction with the invitation logic.
def last_login(user)
return t('.last_login.never') if user.try(:last_sign_in_at).blank?

t(
'.last_login.login_time_ago',
# @note The second `.try` is here for the specs and for setups that use a
# custom User class which may not have this attribute.
last_login_time: time_ago_in_words(user.try(:last_sign_in_at))
).capitalize
end
end
4 changes: 0 additions & 4 deletions admin/app/components/solidus_admin/users/index/component.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,3 @@ en:
status:
active: Active
inactive: Inactive
last_login:
login_time_ago: "%{last_login_time} ago"
never: Never
invitation_sent: Invitation sent
41 changes: 41 additions & 0 deletions admin/app/components/solidus_admin/users/items/component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<%= page do %>
<%= page_header do %>
<%= page_header_back(solidus_admin.users_path) %>
<%= page_header_title(t(".title", email: @user.email)) %>
<%= page_header_actions do %>
<%= render component("ui/button").new(tag: :a, text: t(".create_order_for_user"), href: spree.new_admin_order_path(user_id: @user.id)) %>
<% end %>
<% end %>
<%= page_header do %>
<% tabs.each do |tab| %>
<%= render(component("ui/button").new(tag: :a, scheme: :ghost, text: tab[:text], 'aria-current': tab[:current], href: tab[:href])) %>
<% end %>
<% end %>
<%= page_with_sidebar do %>
<%= page_with_sidebar_main do %>
<%= render component('ui/panel').new(title: t(".items_purchased")) do %>
<% if @items.present? %>
<%= render component('ui/table').new(
id: stimulus_id,
data: {
class: model_class,
rows: rows,
columns: columns,
url: -> { row_url(_1.order) },
},
)%>
<% else %>
<%= t(".no_orders_found") %>
<%= render component("ui/button").new(tag: :a, text: t(".create_one"), href: spree.new_admin_order_path(user_id: @user.id)) %>
<% end %>
<% end %>
<% end %>
<%= page_with_sidebar_aside do %>
<%= render component("users/stats").new(user: @user) %>
<% end %>
<% end %>
<% end %>
170 changes: 170 additions & 0 deletions admin/app/components/solidus_admin/users/items/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# frozen_string_literal: true

class SolidusAdmin::Users::Items::Component < SolidusAdmin::BaseComponent
include SolidusAdmin::Layout::PageHelpers

def initialize(user:, items:)
@user = user
@items = items
end

def tabs
[
{
text: t('.account'),
href: solidus_admin.user_path(@user),
current: false,
},
{
text: t('.addresses'),
href: solidus_admin.addresses_user_path(@user),
current: false,
},
{
text: t('.order_history'),
href: solidus_admin.orders_user_path(@user),
current: false,
},
{
text: t('.items'),
href: solidus_admin.items_user_path(@user),
current: true,
},
{
text: t('.store_credit'),
href: spree.admin_user_store_credits_path(@user),
current: false,
},
]
end

def model_class
Spree::LineItem
end

def row_url(order)
spree.edit_admin_order_path(order)
end

def rows
@items
end

def columns
[
date_column,
image_column,
description_column,
price_column,
quantity_column,
total_column,
state_column,
number_column,
]
end

def date_column
{
col: { class: "w-[8%]" },
header: :date,
data: ->(item) do
content_tag :div, l(item.order.created_at, format: :short), class: "text-sm"
end
}
end

def image_column
{
col: { class: "w-[8%]" },
header: tag.span('aria-label': Spree::Image.model_name.human, role: 'text'),
data: ->(item) do
image = item.variant.gallery.images.first || item.variant.product.gallery.images.first or return

render(
component('ui/thumbnail').new(
src: image.url(:small),
alt: item.product.name
)
)
end
}
end

def description_column
{
col: { class: "w-[24%]" },
header: t(".description_column_header"),
data: ->(item) { item_name_with_variant_and_sku(item) }
}
end

def price_column
{
col: { class: "w-[10%]" },
header: :price,
data: ->(item) do
content_tag :div, item.single_money.to_html
end
}
end

def quantity_column
{
col: { class: "w-[7%]" },
header: :qty,
data: ->(item) do
content_tag :div, item.quantity
end
}
end

def total_column
{
col: { class: "w-[10%]" },
header: t(".total_column_header"),
data: ->(item) do
content_tag :div, item.money.to_html
end
}
end

def state_column
{
col: { class: "w-[15%]" },
header: :state,
data: ->(item) do
color = {
'complete' => :green,
'returned' => :red,
'canceled' => :blue,
'cart' => :graphite_light,
}[item.order.state] || :yellow
component('ui/badge').new(name: item.order.state.humanize, color: color)
end
}
end

def number_column
{
col: { class: "w-[18%]" },
header: t(".number_column_header"),
data: ->(item) do
content_tag :div, item.order.number, class: "font-semibold text-sm"
end
}
end

private

def item_name_with_variant_and_sku(item)
content = []
content << item.product.name
content << "(#{item.variant.options_text})" if item.variant.option_values.any?
content << "<strong>#{t('spree.sku')}:</strong> #{item.variant.sku}" if item.variant.sku.present?

# The `.html_safe` is required for the description to display as desired.
# rubocop:disable Rails/OutputSafety
safe_join([content_tag(:div, content.join("<br>").html_safe, class: "text-sm")])
# rubocop:enable Rails/OutputSafety
end
end
16 changes: 16 additions & 0 deletions admin/app/components/solidus_admin/users/items/component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
en:
title: "Users / %{email} / Items Purchased"
account: Account
addresses: Addresses
order_history: Order History
items: Items
store_credit: Store Credit
last_active: Last Active
create_order_for_user: Create order for this user
items_purchased: Items Purchased
no_orders_found: No Orders found.
create_one: Create One
back: Back
number_column_header: "Order #"
description_column_header: "Description"
total_column_header: "Total"
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,7 @@
<% end %>
<%= page_with_sidebar_aside do %>
<%= render component("ui/panel").new(title: t("spree.lifetime_stats")) do %>
<%= render component("ui/details_list").new(
items: [
{ label: t("spree.total_sales"), value: @user.display_lifetime_value.to_html },
{ label: t("spree.order_count"), value: @user.order_count.to_i },
{ label: t("spree.average_order_value"), value: @user.display_average_order_value.to_html },
{ label: t("spree.member_since"), value: @user.created_at.to_date },
{ label: t(".last_active"), value: last_login(@user) },
]
) %>
<% end %>
<%= render component("users/stats").new(user: @user) %>
<% end %>
<% end %>
<% end %>
Loading

0 comments on commit fc2b820

Please sign in to comment.