Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Admin][Users] Add new admin store credits create flow #6036

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
103 changes: 86 additions & 17 deletions admin/app/controllers/solidus_admin/store_credits_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
before_action :set_user
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 @@ -15,16 +17,54 @@
end

def show
@store_credit_events = @store_credit.store_credit_events.chronological

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

def edit_amount
@store_credit_events = @store_credit.store_credit_events.chronological
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 {
render component("users/store_credits/edit_amount").new(
Expand All @@ -38,8 +78,8 @@
end

def update_amount
return unless ensure_amount
return unless ensure_store_credit_reason
return unless ensure_amount { render_edit_with_errors }
return unless ensure_store_credit_reason { render_edit_with_errors }

if @store_credit.update_amount(permitted_store_credit_params[:amount], @store_credit_reason, spree_current_user)
respond_to do |format|
Expand All @@ -54,13 +94,11 @@
end
end
else
render_edit_with_errors and return
render_edit_with_errors
end
end

def edit_memo
@store_credit_events = @store_credit.store_credit_events.chronological

respond_to do |format|
format.html {
render component("users/store_credits/edit_memo").new(
Expand Down Expand Up @@ -92,8 +130,6 @@
end

def edit_validity
@store_credit_events = @store_credit.store_credit_events.chronological

respond_to do |format|
format.html {
render component("users/store_credits/edit_validity").new(
Expand All @@ -107,7 +143,7 @@
end

def invalidate
return unless ensure_store_credit_reason
return unless ensure_store_credit_reason { render_edit_with_errors }

if @store_credit.invalidate(@store_credit_reason, spree_current_user)
flash[:notice] = t('.success')
Expand All @@ -118,8 +154,6 @@
end

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

format.html do
redirect_to solidus_admin.user_store_credit_path(@user, @store_credit), status: :see_other
end
Expand All @@ -144,15 +178,39 @@
@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 All @@ -176,7 +234,7 @@
def ensure_amount
if permitted_store_credit_params[:amount].blank?
@store_credit.errors.add(:amount, :greater_than, count: 0, value: permitted_store_credit_params[:amount])
render_edit_with_errors
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
Expand All @@ -187,7 +245,18 @@

if @store_credit_reason.blank?
@store_credit.errors.add(:store_credit_reason_id, "Store Credit reason must be provided")
render_edit_with_errors
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

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
Expand Down
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
Loading