Skip to content

Commit 1072c2a

Browse files
committed
PC-27: Added option to load items without category
1 parent 95f6751 commit 1072c2a

4 files changed

Lines changed: 66 additions & 54 deletions

File tree

app/admin/quotes.rb

Lines changed: 10 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -34,63 +34,14 @@
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 :categories, as: :check_boxes, collection: Category.pluck(:name, :id)
37+
f.input :categories, as: :check_boxes,
38+
collection: Category.order(:name).pluck(:name, :id) + [['Items without category', 'other']],
39+
wrapper_html: { class: 'categories-wrapper' }
3840
end
3941
div do
4042
button_tag 'Load Items from Category', type: 'button', id: 'load-items-button', class: 'button'
4143
end
4244
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 pricingParams = lastItemGroup.querySelector("input[id$='_pricing_parameters']");
76-
const discount = lastItemGroup.querySelector("input[id$='_discount']");
77-
78-
if (itemSelect) {
79-
itemSelect.value = item.item_id;
80-
}
81-
if (pricingParams) {
82-
pricingParams.value = item.pricing_parameters;
83-
}
84-
if (discount) {
85-
discount.value = item.discount;
86-
}
87-
}, 100);
88-
});
89-
});
90-
});
91-
});
92-
JS
93-
end
9445
end
9546

9647
show do
@@ -117,14 +68,19 @@
11768

11869
collection_action :load_items_from_categories, method: :post do
11970
category_ids = params[:category_ids] || []
120-
items = Item.where(category_id: category_ids)
71+
72+
items = Item.where(category_id: category_ids.reject { |id| id == 'other' })
73+
items += Item.where(category_id: nil) if category_ids.include?('other')
12174

12275
render json: items.map { |item|
12376
{
12477
category_id: item.category_id,
12578
item_id: item.id,
12679
item_name: item.name,
127-
_pricing_parameters: '',
80+
item_fixed_parameters: item.fixed_parameters,
81+
item_pricing_options: item.pricing_options,
82+
item_open_parameters_label: item.open_parameters_label,
83+
pricing_parameters: {},
12884
discount: 0
12985
}
13086
}

app/assets/javascripts/active_admin.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//= require active_admin/base
22
//= require formula_builder
33
//= require new_parameter
4+
//= require quotes_admin
45

56

67

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
document.addEventListener('DOMContentLoaded', function () {
2+
const button = document.getElementById('load-items-button')
3+
if (!button) return
4+
5+
button.addEventListener('click', function () {
6+
const selectedCategories = Array.from(document.querySelectorAll("input[name='quote[category_ids][]']:checked")).map(
7+
(cb) => cb.value,
8+
)
9+
10+
if (selectedCategories.length === 0) {
11+
alert('Please select at least one category.')
12+
return
13+
}
14+
15+
fetch('/admin/quotes/load_items_from_categories', {
16+
method: 'POST',
17+
headers: {
18+
'Content-Type': 'application/json',
19+
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
20+
},
21+
body: JSON.stringify({ category_ids: selectedCategories }),
22+
})
23+
.then((response) => response.json())
24+
.then((items) => {
25+
const container = document.querySelector('.has_many_container.quote_items')
26+
if (!container) return
27+
28+
items.forEach((item) => {
29+
const addButton = container.querySelector('.has_many_add')
30+
addButton?.click()
31+
32+
setTimeout(() => {
33+
const lastItemGroup = container.querySelectorAll('.has_many_fields').item(-1)
34+
const itemSelect = lastItemGroup?.querySelector("select[id$='_item_id']")
35+
const pricingParams = lastItemGroup?.querySelector("input[id$='_pricing_parameters']")
36+
const discount = lastItemGroup?.querySelector("input[id$='_discount']")
37+
38+
if (itemSelect) itemSelect.value = item.item_id
39+
if (pricingParams) pricingParams.value = item.pricing_parameters
40+
if (discount) discount.value = item.discount
41+
}, 100)
42+
})
43+
})
44+
})
45+
})

app/assets/stylesheets/active_admin.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,14 @@
233233
color: #222 !important;
234234
}
235235

236+
.categories-wrapper .choices-group {
237+
display: grid;
238+
grid-template-columns: repeat(5, 1fr);
239+
gap: 0.5rem 1rem;
240+
margin: auto;
241+
list-style: none;
242+
width: 100%;
243+
}
244+
245+
236246
@import "active_admin/forms/select";

0 commit comments

Comments
 (0)