# frozen_string_literal: true
module SolidusAdmin
class UsersController < SolidusAdmin::BaseController
include SolidusAdmin::ControllerHelpers::Search
include Spree::Core::ControllerHelpers::StrongParameters
before_action :set_user, only: [:edit, :addresses, :update_addresses, :orders, :items, :store_credits]
search_scope(:all, default: true)
search_scope(:customers) { _1.left_outer_joins(:role_users).where(role_users: { id: nil }) }
search_scope(:admin) { _1.joins(:role_users).distinct }
search_scope(:with_orders) { _1.joins(:orders).distinct }
search_scope(:without_orders) { _1.left_outer_joins(:orders).where(orders: { id: nil }) }
def index
users = apply_search_to(
Spree.user_class.order(created_at: :desc, id: :desc),
param: :q,
)
set_page_and_extract_portion_from(users)
respond_to do |format|
format.html { render component('users/index').new(page: @page) }
end
end
def addresses
respond_to do |format|
format.turbo_stream { render turbo_stream: '' }
format.html { render component('users/addresses').new(user: @user) }
end
end
def update_addresses
set_address_from_params
if @address.valid? && @user.update(user_params)
flash[:success] = t(".#{@type}.success")
respond_to do |format|
format.turbo_stream { render turbo_stream: '' }
format.html { render component('users/addresses').new(user: @user) }
end
else
respond_to do |format|
format.html { render component('users/addresses').new(user: @user, address: @address, type: @type), status: :unprocessable_entity }
end
end
end
def orders
set_orders
respond_to do |format|
format.html { render component('users/orders').new(user: @user, orders: @orders) }
end
end
def items
set_items
respond_to do |format|
format.html { render component('users/items').new(user: @user, items: @items) }
end
end
def edit
respond_to do |format|
format.html { render component('users/edit').new(user: @user) }
end
end
def destroy
@users = Spree.user_class.where(id: params[:id])
Spree.user_class.transaction { @users.destroy_all }
flash[:notice] = t('.success')
redirect_back_or_to users_path, status: :see_other
end
def store_credits
@store_credits = Spree::StoreCredit.where(user_id: @user.id).order(id: :desc)
respond_to do |format|
format.html { render component("users/store_credits/index").new(user: @user, store_credits: @store_credits) }
end
end
private
def set_user
@user = Spree.user_class.find(params[:id])
end
def user_params
params.require(:user).permit(
:user_id,
permitted_user_attributes,
bill_address_attributes: permitted_address_attributes,
ship_address_attributes: permitted_address_attributes
)
end
# @note This method is used to generate validation errors on the address.
# Since the update is being performed via the @user, and not directly on
# the @address, we sadly don't seem to get these errors automatically.
def set_address_from_params
if user_params.key?(:bill_address_attributes)
@address = Spree::Address.new(user_params[:bill_address_attributes])
@type = "bill"
elsif user_params.key?(:ship_address_attributes)
@address = Spree::Address.new(user_params[:ship_address_attributes])
@type = "ship"
end
end
def set_orders
params[:q] ||= {}
@search = Spree::Order.reverse_chronological.ransack(params[:q].merge(user_id_eq: @user.id))
@orders = @search.result.page(params[:page]).per(Spree::Config[:admin_products_per_page])
end
def set_items
params[:q] ||= {}
@search = Spree::Order.reverse_chronological.includes(line_items: { variant: [:product, { option_values: :option_type }] }).ransack(params[:q].merge(user_id_eq: @user.id))
@orders = @search.result.page(params[:page]).per(Spree::Config[:admin_products_per_page])
@items = @orders&.map(&:line_items)&.flatten
end
def authorization_subject
Spree.user_class
end
end
end