Skip to content

Commit 34d7671

Browse files
committed
PC-27: Add Categories Quote active admin
1 parent 1da97e8 commit 34d7671

5 files changed

Lines changed: 95 additions & 18 deletions

File tree

app/admin/quotes.rb

Lines changed: 77 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
ActiveAdmin.register Quote do
2-
permit_params :customer_id, :user_id,
3-
quote_items_attributes: [:id,
4-
:_destroy,
5-
:quote_id,
6-
:item_id,
7-
:open_parameters,
8-
:price,
9-
:discount,
10-
:final_price]
2+
permit_params :customer_id, :user_id, category_ids: [],
3+
quote_items_attributes: [:id,
4+
:_destroy,
5+
:quote_id,
6+
:item_id,
7+
:open_parameters,
8+
:price,
9+
:discount,
10+
:final_price]
1111

1212
filter :customer_name, as: :string, label: 'Customer Name'
1313
filter :user, as: :select, collection: proc {
@@ -34,17 +34,63 @@
3434
f.inputs do
3535
f.input :customer, as: :select, collection: Customer.pluck(:company_name, :id)
3636
f.input :user, as: :select, collection: User.order(:email).map { |u| ["#{u.email} (#{u.name})", u.id] }
37-
f.input :total_price, input_html: { disabled: true }
37+
f.input :categories, as: :check_boxes, collection: Category.pluck(:name, :id)
3838
end
39-
f.inputs "Quote Items" do
40-
f.has_many :quote_items, allow_destroy: true, new_record: true do |qi|
41-
qi.input :item, as: :select, collection: Item.pluck(:name, :id)
42-
qi.input :open_parameters
43-
qi.input :price
44-
qi.input :discount
45-
end
39+
div do
40+
button_tag 'Load Items from Category', type: 'button', id: 'load-items-button', class: 'button'
4641
end
4742
f.actions
43+
# JS to load items dynamically
44+
script do
45+
raw <<-JS
46+
document.addEventListener("DOMContentLoaded", function () {
47+
const button = document.getElementById("load-items-button");
48+
button?.addEventListener("click", function () {
49+
const selectedCategories = Array.from(document.querySelectorAll("input[name='quote[category_ids][]']:checked")).map(cb => cb.value);
50+
51+
if (selectedCategories.length === 0) {
52+
alert("Please select at least one category.");
53+
return;
54+
}
55+
56+
fetch("/admin/quotes/load_items_from_categories", {
57+
method: "POST",
58+
headers: {
59+
"Content-Type": "application/json",
60+
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').getAttribute("content")
61+
},
62+
body: JSON.stringify({ category_ids: selectedCategories })
63+
})
64+
.then(response => response.json())
65+
.then(items => {
66+
const container = document.querySelector(".has_many_container.quote_items");
67+
68+
items.forEach(item => {
69+
const addButton = container.querySelector(".has_many_add");
70+
addButton.click();
71+
72+
setTimeout(() => {
73+
const lastItemGroup = container.querySelectorAll(".has_many_fields").item(-1);
74+
const itemSelect = lastItemGroup.querySelector("select[id$='_item_id']");
75+
const openParams = lastItemGroup.querySelector("input[id$='_open_parameters']");
76+
const discount = lastItemGroup.querySelector("input[id$='_discount']");
77+
78+
if (itemSelect) {
79+
itemSelect.value = item.item_id;
80+
}
81+
if (openParams) {
82+
openParams.value = item.open_parameters;
83+
}
84+
if (discount) {
85+
discount.value = item.discount;
86+
}
87+
}, 100);
88+
});
89+
});
90+
});
91+
});
92+
JS
93+
end
4894
end
4995

5096
show do
@@ -68,4 +114,18 @@
68114
end
69115
end
70116
end
117+
118+
collection_action :load_items_from_categories, method: :post do
119+
category_ids = params[:category_ids] || []
120+
items = Item.where(category_id: category_ids)
121+
122+
render json: items.map { |item|
123+
{
124+
item_id: item.id,
125+
item_name: item.name,
126+
open_parameters: '',
127+
discount: 0
128+
}
129+
}
130+
end
71131
end

app/models/category.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ class Category < ApplicationRecord
22
ASCII_CHARACTERS = /\A[[:ascii:]]*\z/
33

44
has_many :items, dependent: :nullify
5+
has_and_belongs_to_many :quotes
56

67
normalizes :name, with: ->(name) { name.gsub(/\s+/, ' ').strip }
78

app/models/quote.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ class Quote < ApplicationRecord
22
belongs_to :customer
33
belongs_to :user
44
has_many :quote_items, dependent: :destroy
5+
has_and_belongs_to_many :categories
56

67
validates :total_price, presence: true, numericality: { greater_than_or_equal_to: 0 }
78

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class CreateJoinTableQuotesCategories < ActiveRecord::Migration[8.0]
2+
def change
3+
create_join_table :quotes, :categories do |t|
4+
t.index [:quote_id, :category_id]
5+
t.index [:category_id, :quote_id]
6+
end
7+
end
8+
end

db/schema.rb

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)