Skip to content

Commit

Permalink
Merge pull request #5462 from solidusio/elia/admin/customer-picker
Browse files Browse the repository at this point in the history
SolidusAdmin customer picker for order
  • Loading branch information
elia authored Nov 13, 2023
2 parents 378ed49 + de59f4a commit 6bbb872
Show file tree
Hide file tree
Showing 34 changed files with 415 additions and 227 deletions.
145 changes: 76 additions & 69 deletions admin/app/components/solidus_admin/orders/cart/component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,77 +3,84 @@
data-controller="<%= stimulus_id %>"
data-<%= stimulus_id %>-products-url-value="<%= solidus_admin.variants_for_order_path(@order) %>"
data-action="
<%= component('ui/search_panel').stimulus_id %>:search-><%= stimulus_id %>#search
<%= component('ui/search_panel').stimulus_id %>:submit-><%= stimulus_id %>#selectResult
<%= component('ui/forms/search').stimulus_id %>:search-><%= stimulus_id %>#search
<%= component('ui/forms/search').stimulus_id %>:submit-><%= stimulus_id %>#selectResult
"
>
<%= render component('ui/search_panel').new(
title: t('.title'),
search_placeholder: t('.search_placeholder'),
id: :order_cart,
) do |panel| %>
<table class="table-auto w-full" <%= :hidden if @order.line_items.empty? %>>
<thead>
<tr class="border-gray-100 border-t">
<th class="text-left body-small-bold text-gray-800 bg-gray-15 px-6 py-3 leading-none">Product</th>
<th class="text-left body-small-bold text-gray-800 bg-gray-15 px-6 py-3 leading-none w-16">Quantity</th>
<th class="text-left body-small-bold text-gray-800 bg-gray-15 px-6 py-3 leading-none w-16">Price</th>
<th class="text-left body-small-bold text-gray-800 bg-gray-15 px-6 py-3 leading-none w-16"><span class="sr-only">Actions</span></th>
</tr>
</thead>
<tbody>
<% @order.line_items.each do |line_item| %>
<tr class="border-gray-100 border-t">
<td class="px-6 py-4">
<div class="flex gap-2 grow">
<% variant = line_item.variant %>
<%= render component("ui/thumbnail").new(
src: (variant.images.first || variant.product.gallery.images.first)&.url(:small),
alt: variant.name
) %>
<div class="flex-col">
<div class="leading-5 text-black body-small-bold"><%= variant.name %></div>
<div class="leading-5 text-gray-500 body-small">
SKU: <%= variant.sku %>
<%= variant.options_text.presence&.prepend("- ") %>
<%= render component('ui/panel').new(title: t('.title')) do |panel| %>
<% panel.with_section do %>
<%= render component('ui/forms/search').new(
placeholder: t('.search_placeholder'),
id: :order_cart,
) %>
<% end %>

