diff --git a/app/furniture/marketplace/cart.rb b/app/furniture/marketplace/cart.rb
index bba801f96..9db6df934 100644
--- a/app/furniture/marketplace/cart.rb
+++ b/app/furniture/marketplace/cart.rb
@@ -17,6 +17,7 @@ class Cart < Record
# this feels like it is starting to want to be it's own model...
has_encrypted :delivery_address
+ attribute :delivery_window, ::Marketplace::Delivery::WindowType.new
has_encrypted :contact_phone_number
has_encrypted :contact_email
@@ -33,15 +34,6 @@ def delivery
@delivery ||= becomes(Delivery)
end
- def delivery_window
- return marketplace.delivery_window if marketplace&.delivery_window.present?
- return nil if super.blank?
-
- DateTime.parse(super) || 48.hours.from_now
- rescue Date::Error => _e
- 48.hours.from_now
- end
-
def delivery_fee
return marketplace.delivery_fee if delivery_address.present?
diff --git a/app/furniture/marketplace/cart/deliveries/_form.html.erb b/app/furniture/marketplace/cart/deliveries/_form.html.erb
index 0ba4629a8..192ddcbd0 100644
--- a/app/furniture/marketplace/cart/deliveries/_form.html.erb
+++ b/app/furniture/marketplace/cart/deliveries/_form.html.erb
@@ -1,12 +1,7 @@
<%= form_with model: delivery.location do |delivery_form| %>
<%= render "text_field", attribute: :delivery_address, form: delivery_form %>
-
- <%- if delivery.marketplace.delivery_window.present? %>
- <%= render "text_field", attribute: :delivery_window, form: delivery_form, disabled?: true %>
- <%- else %>
- <%= render "datetime_field", attribute: :delivery_window, form: delivery_form %>
- <%- end %>
+ <%= render "window_field", attribute: :window, form: delivery_form %>
<%= render "email_field", attribute: :contact_email, form: delivery_form %>
<%= render "text_field", attribute: :contact_phone_number, form: delivery_form %>
<%= delivery_form.submit %>
diff --git a/app/furniture/marketplace/cart/deliveries/_window_field.html.erb b/app/furniture/marketplace/cart/deliveries/_window_field.html.erb
new file mode 100644
index 000000000..9c524dfb2
--- /dev/null
+++ b/app/furniture/marketplace/cart/deliveries/_window_field.html.erb
@@ -0,0 +1,9 @@
+<%- delivery = form.object%>
+<%- disabled = delivery.marketplace.delivery_window.present? %>
+<%- window = form.object.send(attribute) %>
+
+<%- if window.value.is_a?(DateTime) || delivery.marketplace.delivery_window.blank? %>
+ <%= render "datetime_field", attribute: attribute, form: form, disabled?: disabled %>
+<%- else %>
+ <%= render "text_field", attribute: attribute, form: form, disabled?: disabled %>
+<%- end %>
diff --git a/app/furniture/marketplace/cart/delivery.rb b/app/furniture/marketplace/cart/delivery.rb
index 34e2a2392..31a5f9a36 100644
--- a/app/furniture/marketplace/cart/delivery.rb
+++ b/app/furniture/marketplace/cart/delivery.rb
@@ -3,6 +3,7 @@ class Cart
class Delivery < Cart
extend StripsNamespaceFromModelName
location(routed_as: :resource, parent: :cart)
+ attribute :delivery_window, ::Marketplace::Delivery::WindowType.new
validates :contact_email, presence: true
validates :contact_phone_number, presence: true
diff --git a/app/furniture/marketplace/carts/_cart.html.erb b/app/furniture/marketplace/carts/_cart.html.erb
index 7d8320bc4..c4f263bdd 100644
--- a/app/furniture/marketplace/carts/_cart.html.erb
+++ b/app/furniture/marketplace/carts/_cart.html.erb
@@ -29,7 +29,7 @@
Orders placed by <%= cart.marketplace.order_by %>
are delivered on <%= cart.marketplace.delivery_window %>
<%- elsif cart.delivery_window.present? %>
- Place orders <%= cart.marketplace.order_by %> to ensure an on-time delivery for <%= l(cart.delivery_window, format: :day_month_date_hour_minute) %>
+ Place orders <%= cart.marketplace.order_by %> to ensure an on-time delivery for <%= render(cart.delivery_window) %>
<%= render Marketplace::Cart::Delivery::EditButtonComponent.new(cart.delivery) %>
<%- end %>
diff --git a/app/furniture/marketplace/delivery.rb b/app/furniture/marketplace/delivery.rb
new file mode 100644
index 000000000..e302e6f78
--- /dev/null
+++ b/app/furniture/marketplace/delivery.rb
@@ -0,0 +1,5 @@
+class Marketplace
+ class Delivery < Order
+ attribute :delivery_window, ::Marketplace::Delivery::WindowType.new
+ end
+end
diff --git a/app/furniture/marketplace/delivery/window.rb b/app/furniture/marketplace/delivery/window.rb
new file mode 100644
index 000000000..24f1596fa
--- /dev/null
+++ b/app/furniture/marketplace/delivery/window.rb
@@ -0,0 +1,21 @@
+class Marketplace
+ class Delivery
+ class Window < Model
+ attr_writer :value
+
+ def value
+ return nil if @value.blank?
+
+ DateTime.iso8601(@value)
+ rescue Date::Error => _e
+ @value
+ end
+
+ delegate :strftime, to: :value
+
+ def eql?(other)
+ value.eql?(other.value)
+ end
+ end
+ end
+end
diff --git a/app/furniture/marketplace/delivery/window_type.rb b/app/furniture/marketplace/delivery/window_type.rb
new file mode 100644
index 000000000..129ff3613
--- /dev/null
+++ b/app/furniture/marketplace/delivery/window_type.rb
@@ -0,0 +1,13 @@
+class Marketplace
+ class Delivery
+ class WindowType < ActiveRecord::Type::Value
+ def deserialize(value)
+ Window.new(value: value)
+ end
+ end
+
+ def cast(value)
+ Window.value(value: value)
+ end
+ end
+end
diff --git a/app/furniture/marketplace/delivery/windows/_window.html.erb b/app/furniture/marketplace/delivery/windows/_window.html.erb
new file mode 100644
index 000000000..3e292cb85
--- /dev/null
+++ b/app/furniture/marketplace/delivery/windows/_window.html.erb
@@ -0,0 +1,5 @@
+<%- if window.value.is_a?(DateTime) %>
+ <%= l(window.value, format: :day_month_date_hour_minute) %>
+<%- else %>
+ <%= window.value %>
+<%- end %>
diff --git a/app/furniture/marketplace/order.rb b/app/furniture/marketplace/order.rb
index b36c28aaa..370d14206 100644
--- a/app/furniture/marketplace/order.rb
+++ b/app/furniture/marketplace/order.rb
@@ -12,6 +12,7 @@ class Order < Record
has_many :products, through: :ordered_products, inverse_of: :orders
has_encrypted :delivery_address
+ attribute :delivery_window, Delivery::WindowType.new
has_encrypted :contact_phone_number
has_encrypted :contact_email
@@ -28,6 +29,10 @@ def tax_total
ordered_products.sum(0, &:tax_amount)
end
+ def delivery
+ becomes(Delivery)
+ end
+
delegate :delivery_fee, to: :marketplace
def marketplace_name
diff --git a/app/furniture/marketplace/order/email_receipt_component.html.erb b/app/furniture/marketplace/order/email_receipt_component.html.erb
index c28a3acb7..871ac214e 100644
--- a/app/furniture/marketplace/order/email_receipt_component.html.erb
+++ b/app/furniture/marketplace/order/email_receipt_component.html.erb
@@ -49,7 +49,7 @@
Delivery Details |
Delivery Schedule: |
- <%= order.delivery_window %> |
+ <%= render(order.delivery.window) %> |
Buyer Email: |
diff --git a/app/views/application/_datetime_field.html.erb b/app/views/application/_datetime_field.html.erb
index 81583d9e5..fd69f7d66 100644
--- a/app/views/application/_datetime_field.html.erb
+++ b/app/views/application/_datetime_field.html.erb
@@ -1,5 +1,6 @@
+<%- disabled = local_assigns.fetch(:disabled?, false)%>
<%= form.label attribute %>
- <%= form.datetime_field attribute %>
+ <%= form.datetime_field attribute, disabled: disabled %>
<%= render partial: "error", locals: { model: form.object, attribute: attribute } %>
diff --git a/spec/furniture/marketplace/delivery/window_spec.rb b/spec/furniture/marketplace/delivery/window_spec.rb
new file mode 100644
index 000000000..6ba5645e5
--- /dev/null
+++ b/spec/furniture/marketplace/delivery/window_spec.rb
@@ -0,0 +1,27 @@
+require "rails_helper"
+
+RSpec.describe Marketplace::Delivery::Window do
+ subject(:window) { described_class.new(value: value) }
+
+ describe "#value" do
+ subject(:deserialize) { window.value }
+
+ context "when the value is blank" do
+ let(:value) { "" }
+
+ it { is_expected.to be_nil }
+ end
+
+ context "when the value is an iso8601 String" do
+ let(:value) { DateTime.parse("2023-01-01 3:00pm").iso8601 }
+
+ it { is_expected.to eql(DateTime.parse("2023-01-01 3:00pm")) }
+ end
+
+ context "when the value is a plain string" do
+ let(:value) { "This Evening" }
+
+ it { is_expected.to eql(value) }
+ end
+ end
+end
diff --git a/spec/furniture/marketplace/delivery/window_type_spec.rb b/spec/furniture/marketplace/delivery/window_type_spec.rb
new file mode 100644
index 000000000..330f5337b
--- /dev/null
+++ b/spec/furniture/marketplace/delivery/window_type_spec.rb
@@ -0,0 +1,11 @@
+require "rails_helper"
+
+RSpec.describe Marketplace::Delivery::WindowType do
+ subject(:type) { described_class.new }
+
+ describe "#deserialize" do
+ subject(:deserialize) { type.deserialize("words") }
+
+ it { is_expected.to eql(Marketplace::Delivery::Window.new(value: "words")) }
+ end
+end