diff --git a/admin/app/components/solidus_admin/ui/forms/field/component.rb b/admin/app/components/solidus_admin/ui/forms/field/component.rb
index 352d1d9e58a..f15653d957a 100644
--- a/admin/app/components/solidus_admin/ui/forms/field/component.rb
+++ b/admin/app/components/solidus_admin/ui/forms/field/component.rb
@@ -46,7 +46,7 @@ def self.select(form, method, choices, object: nil, hint: nil, tip: nil, size: :
tag: :select,
choices:,
size:,
- value: object.public_send(method),
+ value: (object.public_send(method) if object.respond_to?(method)),
error: (errors.to_sentence.capitalize if errors),
**attributes,
}
diff --git a/admin/app/components/solidus_admin/users/store_credits/edit_amount/component.html.erb b/admin/app/components/solidus_admin/users/store_credits/edit_amount/component.html.erb
new file mode 100644
index 00000000000..9b4c1454ab1
--- /dev/null
+++ b/admin/app/components/solidus_admin/users/store_credits/edit_amount/component.html.erb
@@ -0,0 +1,33 @@
+ <%= render component("ui/modal").new(title: t(".title")) do |modal| %>
+ <%= form_for @store_credit, url: solidus_admin.update_amount_user_store_credit_path(@user, @store_credit), method: :put, data: { turbo: false }, html: { id: form_id } do |f| %>
+
+ <%= render component("ui/forms/field").text_field(f, :amount, class: "required") %>
+ <%= render component("ui/forms/field").select(
+ f,
+ :store_credit_reason_id,
+ store_credit_reasons_select_options.html_safe,
+ include_blank: t('spree.choose_reason'),
+ html: { required: true }
+ ) %>
+
+ <% if @store_credit.errors.any? %>
+
+
+ <% @store_credit.errors.full_messages.each do |message| %>
+ - <%= message %>
+ <% end %>
+
+
+ <% end %>
+ <%= render component("ui/forms/field").text_field(f, :memo, class: "required") %>
+
+ <% modal.with_actions do %>
+
+ <%= render component("ui/button").new(form: form_id, type: :submit, text: t('.submit')) %>
+ <% end %>
+ <% end %>
+ <% end %>
+<%= render component("users/store_credits/show").new(user: @user, store_credit: @store_credit, events: @store_credit_events) %>
+
diff --git a/admin/app/components/solidus_admin/users/store_credits/edit_amount/component.rb b/admin/app/components/solidus_admin/users/store_credits/edit_amount/component.rb
new file mode 100644
index 00000000000..545444fc79c
--- /dev/null
+++ b/admin/app/components/solidus_admin/users/store_credits/edit_amount/component.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class SolidusAdmin::Users::StoreCredits::EditAmount::Component < SolidusAdmin::BaseComponent
+ def initialize(user:, store_credit:, events:, reasons:)
+ @user = user
+ @store_credit = store_credit
+ @store_credit_events = events
+ @store_credit_reasons = reasons
+ end
+
+ def form_id
+ dom_id(@store_credit, "#{stimulus_id}_edit_store_credit_form")
+ end
+
+ def store_credit_reasons_select_options
+ # Placeholder + Store Credit Reasons
+ "" + options_from_collection_for_select(@store_credit_reasons, :id, :name)
+ end
+end
diff --git a/admin/app/components/solidus_admin/users/store_credits/edit_amount/component.yml b/admin/app/components/solidus_admin/users/store_credits/edit_amount/component.yml
new file mode 100644
index 00000000000..3bfc972f777
--- /dev/null
+++ b/admin/app/components/solidus_admin/users/store_credits/edit_amount/component.yml
@@ -0,0 +1,5 @@
+en:
+ title: Edit Store Credit
+ cancel: Cancel
+ submit: Update Store Credit
+ choose_reason: Choose Reason For Changing Amount
diff --git a/admin/app/components/solidus_admin/users/store_credits/index/component.rb b/admin/app/components/solidus_admin/users/store_credits/index/component.rb
index f3036e4cd50..615a2163eda 100644
--- a/admin/app/components/solidus_admin/users/store_credits/index/component.rb
+++ b/admin/app/components/solidus_admin/users/store_credits/index/component.rb
@@ -47,7 +47,7 @@ def rows
end
def row_url(store_credit)
- spree.admin_user_store_credit_path(@user, store_credit)
+ solidus_admin.user_store_credit_path(@user, store_credit)
end
def columns
diff --git a/admin/app/components/solidus_admin/users/store_credits/show/component.html.erb b/admin/app/components/solidus_admin/users/store_credits/show/component.html.erb
index ca89b32b5fd..9e0882593eb 100644
--- a/admin/app/components/solidus_admin/users/store_credits/show/component.html.erb
+++ b/admin/app/components/solidus_admin/users/store_credits/show/component.html.erb
@@ -2,20 +2,6 @@
<%= page_header do %>
<%= page_header_back(solidus_admin.users_path) %>
<%= page_header_title(t(".title", email: @user.email, amount: @store_credit.display_amount)) %>
-
- <%= page_header_actions do %>
- <%# TODO: can? actions in admin %>
- <%# if @store_credit.editable? && can?(:edit, @store_credit) %>
- <% if @store_credit.editable? %>
- <%= render component("ui/button").new(tag: :a, text: t(".change_amount"), href: spree.edit_amount_admin_user_store_credit_path(@user, @store_credit)) %>
- <% end %>
- <%# TODO: can? actions in admin %>
- <%# if @store_credit.invalidateable? && can?(:invalidate, @store_credit) %>
- <% if @store_credit.invalidateable? %>
- <%= render component("ui/button").new(scheme: :danger, tag: :a, text: t(".invalidate"), href: spree.edit_validity_admin_user_store_credit_path(@user, @store_credit)) %>
- <% end %>
-
- <% end %>
<% end %>
<%= page_header do %>
@@ -26,17 +12,31 @@
<%= page_with_sidebar do %>
<%= page_with_sidebar_main do %>
- <%= render component('ui/panel').new(title: t(".store_credit")) do %>
- <%= render component('ui/details_list').new(
- items: [
- { label: t('.credited'), value: @store_credit.display_amount },
- { label: t('.created_by'), value: @store_credit.created_by_email },
- { label: t('.type'), value: @store_credit.category_name },
- { label: t('.memo'), value: @store_credit.memo }
- ]
- ) %>
- <% end %>
+ <%= render component('ui/panel').new(title: t(".store_credit")) do |panel| %>
+ <% panel.with_section do %>
+ <%= render component('ui/details_list').new(
+ items: [
+ { label: t('.credited'), value: @store_credit.display_amount },
+ { label: t('.created_by'), value: @store_credit.created_by_email },
+ { label: t('.type'), value: @store_credit.category_name },
+ { label: t('.memo'), value: @store_credit.memo }
+ ]
+ ) %>
+ <% end %>
+ <% if @store_credit.editable? || @store_credit.invalidateable? %>
+ <% panel.with_section do %>
+
+ <% if @store_credit.invalidateable? %>
+ <%= render component("ui/button").new(scheme: :danger, tag: :a, "data-action": "click->#{stimulus_id}#confirmDelete", text: t(".invalidate"), href: spree.edit_validity_admin_user_store_credit_path(@user, @store_credit)) %>
+ <% end %>
+ <% if @store_credit.editable? %>
+ <%= render component("ui/button").new(tag: :a, "data-action": "click->#{stimulus_id}#confirmDelete", text: t(".edit"), href: solidus_admin.edit_amount_user_store_credit_path(@user, @store_credit)) %>
+ <% end %>
+
+ <% end %>
+ <% end %>
+ <% end %>
<% if @events.present? %>
<%= t(".store_credit_history") %>
diff --git a/admin/app/components/solidus_admin/users/store_credits/show/component.js b/admin/app/components/solidus_admin/users/store_credits/show/component.js
new file mode 100644
index 00000000000..b6f7437145d
--- /dev/null
+++ b/admin/app/components/solidus_admin/users/store_credits/show/component.js
@@ -0,0 +1,15 @@
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ actionButtonClicked(event) {
+ const url = new URL(event.params.url, "http://dummy.com")
+ const params = new URLSearchParams(url.search)
+ const frameId = params.get('_turbo_frame')
+ const frame = frameId ? { frame: frameId } : {}
+ // remove the custom _turbo_frame param from url search:
+ params.delete('_turbo_frame')
+ url.search = params.toString()
+
+ window.Turbo.visit(url.pathname + url.search, frame)
+ }
+}
diff --git a/admin/app/components/solidus_admin/users/store_credits/show/component.yml b/admin/app/components/solidus_admin/users/store_credits/show/component.yml
index d0a4ec2d378..5da2e914918 100644
--- a/admin/app/components/solidus_admin/users/store_credits/show/component.yml
+++ b/admin/app/components/solidus_admin/users/store_credits/show/component.yml
@@ -7,7 +7,7 @@ en:
store_credit: Store Credit
last_active: Last Active
add_store_credit: Add Store Credit
- change_amount: Change Amount
+ edit: Edit Store Credit
invalidate: Invalidate
store_credit_history: Store Credit History
credited: Credited
diff --git a/admin/app/controllers/solidus_admin/store_credits_controller.rb b/admin/app/controllers/solidus_admin/store_credits_controller.rb
index c7032de4907..0a7265c4675 100644
--- a/admin/app/controllers/solidus_admin/store_credits_controller.rb
+++ b/admin/app/controllers/solidus_admin/store_credits_controller.rb
@@ -3,8 +3,10 @@
module SolidusAdmin
class StoreCreditsController < SolidusAdmin::BaseController
before_action :set_user
- before_action :set_store_credit, only: [:show]
+ before_action :set_store_credit, only: [:show, :edit_amount, :update_amount]
+ before_action :set_store_credit_reasons, only: [:edit_amount, :update_amount]
+ SolidusAdmin::StoreCreditsController
def index
@store_credits = Spree::StoreCredit.where(user_id: @user.id).order(id: :desc)
@@ -18,11 +20,111 @@ def show
respond_to do |format|
format.html { render component("users/store_credits/show").new(user: @user, store_credit: @store_credit, events: @store_credit_events) }
+
+ format.turbo_stream do
+ render turbo_stream: turbo_stream.replace(
+ "store_credit_details", # Target a container ID in your HTML
+ partial: "users/store_credits/show", # Use the appropriate partial
+ locals: { user: @user, store_credit: @store_credit, events: @store_credit_events }
+ )
+ end
+ end
+ end
+
+ def edit_amount
+ @store_credit_events = @store_credit.store_credit_events.chronological
+
+ respond_to do |format|
+ format.html { render component("users/store_credits/edit_amount").new(
+ user: @user,
+ store_credit: @store_credit,
+ events: @store_credit_events,
+ reasons: @store_credit_reasons
+ )}
+ end
+ end
+
+ # def update_amount
+ # binding.pry
+ #
+ # @store_credit_reason = Spree::StoreCreditReason.find_by(id: params[:store_credit_reason_id])
+ # unless @store_credit_reason
+ # @store_credit.errors.add(:base, t('spree.admin.store_credits.errors.store_credit_reason_required'))
+ # render_edit_page
+ # end
+ #
+ # amount = params.require(:store_credit).require(:amount)
+ # if @store_credit.update_amount(amount, @store_credit_reason, spree_current_user)
+ # flash[:success] = flash_message_for(@store_credit, :successfully_updated)
+ # redirect_to admin_user_store_credit_path(@user, @store_credit)
+ # else
+ # flash[:error] = "#{t("spree.admin.store_credits.unable_to_update")}: #{@store_credit.errors.full_messages.join(', ')}"
+ # render(:edit_amount) && return
+ # end
+ # end
+
+ def wip_old_update_amount
+ if @store_credit.update(permitted_store_credit_params)
+ flash[:notice] = t('.success')
+ redirect_to solidus_admin.user_store_credit_path(@user, @store_credit), status: :see_other
+ else
+ respond_to do |format|
+ format.html { render component("users/store_credits/edit_amount").new(
+ user: @user,
+ store_credit: @store_credit,
+ events: @store_credit_events,
+ reasons: @store_credit_reasons
+ ),
+ status: :unprocessable_entity
+ }
+ end
+ end
+ end
+
+ def update_amount
+ @store_credit_reason = Spree::StoreCreditReason.find_by(id: params[:store_credit_reason_id])
+ amount = params.require(:store_credit).require(:amount)
+
+ if amount_changed?
+ if @store_credit_reason.blank?
+ @store_credit.errors.add(:base, "Store Credit reason must be provided")
+ render_edit_page_with_errors and return
+ end
+
+ unless @store_credit.update_amount(amount, @store_credit_reason, spree_current_user)
+ render_edit_page_with_errors and return
+ end
end
+
+ @store_credit.update(memo: permitted_store_credit_params[:memo])
+
+ flash[:notice] = t('.success')
+ redirect_to solidus_admin.user_store_credit_path(@user, @store_credit), status: :see_other
end
private
+ def render_edit_page_with_errors
+ @store_credit_events = @store_credit.store_credit_events.chronological
+
+ respond_to do |format|
+ format.html do
+ render component("users/store_credits/edit_amount").new(
+ user: @user,
+ store_credit: @store_credit,
+ events: @store_credit_events,
+ reasons: @store_credit_reasons
+ ),
+ status: :unprocessable_entity
+ end
+ end
+ end
+
+ def permitted_store_credit_params
+ params.require(:store_credit).permit([:amount, :currency, :category_id, :memo]).
+ merge(created_by: spree_current_user)
+ end
+
def set_store_credit
@store_credit = Spree::StoreCredit.find(params[:id])
end
@@ -30,5 +132,21 @@ def set_store_credit
def set_user
@user = Spree.user_class.find(params[:user_id])
end
+
+ def set_store_credit_reasons
+ @store_credit_reasons = Spree::StoreCreditReason.active.order(:name)
+ end
+
+ def amount_changed?
+ # Add error if the amount is blank or nil. Let the model validation handle all other cases.
+ if permitted_store_credit_params[:amount].blank?
+ @store_credit.errors.add(:amount, :greater_than, count: 0, value: permitted_store_credit_params[:amount])
+ return false
+ end
+
+ old_amount = @store_credit.amount
+ new_amount = BigDecimal(permitted_store_credit_params[:amount])
+ old_amount != new_amount
+ end
end
end
diff --git a/admin/config/locales/store_credits.en.yml b/admin/config/locales/store_credits.en.yml
new file mode 100644
index 00000000000..e24c5cda30c
--- /dev/null
+++ b/admin/config/locales/store_credits.en.yml
@@ -0,0 +1,10 @@
+en:
+ solidus_admin:
+ store_credits:
+ title: "Store Credits"
+ destroy:
+ success: "Store credit was successfully removed."
+ create:
+ success: "Store credit was successfully created."
+ update_amount:
+ success: "Store credit was successfully updated."
diff --git a/admin/config/routes.rb b/admin/config/routes.rb
index cf3b11aa03a..4f4cf14b332 100644
--- a/admin/config/routes.rb
+++ b/admin/config/routes.rb
@@ -53,7 +53,14 @@
get :items
end
- resources :store_credits, only: [:index, :show], controller: "store_credits"
+ resources :store_credits, only: [:index, :show], constraints: { id: /\d+/ }, controller: "store_credits" do
+ member do
+ get :edit_amount
+ put :update_amount
+ # get :edit_validity
+ # put :invalidate
+ end
+ end
end
admin_resources :promotions, only: [:index, :destroy]
diff --git a/backend/app/views/spree/admin/store_credits/edit_amount.html.erb b/backend/app/views/spree/admin/store_credits/edit_amount.html.erb
index b3ce218b0fb..ad49a4a7f42 100644
--- a/backend/app/views/spree/admin/store_credits/edit_amount.html.erb
+++ b/backend/app/views/spree/admin/store_credits/edit_amount.html.erb
@@ -1,14 +1,3 @@
-<% admin_breadcrumb(link_to plural_resource_name(Spree::LegacyUser), spree.admin_users_path) %>
-<% admin_breadcrumb(link_to @user.email, edit_admin_user_url(@user)) %>
-<% admin_breadcrumb(link_to plural_resource_name(Spree::StoreCredit), spree.admin_user_store_credits_path(@user)) %>
-<% admin_breadcrumb(link_to Spree::StoreCredit.model_name.human, admin_user_store_credit_path(@user, @store_credit)) %>
-<% admin_breadcrumb(t('spree.edit')) %>
-
-<%= render 'spree/admin/users/sidebar' %>
-<%= render 'spree/admin/users/tabs', current: :store_credits %>
-<% content_for :page_actions do %>
-<% end %>
-
<%= form_for [:admin, @user, @store_credit], url: update_amount_admin_user_store_credit_path, method: :put do |f| %>
<% end %>