Skip to content

Commit

Permalink
Add new admin store credits create flow
Browse files Browse the repository at this point in the history
  • Loading branch information
MadelineCollier committed Dec 18, 2024
1 parent e8593a8 commit 0517f29
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
<%= page_header_title(t(".title", email: @user.email)) %>

<%= page_header_actions do %>
<%= render component("ui/button").new(tag: :a, text: t(".add_store_credit"), href: spree.new_admin_user_store_credit_url(user_id: @user.id, only_path: true)) %>
<%= render component("ui/button").new(
"data-action": "click->#{stimulus_id}#actionButtonClicked",
"data-#{stimulus_id}-url-param": solidus_admin.new_user_store_credit_path(user_id: @user.id, _turbo_frame: :new_store_credit_modal),
text: t(".add_store_credit"),
)%>
<% end %>
<% end %>

Expand Down Expand Up @@ -37,7 +41,11 @@
<% else %>
<%= render component('ui/panel').new(title: t(".store_credit")) do %>
<%= t(".no_credits_found") %>
<%= render component("ui/button").new(tag: :a, text: t(".create_one"), href: spree.new_admin_user_store_credit_url(user_id: @user.id, only_path: true)) %>
<%= render component("ui/button").new(
"data-action": "click->#{stimulus_id}#actionButtonClicked",
"data-#{stimulus_id}-url-param": solidus_admin.new_user_store_credit_path(user_id: @user.id, _turbo_frame: :new_store_credit_modal),
text: t(".create_one"),
)%>
<% end %>
<% end %>
<% end %>
Expand All @@ -46,4 +54,8 @@
<%= render component("users/stats").new(user: @user) %>
<% end %>
<% end %>

<% turbo_frames.each do |frame| %>
<%= turbo_frame_tag frame %>
<% end %>
<% end %>
Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ def tabs
]
end

def turbo_frames
%w[
new_store_credit_modal
]
end

def rows
@store_credits
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<%= turbo_frame_tag :new_store_credit_modal do %>
<%= render component("ui/modal").new(title: t(".title")) do |modal| %>
<%= form_for @store_credit, url: solidus_admin.user_store_credits_path(@user), method: :post, html: { id: form_id } do |f| %>
<div class="flex flex-col gap-6 pb-4">
<%= render component("ui/forms/field").text_field(f, :amount, class: "required") %>
<%= render component("ui/forms/field").select(
f,
:currency,
currency_select_options.html_safe,
include_blank: t("spree.currency"),
html: { required: true }
) %>
<%= render component("ui/forms/field").select(
f,
:category_id,
store_credit_categories_select_options.html_safe,
include_blank: t("spree.category"),
html: { required: true }
) %>
<%= render component("ui/forms/field").text_field(f, :memo) %>
</div>
<% modal.with_actions do %>
<form method="dialog">
<%= render component("ui/button").new(scheme: :secondary, text: t(".cancel")) %>
</form>
<%= render component("ui/button").new(form: form_id, type: :submit, text: t(".submit")) %>
<% end %>
<% end %>
<% end %>
<% end %>
<%= render component("users/store_credits/index").new(user: @user, store_credits: @store_credits) %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

class SolidusAdmin::Users::StoreCredits::New::Component < SolidusAdmin::BaseComponent
def initialize(user:, store_credit:, categories:)
@user = user
@store_credit = store_credit
@store_credit_categories = categories
@store_credits = Spree::StoreCredit.where(user_id: @user.id).order(id: :desc)
end

def form_id
dom_id(@store_credit, "#{stimulus_id}_new_form")
end

def currency_select_options
options_from_collection_for_select(Spree::Config.available_currencies, :iso_code, :iso_code, Spree::Config.currency)
end

def store_credit_categories_select_options
# Placeholder + Store Credit Categories
"<option value>#{t('.choose_category')}</option>" + options_from_collection_for_select(@store_credit_categories, :id, :name)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
en:
title: New Store Credit
cancel: Cancel
submit: Create
choose_category: Choose Store Credit Category
76 changes: 75 additions & 1 deletion admin/app/controllers/solidus_admin/store_credits_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class StoreCreditsController < SolidusAdmin::BaseController
before_action :set_store_credit, only: [:show, :edit_amount, :update_amount, :edit_memo, :update_memo, :edit_validity, :invalidate]
before_action :set_store_credit_reasons, only: [:edit_amount, :update_amount, :edit_validity, :invalidate]
before_action :set_store_credit_events, only: [:show, :edit_amount, :edit_memo, :edit_validity]
before_action :set_store_credit_categories, only: [:new]

def index
@store_credits = Spree::StoreCredit.where(user_id: @user.id).order(id: :desc)
Expand All @@ -21,6 +22,48 @@ def show
end
end

def new
@store_credit ||= Spree::StoreCredit.new

respond_to do |format|
format.html {
render component("users/store_credits/new").new(
user: @user,
store_credit: @store_credit,
categories: @store_credit_categories
)
}
end
end

