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
index f13f88284cf..b791c7ad7b8 100644
--- a/admin/app/components/solidus_admin/ui/forms/address/component.html.erb
+++ b/admin/app/components/solidus_admin/ui/forms/address/component.html.erb
@@ -6,9 +6,9 @@
<%= 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").text_field(@form, :city) %>
+ <%= render component("ui/forms/field").text_field(@form, :zipcode) %>
<%= render component("ui/forms/field").select(
diff --git a/admin/app/controllers/solidus_admin/addresses_controller.rb b/admin/app/controllers/solidus_admin/addresses_controller.rb
new file mode 100644
index 00000000000..1b527b86ff5
--- /dev/null
+++ b/admin/app/controllers/solidus_admin/addresses_controller.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module SolidusAdmin
+ class AddressesController < BaseController
+ include Spree::Core::ControllerHelpers::StrongParameters
+
+ before_action :load_order
+ before_action :validate_address_type
+
+ def new
+ address = @order.send("#{address_type}_address")
+ @order.send("build_#{address_type}_address", country_id: default_country_id) if address.nil?
+ address ||= @order.send("#{address_type}_address")
+ address.country_id ||= default_country_id if address.country.nil?
+
+ respond_to do |format|
+ format.html { render component('orders/address').new(order: @order, type: address_type) }
+ end
+ end
+
+ def update
+ if @order.contents.update_cart(order_params)
+ flash[:success] = t('spree.customer_details_updated')
+ redirect_to edit_order_url(@order)
+ else
+ respond_to do |format|
+ format.html { render component('orders/address').new(order: @order, type: address_type) }
+ end
+ end
+ end
+
+ private
+
+ def address_type
+ params[:address_type].presence_in(%w[bill ship])
+ end
+
+ def validate_address_type
+ unless address_type
+ flash[:error] = t('spree.address_type_invalid')
+ redirect_to spree.admin_order_url(@order)
+ end
+ end
+
+ def default_country_id
+ @default_country_id ||= begin
+ country = Spree::Country.default
+ country.id if Spree::Country.available.exists?(id: country.id)
+ end
+ end
+
+ def load_order
+ @order = Spree::Order.find_by!(number: params[:order_id])
+ authorize! action_name, @order
+ end
+
+ def order_params
+ params.require(:order).permit(
+ bill_address_attributes: permitted_address_attributes,
+ ship_address_attributes: permitted_address_attributes
+ )
+ end
+ end
+end
diff --git a/admin/config/routes.rb b/admin/config/routes.rb
index 98db04921c4..a1493f2569a 100644
--- a/admin/config/routes.rb
+++ b/admin/config/routes.rb
@@ -20,6 +20,8 @@
resources :orders, only: [:index, :show, :edit] do
resources :line_items, only: [:destroy, :create, :update]
+ resource :ship_address, only: [:new, :update], controller: "addresses", address_type: "ship"
+ resource :bill_address, only: [:new, :update], controller: "addresses", address_type: "bill"
member do
get :variants_for
diff --git a/admin/spec/components/previews/solidus_admin/orders/address/component_preview.rb b/admin/spec/components/previews/solidus_admin/orders/address/component_preview.rb
new file mode 100644
index 00000000000..d913c5c7bf7
--- /dev/null
+++ b/admin/spec/components/previews/solidus_admin/orders/address/component_preview.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+# @component "orders/address"
+class SolidusAdmin::Orders::Address::ComponentPreview < ViewComponent::Preview
+ include SolidusAdmin::Preview
+
+ def overview
+ render_with_template
+ end
+
+ # @param address text
+ # @param type text
+ def playground(address: "address", type: "type")
+ render component("orders/address").new(address: address, type: type)
+ end
+end
diff --git a/admin/spec/components/previews/solidus_admin/orders/address/component_preview/overview.html.erb b/admin/spec/components/previews/solidus_admin/orders/address/component_preview/overview.html.erb
new file mode 100644
index 00000000000..1a3d5ffadb0
--- /dev/null
+++ b/admin/spec/components/previews/solidus_admin/orders/address/component_preview/overview.html.erb
@@ -0,0 +1,7 @@
+
+
+ Scenario 1
+
+
+ <%= render current_component.new(address: "address", type: "type") %>
+
diff --git a/admin/spec/components/solidus_admin/orders/address/component_spec.rb b/admin/spec/components/solidus_admin/orders/address/component_spec.rb
new file mode 100644
index 00000000000..ab1387decac
--- /dev/null
+++ b/admin/spec/components/solidus_admin/orders/address/component_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe SolidusAdmin::Orders::Address::Component, type: :component do
+ it "renders the overview preview" do
+ render_preview(:overview)
+ end
+
+ # it "renders something useful" do
+ # render_inline(described_class.new(address: "address", type: "type"))
+ #
+ # expect(page).to have_text "Hello, components!"
+ # expect(page).to have_css '.value'
+ # end
+end