Skip to content

Commit

Permalink
Merge pull request #5468 from nebulab/rainerd/admin/add-ui-forms-addr…
Browse files Browse the repository at this point in the history
…ess-component

[Admin] Introduce `ui/forms/address` component for order admin checkout
  • Loading branch information
elia authored Oct 31, 2023
2 parents 94c455b + 38fb96a commit e689e66
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<fieldset class="<%= stimulus_id %>"
data-controller="<%= stimulus_id %>"
<%= :disabled if @disabled %>
>
<div class="<%= stimulus_id %>--address-form flex flex-wrap gap-4 pb-4">
<%= render component("ui/forms/field").text_field(@form, :name) %>
<%= render component("ui/forms/field").text_field(@form, :address1) %>
<%= render component("ui/forms/field").text_field(@form, :address2) %>
<div class="flex w-full space-x-4">
<%= render component("ui/forms/field").text_field(@form, :city, class: "flex-1") %>
<%= render component("ui/forms/field").text_field(@form, :zipcode, class: "flex-1") %>
</div>

<%= render component("ui/forms/field").select(
@form,
:country_id,
Spree::Country.all.map { |c| [c.name, c.id] },
value: @form.object.try(:country_id),
"data-#{stimulus_id}-target": "country",
"data-action": "change->#{stimulus_id}#loadStates"
) %>

<%= render component("ui/forms/field").select(
@form,
:state_id,
[],
value: @form.object.try(:state_id),
"data-#{stimulus_id}-target": "state"
) %>

<%= render component("ui/forms/field").text_field(@form, :phone) %>
</div>
</fieldset>
33 changes: 33 additions & 0 deletions admin/app/components/solidus_admin/ui/forms/address/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
static targets = ["country", "state"]

connect() {
this.loadStates()
}

loadStates() {
const countryId = this.countryTarget.value

fetch(`/admin/countries/${countryId}/states`)
.then(response => response.json())
.then(data => {
this.updateStateOptions(data)
})
}

updateStateOptions(data) {
const stateSelect = this.stateTarget

stateSelect.innerHTML = ""

data.forEach(state => {
const option = document.createElement("option")

option.value = state.id
option.innerText = state.name
stateSelect.appendChild(option)
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

class SolidusAdmin::UI::Forms::Address::Component < SolidusAdmin::BaseComponent
def initialize(form:, disabled: false)
@form = form
@disabled = disabled
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,21 @@ def initialize(tag: :input, size: :m, error: nil, **attributes)
raise ArgumentError, "unsupported tag: #{tag}" unless %i[input textarea select].include?(tag)

specialized_classes = []
readonly_classes = "read-only:bg-gray-15 focus:read-only:bg-gray-15 focus:read-only:ring-0
read-only:cursor-not-allowed read-only:focus:border-gray-300
read-only:hover:border-gray-300 read-only:hover:focus:border-gray-300"

case tag
when :input
specialized_classes << "form-input"
specialized_classes << readonly_classes
specialized_classes << HEIGHTS[size]
if attributes[:type] && !TYPES.include?(attributes[:type])
raise ArgumentError, "unsupported type attribute: #{attributes[:type]}"
end
when :textarea
specialized_classes << "form-textarea"
specialized_classes << readonly_classes
specialized_classes << MULTILINE_HEIGHTS[size]
when :select
if attributes[:multiple]
Expand All @@ -71,8 +76,6 @@ def initialize(tag: :input, size: :m, error: nil, **attributes)
disabled:bg-gray-50 disabled:text-gray-500 disabled:placeholder:text-gray-300 disabled:cursor-not-allowed
invalid:border-red-400 invalid:hover:border-red-400 invalid:text-red-400
aria-invalid:border-red-400 aria-invalid:hover:border-red-400 aria-invalid:text-red-400
read-only:bg-gray-15 focus:read-only:bg-gray-15 focus:read-only:ring-0 read-only:cursor-not-allowed
read-only:focus:border-gray-300 read-only:hover:border-gray-300 read-only:hover:focus:border-gray-300
],
SIZES[size],
specialized_classes,
Expand Down
12 changes: 12 additions & 0 deletions admin/app/controllers/solidus_admin/countries_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

module SolidusAdmin
class CountriesController < SolidusAdmin::BaseController
skip_before_action :authorize_solidus_admin_user!

def states
@states = Spree::State.where(country_id: params[:country_id])
render json: @states.select(:id, :name)
end
end
end
5 changes: 5 additions & 0 deletions admin/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
put :activate
end
end

resources :countries, only: [] do
get 'states', to: 'countries#states'
end

resources :orders, only: [:index] do
resources :line_items, only: [:destroy, :create, :update]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

# @component "ui/forms/address"
class SolidusAdmin::UI::Forms::Address::ComponentPreview < ViewComponent::Preview
include SolidusAdmin::Preview

def overview
render_with_template
end

# @param disabled toggle
def playground(disabled: false)
view = ActionView::Base.new(ActionView::LookupContext.new([]), {}, nil)
render component("ui/forms/address").new(
form: ActionView::Helpers::FormBuilder.new(:address, Spree::Address.new, view, {}),
disabled: disabled
)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%= form_for Spree::Address.new, url: '#' do |f| %>
<%= render current_component.new(form: f, disabled: false) %>
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

require "spec_helper"

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

0 comments on commit e689e66

Please sign in to comment.