Skip to content

Commit

Permalink
Add new users admin order history page
Browse files Browse the repository at this point in the history
This migrates the `users/:id/orders` page from the legacy
soldius_backend to the new solidus_admin.
  • Loading branch information
MadelineCollier committed Oct 10, 2024
1 parent 53f4b28 commit 5dfc7e1
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def tabs
},
{
text: t('.order_history'),
href: spree.orders_admin_user_path(@user),
href: solidus_admin.orders_user_path(@user),
current: false,
},
{
Expand Down
5 changes: 2 additions & 3 deletions admin/app/components/solidus_admin/users/edit/component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ def tabs
},
{
text: t('.order_history'),
href: spree.orders_admin_user_path(@user),
# @todo: update this "current" logic once folded into new admin
current: action_name != "edit",
href: solidus_admin.orders_user_path(@user),
current: action_name == "orders",
},
{
text: t('.items'),
Expand Down
52 changes: 52 additions & 0 deletions admin/app/components/solidus_admin/users/orders/component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<%= 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(".order_history")) do %>
<% if @orders.present? %>
<%= render component('ui/table').new(
id: stimulus_id,
data: {
class: model_class,
rows: rows,
fade: -> { row_fade(_1) },
columns: columns,
url: -> { row_url(_1) },
},
)%>
<% 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("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 %>
<% end %>
<% end %>
<% end %>
145 changes: 145 additions & 0 deletions admin/app/components/solidus_admin/users/orders/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# frozen_string_literal: true

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

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

def form_id
@form_id ||= "#{stimulus_id}--form-#{@user.id}"
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: true,
},
{
text: t('.items'),
href: spree.items_admin_user_path(@user),
current: false,
},
{
text: t('.store_credit'),
href: spree.admin_user_store_credits_path(@user),
current: false,
},
]
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 model_class
Spree::Order
end

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

def rows
@orders
end

def row_fade(_order)
false
end

def columns
[
number_column,
state_column,
date_column,
payment_column,
shipment_column,
total_column,
]
end

def number_column
{
header: :order,
data: ->(order) do
if !row_fade(order)
content_tag :div, order.number, class: 'font-semibold'
else
content_tag :div, order.number
end
end
}
end

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

def date_column
{
header: :date,
data: ->(order) do
content_tag :div, l(order.created_at, format: :short)
end
}
end

def total_column
{
header: :total,
data: ->(order) do
content_tag :div, number_to_currency(order.total)
end
}
end

def payment_column
{
header: :payment,
data: ->(order) do
component('ui/badge').new(name: order.payment_state.humanize, color: order.paid? ? :green : :yellow) if order.payment_state?
end
}
end

def shipment_column
{
header: :shipment,
data: ->(order) do
component('ui/badge').new(name: order.shipment_state.humanize, color: order.shipped? ? :green : :yellow) if order.shipment_state?
end
}
end
end
16 changes: 16 additions & 0 deletions admin/app/components/solidus_admin/users/orders/component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
en:
title: "Users / %{email} / Order History"
account: Account
addresses: Addresses
order_history: Order History
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
no_orders_found: No Orders found.
create_one: Create One
back: Back
16 changes: 15 additions & 1 deletion admin/app/controllers/solidus_admin/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class UsersController < SolidusAdmin::BaseController
include SolidusAdmin::ControllerHelpers::Search
include Spree::Core::ControllerHelpers::StrongParameters

before_action :set_user, only: [:edit, :addresses, :update_addresses]
before_action :set_user, only: [:edit, :addresses, :update_addresses, :orders]

search_scope(:all, default: true)
search_scope(:customers) { _1.left_outer_joins(:role_users).where(role_users: { id: nil }) }
Expand Down Expand Up @@ -50,6 +50,14 @@ def update_addresses
end
end

def orders
set_orders

respond_to do |format|
format.html { render component('users/orders').new(user: @user, orders: @orders) }
end
end

def edit
respond_to do |format|
format.html { render component('users/edit').new(user: @user) }
Expand Down Expand Up @@ -93,6 +101,12 @@ def set_address_from_params
end
end

def set_orders
params[:q] ||= {}
@search = Spree::Order.reverse_chronological.ransack(params[:q].merge(user_id_eq: @user.id))
@orders = @search.result.page(params[:page]).per(Spree::Config[:admin_products_per_page])
end

def authorization_subject
Spree.user_class
end
Expand Down
1 change: 1 addition & 0 deletions admin/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
member do
get :addresses
put :update_addresses
get :orders
end
end

Expand Down
45 changes: 45 additions & 0 deletions admin/spec/features/users_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,49 @@
expect(page).to have_field("user[ship_address_attributes][name]", with: "Elrond")
end
end

context "when viewing a user's order history" do
context "when a user has no orders" do
before do
create(:user, email: "[email protected]")
visit "/admin/users"
find_row("[email protected]").click
click_on "Order History"
end

it "shows the order history page" do
expect(page).to have_content("Users / [email protected] / Order History")
expect(page).to have_content("Lifetime Stats")
expect(page).to have_content("Order History")
expect(page).to be_axe_clean
end

it "shows the appropriate content" do
expect(page).to have_content("No Orders found.")
end
end

context "when a user has ordered before" do
before do
create(:user, :with_orders, email: "[email protected]")
visit "/admin/users"
find_row("[email protected]").click
click_on "Order History"
end

it "shows the order history page" do
expect(page).to have_content("Users / [email protected] / Order History")
expect(page).to have_content("Lifetime Stats")
expect(page).to have_content("Order History")
expect(page).to be_axe_clean
end

it "shows the order history" do
expect(page).to have_content(/R\d+/) # Matches on any order number.
expect(page).to have_content("Shipment")
expect(page).to have_content("Payment")
expect(page).not_to have_content("No Orders found.")
end
end
end
end
10 changes: 10 additions & 0 deletions admin/spec/requests/solidus_admin/users_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@
end
end

describe "GET /orders" do
let!(:order) { create(:order, user: user) }

it "renders the orders template and displays the user's orders" do
get solidus_admin.orders_user_path(user)
expect(response).to have_http_status(:ok)
expect(response.body).to include(order.number)
end
end

describe "DELETE /destroy" do
it "deletes the user and redirects to the index page with a 303 See Other status" do
# Ensure the user exists prior to deletion
Expand Down

0 comments on commit 5dfc7e1

Please sign in to comment.