<% panel.with_section(wide: true, high: true) do %>
<div class="rounded-b-lg overflow-hidden">
<table class="table-auto w-full" <%= :hidden if @order.line_items.empty? %>>
<thead>
<tr>
<th class="text-left body-small-bold text-gray-800 bg-gray-15 px-6 py-3 leading-none">Product</th>
<th class="text-left body-small-bold text-gray-800 bg-gray-15 px-6 py-3 leading-none w-16">Quantity</th>
<th class="text-left body-small-bold text-gray-800 bg-gray-15 px-6 py-3 leading-none w-16">Price</th>
<th class="text-left body-small-bold text-gray-800 bg-gray-15 px-6 py-3 leading-none w-16"><span class="sr-only">Actions</span></th>
</tr>
</thead>
<tbody>
<% @order.line_items.each do |line_item| %>
<tr class="border-gray-100 border-t">
<td class="px-6 py-4">
<div class="flex gap-2 grow">
<% variant = line_item.variant %>
<%= render component("ui/thumbnail").new(
src: (variant.images.first || variant.product.gallery.images.first)&.url(:small),
alt: variant.name
) %>
<div class="flex-col">
<div class="leading-5 text-black body-small-bold"><%= variant.name %></div>
<div class="leading-5 text-gray-500 body-small">
SKU: <%= variant.sku %>
<%= variant.options_text.presence&.prepend("- ") %>
</div>
</div>
</div>
</div>
</div>
</td>
<td class="px-6 py-4">
<%= form_for(line_item, url: solidus_admin.order_line_item_path(@order, line_item), html: {
"data-controller": "readonly-when-submitting"
}) do |f| %>
<%= render component("ui/forms/input").new(
name: "#{f.object_name}[quantity]",
type: :number,
value: line_item.quantity,
"aria-label": "Quantity",
min: 0,
class: "!w-16 inline-block",
"data-action": "input->#{stimulus_id}#updateLineItem",
) %>
<% render component("ui/button").new(type: :submit, text: "Update", class: "inline-block") %>
<% end %>
</td>
<td class="px-6 py-4">
<span class="text-gray-500 body-small"><%= line_item.single_money.to_html %></span>
</td>
<td class="px-6 py-4 text-right">
<%= form_for(line_item, url: solidus_admin.order_line_item_path(@order, line_item), method: :delete) do |f| %>
<%= render component('ui/button').new(
scheme: :ghost,
size: :s,
title: t("spree.delete"),
icon: 'close-line',
"data-controller": "confirm",
"data-confirm-text-value": t("spree.are_you_sure"),
) %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</td>
<td class="px-6 py-4">
<%= form_for(line_item, url: solidus_admin.order_line_item_path(@order, line_item), html: {
"data-controller": "readonly-when-submitting"
}) do |f| %>
<%= render component("ui/forms/input").new(
name: "#{f.object_name}[quantity]",
type: :number,
value: line_item.quantity,
"aria-label": "Quantity",
min: 0,
class: "!w-16 inline-block",
"data-action": "input->#{stimulus_id}#updateLineItem",
) %>
<% render component("ui/button").new(type: :submit, text: "Update", class: "inline-block") %>
<% end %>
</td>
<td class="px-6 py-4">
<span class="text-gray-500 body-small"><%= line_item.single_money.to_html %></span>
</td>
<td class="px-6 py-4 text-right">
<%= form_for(line_item, url: solidus_admin.order_line_item_path(@order, line_item), method: :delete) do |f| %>
<%= render component('ui/button').new(
scheme: :ghost,
size: :s,
title: t("spree.delete"),
icon: 'close-line',
"data-controller": "confirm",
"data-confirm-text-value": t("spree.are_you_sure"),
) %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% end %>
<% end %>
</div>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%= render component('ui/search_panel/result').new do %>
<%= render component('ui/forms/search/result').new do %>
<%= form_for(@order.line_items.build(variant: @variant), url: solidus_admin.order_line_items_path(@order), method: :post, html: {
"data-controller": "readonly-when-submitting",
class: "flex items-center",
Expand Down
64 changes: 32 additions & 32 deletions admin/app/components/solidus_admin/orders/show/component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -14,60 +14,60 @@
<% end %>

<%= page_with_sidebar_aside do %>
<%= render component('ui/panel').new(title: panel_title_with_more_links(t(".customer"), [
link_to(t(".edit_email"), solidus_admin.order_customer_path(@order), class: "p-2 hover:bg-gray-25 rounded-sm text-black"),
link_to(t(".edit_shipping"), solidus_admin.new_order_ship_address_path(@order), class: "p-2 hover:bg-gray-25 rounded-sm text-black"),
link_to(t(".edit_billing"), solidus_admin.new_order_bill_address_path(@order), class: "p-2 hover:bg-gray-25 rounded-sm text-black"),
link_to(t(".remove_customer"), solidus_admin.order_customer_path(@order), 'data-turbo-method': :delete, class: "p-2 hover:bg-gray-25 rounded-sm text-red-500"),
])) do %>
<div class="flex flex-col -m-6 p-6 gap-6 border-t border-gray-100 mt-0">
<%# CUSTOMER %>
<% if @order.user %>
<div class="flex flex-col gap-2">
<div class="body-small-bold"><%= customer_name(@order.user) || tag.span(t('.no_name'), class: "text-gray-500") %></div>
<%= render component('ui/panel').new do |panel| %>
<% panel.with_menu t(".edit_email"), solidus_admin.order_customer_path(@order) %>
<% panel.with_menu t(".edit_shipping"), solidus_admin.new_order_ship_address_path(@order) %>
<% panel.with_menu t(".edit_billing"), solidus_admin.new_order_bill_address_path(@order) %>
<% panel.with_menu t(".remove_customer"), solidus_admin.order_customer_path(@order), method: :delete, class: "text-red-500" if @order.user %>

<% panel.with_section(class: 'flex flex-col gap-6') do %>
<div class="flex flex-col gap-2">
<span class="body-small-bold"><%= t(".customer") %></span>
<% if @order.user %>
<div class="body-small"><%= customer_name(@order.user) || tag.span(t('.no_name'), class: "text-gray-500") %></div>
<div class="body-small body-link"><%= link_to @order.user.email, spree.admin_user_path(@order.user) %></div>
<div class="body-small text-gray-500"><%= t(".orders_count", count: @order.user.orders.count) %></div>
</div>
<% end %>
<div class="body-small text-gray-500"><%= t(".orders_count", count: @order.user.orders.complete.count) %></div>
<% else %>
<%= render component('orders/show/customer_search').new(order: @order) %>
<% end %>
</div>

<%# EMAIL %>
<% if @order.email %>
<div class="flex flex-col gap-2">
<span class="body-small-bold"><%= t('.order_email') %></span>
<div class="body-small"><%= @order.email %></div>
<div class="flex flex-col gap-2">
<span class="body-small-bold"><%= t('.order_email') %></span>
<div class="body-small">
<% if @order.email? %>
<%= @order.email %>
<% else %>
<%= link_to(t(".add_email"), solidus_admin.order_customer_path(@order), class: "body-link") %>
<% end %>
</div>
<% end %>
</div>

<%# SHIPPING %>
<div class="flex flex-col gap-2">
<span class="body-small-bold"><%= @order.class.human_attribute_name(:ship_address) %></span>
<div class="body-small">
<% if @order.ship_address %>
<%= format_address @order.ship_address %>
<% else %>
<span class="italic text-gray-500"><%= t('.no_shipping_address') %></span>
<%= link_to t(".add_shipping"), solidus_admin.new_order_ship_address_path(@order), class: 'body-link' %>
<% end %>
</div>
</div>

<%# BILLING %>
<div class="flex flex-col gap-2">
<span class="body-small-bold"><%= @order.class.human_attribute_name(:bill_address) %></span>
<div class="body-small">
<% if @order.bill_address %>
<% if @order.bill_address == @order.ship_address %>
<span class="text-gray-500"><%= t('.same_as_shipping') %></span>
<% else %>
<%= format_address @order.bill_address %>
<% end %>
<% if @order.bill_address.blank? %>
<%= link_to t(".add_billing"), solidus_admin.new_order_bill_address_path(@order), class: 'body-link' %>
<% elsif @order.bill_address == @order.ship_address %>
<span class="text-gray-500"><%= t('.same_as_shipping') %></span>
<% else %>
<span class="italic text-gray-500"><%= t('.no_billing_address') %></span>
<%= format_address @order.bill_address %>
<% end %>
</div>
</div>

</div>

<% end %>
<% end %>

<% end %>
Expand Down
21 changes: 0 additions & 21 deletions admin/app/components/solidus_admin/orders/show/component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,6 @@ def format_address(address)
], " ")
end