def create
@store_credit = @user.store_credits.build(
permitted_store_credit_params.merge({
created_by: spree_current_user,
action_originator: spree_current_user
})
)

return unless ensure_amount { render_new_with_errors }
return unless ensure_store_credit_category { render_new_with_errors }

if @store_credit.save
respond_to do |format|
flash[:notice] = t('.success')

format.html do
redirect_to solidus_admin.user_store_credits_path(@user), status: :see_other
end

format.turbo_stream do
render turbo_stream: '<turbo-stream action="refresh" />'
end
end
else
render_new_with_errors

Check warning on line 63 in admin/app/controllers/solidus_admin/store_credits_controller.rb

View check run for this annotation

Codecov / codecov/patch

admin/app/controllers/solidus_admin/store_credits_controller.rb#L63

Added line #L63 was not covered by tests
end
end

def edit_amount
respond_to do |format|
format.html {
Expand Down Expand Up @@ -135,19 +178,39 @@ def set_store_credit_reasons
@store_credit_reasons = Spree::StoreCreditReason.active.order(:name)
end

def set_store_credit_categories
@store_credit_categories = Spree::StoreCreditCategory.all.order(:name)
end

def set_store_credit_events
@store_credit_events = @store_credit.store_credit_events.chronological
end

def permitted_store_credit_params
permitted_params = [:amount, :currency, :category_id, :memo]
permitted_params << :category_id if action_name.to_sym == :create
permitted_params << :store_credit_reason_id if [:update_amount, :invalidate].include?(action_name.to_sym)

params.require(:store_credit).permit(permitted_params).merge(created_by: spree_current_user)
end

def render_new_with_errors
set_store_credit_categories

respond_to do |format|
format.html do
render component("users/store_credits/new").new(
user: @user,
store_credit: @store_credit,
categories: @store_credit_categories
),
status: :unprocessable_entity
end
end
end

def render_edit_with_errors
@store_credit_events = @store_credit.store_credit_events.chronological
set_store_credit_events

template = if action_name.to_sym == :invalidate
"edit_validity"
Expand Down Expand Up @@ -187,5 +250,16 @@ def ensure_store_credit_reason
end
true
end

def ensure_store_credit_category
@store_credit_category = Spree::StoreCreditCategory.find_by(id: permitted_store_credit_params[:category_id])

if @store_credit_category.blank?
@store_credit.errors.add(:category_id, "Store Credit category must be provided")
yield if block_given? # Block is for error template rendering on a per-action basis so this can be re-used.
return false
end
true
end
end
end
2 changes: 1 addition & 1 deletion admin/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
get :items
end

resources :store_credits, only: [:index, :show], constraints: { id: /\d+/ }, controller: "store_credits" do
resources :store_credits, only: [:index, :show, :new, :create], controller: "store_credits" do
member do
get :edit_amount
put :update_amount
Expand Down
36 changes: 33 additions & 3 deletions admin/spec/features/store_credits_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

describe "StoreCredits", :js, type: :feature do
let(:admin) { create(:admin_user, email: "[email protected]") }
let!(:store_credit_reason) { create(:store_credit_reason, name: "credit given in error") }
let!(:store_credit_category) { create(:store_credit_category, name: "Gift Card") }
let!(:store_credit_type) { create(:primary_credit_type) }

before do
sign_in admin
Expand All @@ -27,11 +30,40 @@
it "shows the appropriate content" do
expect(page).to have_content("No Store Credits found.")
end

it "allows creation of a new store credit" do
click_on "Create One"

expect(page).to have_selector("dialog", wait: 5)
expect(page).to have_content("New Store Credit")

within("dialog") do
fill_in "Amount", with: ""
select "Gift Card", from: "store_credit[category_id]"
click_on "Create"
expect(page).to have_content("must be greater than 0")
click_on "Cancel"
end

click_on "Create One"

expect(page).to have_selector("dialog", wait: 5)
expect(page).to have_content("New Store Credit")

within("dialog") do
fill_in "Amount", with: "666.66"
select "Gift Card", from: "store_credit[category_id]"
fill_in "Memo", with: "A brand new store credit, how nice!"
click_on "Create"
end

expect(page).to have_content("Store credit was successfully created.")
expect(page).to have_content("Current balance: $666.66")
end
end

context "when a user has store credits" do
let!(:store_credit) { create(:store_credit, amount: 199.00, currency: "USD") }
let!(:store_credit_reason) { create(:store_credit_reason, name: "credit given in error") }

before do
store_credit.user.update(email: "[email protected]")
Expand Down Expand Up @@ -61,8 +93,6 @@
end

context "when clicking through to a single store credit" do
let!(:store_credit_reason) { create(:store_credit_reason, name: "credit given in error") }

before do
stub_authorization!(admin)
find_row("$199.00").click
Expand Down
Loading

0 comments on commit 0517f29

Please sign in to comment.