From cd57264cba70f706c2cbb796ec8555117ce91044 Mon Sep 17 00:00:00 2001 From: Rainer Dema Date: Mon, 30 Oct 2023 19:48:16 +0100 Subject: [PATCH 1/3] Add CountriesController to fetch states for address form --- .../solidus_admin/countries_controller.rb | 12 ++++++++++++ admin/config/routes.rb | 5 +++++ 2 files changed, 17 insertions(+) create mode 100644 admin/app/controllers/solidus_admin/countries_controller.rb diff --git a/admin/app/controllers/solidus_admin/countries_controller.rb b/admin/app/controllers/solidus_admin/countries_controller.rb new file mode 100644 index 00000000000..ddc842d9ef0 --- /dev/null +++ b/admin/app/controllers/solidus_admin/countries_controller.rb @@ -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 diff --git a/admin/config/routes.rb b/admin/config/routes.rb index f40cb228d22..f8d2c3b78f7 100644 --- a/admin/config/routes.rb +++ b/admin/config/routes.rb @@ -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] From cd87886069c1083406ff114fb8b282953b3b9d98 Mon Sep 17 00:00:00 2001 From: Rainer Dema Date: Mon, 30 Oct 2023 19:35:37 +0100 Subject: [PATCH 2/3] Add `ui/forms/address` component --- .../ui/forms/address/component.html.erb | 33 +++++++++++++++++++ .../ui/forms/address/component.js | 33 +++++++++++++++++++ .../ui/forms/address/component.rb | 8 +++++ .../ui/forms/address/component_preview.rb | 19 +++++++++++ .../component_preview/overview.html.erb | 3 ++ .../ui/forms/address/component_spec.rb | 9 +++++ 6 files changed, 105 insertions(+) create mode 100644 admin/app/components/solidus_admin/ui/forms/address/component.html.erb create mode 100644 admin/app/components/solidus_admin/ui/forms/address/component.js create mode 100644 admin/app/components/solidus_admin/ui/forms/address/component.rb create mode 100644 admin/spec/components/previews/solidus_admin/ui/forms/address/component_preview.rb create mode 100644 admin/spec/components/previews/solidus_admin/ui/forms/address/component_preview/overview.html.erb create mode 100644 admin/spec/components/solidus_admin/ui/forms/address/component_spec.rb diff --git a/admin/app/components/solidus_admin/ui/forms/address/component.html.erb b/admin/app/components/solidus_admin/ui/forms/address/component.html.erb new file mode 100644 index 00000000000..f13f88284cf --- /dev/null +++ b/admin/app/components/solidus_admin/ui/forms/address/component.html.erb @@ -0,0 +1,33 @@ +
+> +
+ <%= 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) %> +
+ <%= render component("ui/forms/field").text_field(@form, :city, class: "flex-1") %> + <%= render component("ui/forms/field").text_field(@form, :zipcode, class: "flex-1") %> +
+ + <%= 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) %> +
+
diff --git a/admin/app/components/solidus_admin/ui/forms/address/component.js b/admin/app/components/solidus_admin/ui/forms/address/component.js new file mode 100644 index 00000000000..87a5948a7b4 --- /dev/null +++ b/admin/app/components/solidus_admin/ui/forms/address/component.js @@ -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) + }) + } +} diff --git a/admin/app/components/solidus_admin/ui/forms/address/component.rb b/admin/app/components/solidus_admin/ui/forms/address/component.rb new file mode 100644 index 00000000000..37c85cbf4d0 --- /dev/null +++ b/admin/app/components/solidus_admin/ui/forms/address/component.rb @@ -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 diff --git a/admin/spec/components/previews/solidus_admin/ui/forms/address/component_preview.rb b/admin/spec/components/previews/solidus_admin/ui/forms/address/component_preview.rb new file mode 100644 index 00000000000..e3bd6a00526 --- /dev/null +++ b/admin/spec/components/previews/solidus_admin/ui/forms/address/component_preview.rb @@ -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 diff --git a/admin/spec/components/previews/solidus_admin/ui/forms/address/component_preview/overview.html.erb b/admin/spec/components/previews/solidus_admin/ui/forms/address/component_preview/overview.html.erb new file mode 100644 index 00000000000..8068d4ec9b7 --- /dev/null +++ b/admin/spec/components/previews/solidus_admin/ui/forms/address/component_preview/overview.html.erb @@ -0,0 +1,3 @@ +<%= form_for Spree::Address.new, url: '#' do |f| %> + <%= render current_component.new(form: f, disabled: false) %> +<% end %> diff --git a/admin/spec/components/solidus_admin/ui/forms/address/component_spec.rb b/admin/spec/components/solidus_admin/ui/forms/address/component_spec.rb new file mode 100644 index 00000000000..ad96467e467 --- /dev/null +++ b/admin/spec/components/solidus_admin/ui/forms/address/component_spec.rb @@ -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 From 38fb96ae359916a87c19d9c805eecc7c92a79ff4 Mon Sep 17 00:00:00 2001 From: Rainer Dema Date: Mon, 30 Oct 2023 19:52:04 +0100 Subject: [PATCH 3/3] Refactor styling for select tag in `ui/forms/input` component Modified input component styling to prevent select elements from appearing as readonly by default. --- .../components/solidus_admin/ui/forms/input/component.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/admin/app/components/solidus_admin/ui/forms/input/component.rb b/admin/app/components/solidus_admin/ui/forms/input/component.rb index 53ac3ae9a91..1c7441eb4ec 100644 --- a/admin/app/components/solidus_admin/ui/forms/input/component.rb +++ b/admin/app/components/solidus_admin/ui/forms/input/component.rb @@ -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] @@ -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,