def panel_title_with_more_links(title, links)
tag.details(
tag.summary(
tag.span(
safe_join([
title,
component("ui/button").new(
icon: "more-line",
scheme: :ghost,
tag: :span,
alt: t("spree.edit"),
class: "cursor-pointer"
).render_in(self),
]),
class: 'flex items-center justify-between text-black',
)
) + tag.div(safe_join(links, " "), class: "body-small absolute border border-gray-100 mt-0.5 right-0 flex min-w-[10rem] flex-col p-2 rounded-sm shadow-lg bg-white z-10"),
class: 'relative',
)
end

def customer_name(user)
(
user.default_user_bill_address ||
Expand Down
5 changes: 3 additions & 2 deletions admin/app/components/solidus_admin/orders/show/component.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ en:
customer: Customer
no_name: No name available
order_email: Order contact email
no_billing_address: No billing address
no_shipping_address: No shipping address
same_as_shipping: Same as shipping address

edit_email: "Edit order email"
add_email: "Add order email"
edit_shipping: "Edit shipping address"
add_shipping: "Add shipping address"
edit_billing: "Edit billing address"
add_billing: "Add billing address"
remove_customer: "Remove customer"

orders_count:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<div
class="w-full relative overflow-visible"
data-controller="<%= stimulus_id %>"
data-<%= stimulus_id %>-customers-url-value="<%= solidus_admin.customers_for_order_path(@order) %>"
data-action="
<%= component('ui/forms/search').stimulus_id %>:search-><%= stimulus_id %>#search
<%= component('ui/forms/search').stimulus_id %>:submit-><%= stimulus_id %>#submit
"
>
<%= render component("ui/forms/search").new(
placeholder: t(".placeholder"),
id: :order_customer
) %>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
static values = { customersUrl: String }

async search({ detail: { query, controller } }) {
controller.resultsValue =
(await (await fetch(`${this.customersUrlValue}?q[name_or_variants_including_master_sku_cont]=${query}`)).text())
}

submit(event) {
event.detail.resultTarget.querySelector('form').submit()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class SolidusAdmin::Orders::Show::CustomerSearch::Component < SolidusAdmin::BaseComponent
def initialize(order:)
@order = order
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
en:
placeholder: "Search customer"
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<%= render component('ui/forms/search/result').new do %>
<% if @customer %>
<%= form_for(@order, url: solidus_admin.order_path(@order), html: {
"data-controller": "readonly-when-submitting",
class: "flex items-center",
}) do |f| %>
<%= hidden_field_tag("#{f.object_name}[user_id]", @customer.id) %>
<button type="submit" class="flex gap-2 grow items-center">
<%= render component("ui/icon").new(name: "user-line", class: 'w-5 h-5 m-2') %>
<div class="flex-col text-left">
<div class="leading-5 text-black body-small-bold"><%= @name %></div>
<div class="leading-5 text-gray-500 body-small"><%= @customer.email %></div>
</div>
</button>
<% end %>
<% end %>
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class SolidusAdmin::Orders::Show::CustomerSearch::Result::Component < SolidusAdmin::BaseComponent
with_collection_parameter :customer

def initialize(order:, customer:)
@order = order
@customer = customer
@name = (customer.default_user_bill_address || customer.default_user_ship_address)&.address&.name if customer
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<%= render component("ui/forms/field").text_field(f, :email) %>
<label class="body-small mt-4 block">
<%= t('.guest_checkout') %>:
<output class="body-small-bold"><%= @order.user ? t('.yes') : t('.no') %></output>
<output class="body-small-bold"><%= @order.user ? t('.no') : t('.yes') %></output>
<%= render component('ui/toggletip').new(text: t('.guest_checkout_tip'), class: "align-middle") %>
</label>
<% end %>
Expand Down
Loading

0 comments on commit 6bbb872

Please sign in to comment.