Skip to content

Commit

Permalink
elia/admin/customer-picker: [wip]
Browse files Browse the repository at this point in the history
  • Loading branch information
elia committed Oct 27, 2023
1 parent f1ee754 commit 848bff8
Show file tree
Hide file tree
Showing 15 changed files with 208 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<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/search_panel').stimulus_id %>:search-><%= stimulus_id %>#search
<%= component('ui/search_panel').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| %>
<% if @order.user || @order.email %>
<div class="p-6 border-t border-gray-100 flex-col gap-2">
<div class="py-2">
<span><%= @customer.name %> <%= tag.em(t('.guest'), class: "italic") unless @customer.id %></span>
<%= render component('ui/button').new(icon: 'edit-line', scheme: :ghost, tag: :a, href: solidus_admin.edit_order_customer_path(@order, @customer), alt: t(".edit")) %>
</div>
<%= link_to_if @customer.id, @customer.email, spree.admin_user_path(@customer), class: 'body-link body-small' %>
<div class="text-gray-500 body-small"><%= t('.orders_count', count: @customer.orders.count) %></div>
</div>
<% end %>
<% end %>
</div>
15 changes: 15 additions & 0 deletions admin/app/components/solidus_admin/orders/customer/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
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())
}

selectResult(event) {
const result = event.detail.resultTarget
result.querySelector("form")?.submit() || Turbo.visit(result.querySelector("a").href)
}
}
19 changes: 19 additions & 0 deletions admin/app/components/solidus_admin/orders/customer/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class SolidusAdmin::Orders::Customer::Component < SolidusAdmin::BaseComponent
def initialize(order:)
@order = order
@customer = order.user || Guest.new(email: order.email)
end

Guest = Struct.new(:email, :id, keyword_init: true) do
def name
email
end

def orders
[]
end
end

end
10 changes: 10 additions & 0 deletions admin/app/components/solidus_admin/orders/customer/component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Add your component translations here.
# Use the translation in the example in your template with `t(".hello")`.
en:
title: "Customer"
search_placeholder: "Search by email or name"
edit: "Change the customer associated to this order"
guest: "Guest"
orders_count:
one: "1 order"
other: "%{count} orders"
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<%= render component('ui/search_panel/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) %>
<div class="flex gap-2 grow items-center">
<%= render component("ui/icon").new(
name: "user-line",
) %>
<div class="flex-col">
<div class="leading-5 text-black body-small-bold"><%= @name %></div>
<div class="leading-5 text-gray-500 body-small"><%= @customer.email %></div>
</div>
</div>
<% end %>
<% else %>
<a class="flex gap-2 grow items-center cursor-pointer" href="<%= solidus_admin.new_order_customer_path(@order) %>">
<%= render component("ui/icon").new(name: "add-box-fill") %>
<div><%= t('.add') %></div>
</a>
<% end %>
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class SolidusAdmin::Orders::Customer::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)&.name if customer
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
en:
add: Create a new customer
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,13 @@
<% end %>
<% end %>

<%= render component('orders/cart').new(order: @order) %>
<%= page_with_sidebar do %>
<%= page_with_sidebar_main do %>
<%= render component('orders/cart').new(order: @order) %>
<% end %>

<%= page_with_sidebar_aside do %>
<%= render component('orders/customer').new(order: @order) %>
<% end %>
<% end %>
<% end %>
14 changes: 14 additions & 0 deletions admin/app/controllers/solidus_admin/customers_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module SolidusAdmin
class CustomersController < SolidusAdmin::BaseController
def edit
end

private

def authorization_subject
Spree::User
end
end
end
34 changes: 34 additions & 0 deletions admin/app/controllers/solidus_admin/orders_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

module SolidusAdmin
class OrdersController < SolidusAdmin::BaseController
include Spree::Core::ControllerHelpers::StrongParameters

def index
orders = Spree::Order
.order(created_at: :desc, id: :desc)
Expand All @@ -26,6 +28,18 @@ def show
end
end

def update
load_order

if @order.update(order_params)
flash[:notice] = t('.success')
else
flash[:error] = t('.error')
end

redirect_to spree.edit_admin_order_path(@order)
end

def variants_for
load_order

Expand Down Expand Up @@ -53,11 +67,31 @@ def variants_for
end
end

def customers_for
load_order

@users = [nil] + Spree.user_class
.where.not(id: @order.user_id)
.order(created_at: :desc, id: :desc)
.ransack(params[:q])
.result(distinct: true)
.includes(:default_user_bill_address, :default_user_ship_address)
.limit(10)

respond_to do |format|
format.html { render component('orders/customer/result').with_collection(@users, order: @order), layout: false }
end
end

private

def load_order
@order = Spree::Order.find_by!(number: params[:id])
authorize! action_name, @order
end

def order_params
params.require(:order).permit(permitted_order_attributes)
end
end
end
3 changes: 3 additions & 0 deletions admin/config/locales/orders.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ en:
solidus_admin:
orders:
title: "Orders"
update:
success: "Order updated successfully"
error: "Order could not be updated"
4 changes: 3 additions & 1 deletion admin/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
put :activate
end
end
resources :orders, only: [:index] do
resources :orders, only: [:index, :update] do
resources :line_items, only: [:destroy, :create, :update]
resource :customer, only: [:new, :edit]

member do
get :cart, to: "orders#show"
get :variants_for
get :customers_for
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

# @component "orders/customer"
class SolidusAdmin::Orders::Customer::ComponentPreview < ViewComponent::Preview
include SolidusAdmin::Preview

def overview
render_with_template
end

# @param order text
def playground(order: "order")
render component("orders/customer").new(order: order)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div class="mb-8">
<h6 class="text-gray-500 mb-3 mt-0">
Scenario 1
</h6>

<%= render current_component.new(order: "order") %>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

require "spec_helper"

RSpec.describe SolidusAdmin::Orders::Customer::Component, type: :component do
it "renders the overview preview" do
render_preview(:overview)
end

# it "renders something useful" do
# render_inline(described_class.new(order: "order"))
#
# expect(page).to have_text "Hello, components!"
# expect(page).to have_css '.value'
# end
end

0 comments on commit 848bff8

Please sign in to comment.