Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Admin] Add new users admin order history page #5869

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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}"

Check warning on line 12 in admin/app/components/solidus_admin/users/orders/component.rb

View check run for this annotation

Codecov / codecov/patch

admin/app/components/solidus_admin/users/orders/component.rb#L12

Added line #L12 was not covered by tests
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(

Check warning on line 48 in admin/app/components/solidus_admin/users/orders/component.rb

View check run for this annotation

Codecov / codecov/patch

admin/app/components/solidus_admin/users/orders/component.rb#L48

Added line #L48 was not covered by tests
'.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

Check warning on line 89 in admin/app/components/solidus_admin/users/orders/component.rb

View check run for this annotation

Codecov / codecov/patch

admin/app/components/solidus_admin/users/orders/component.rb#L89

Added line #L89 was not covered by tests
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
Loading