5f8b358fd4
- Refactored Homepage with customisable Hero Section - New Homepage Section to add content on Homepage as cards or using Custom HTML - Products page at "/all-products" with customisable filters - Item Configure dialog to find an Item Variant filtered by attribute values - Contact Us dialog on Item page - Customisable Item page content using the Website Content field
162 lines
4.5 KiB
JavaScript
162 lines
4.5 KiB
JavaScript
$(() => {
|
|
class ProductListing {
|
|
constructor() {
|
|
this.bind_filters();
|
|
this.bind_search();
|
|
this.restore_filters_state();
|
|
}
|
|
|
|
bind_filters() {
|
|
this.field_filters = {};
|
|
this.attribute_filters = {};
|
|
|
|
$('.product-filter').on('change', frappe.utils.debounce((e) => {
|
|
const $checkbox = $(e.target);
|
|
const is_checked = $checkbox.is(':checked');
|
|
|
|
if ($checkbox.is('.attribute-filter')) {
|
|
const {
|
|
attributeName: attribute_name,
|
|
attributeValue: attribute_value
|
|
} = $checkbox.data();
|
|
|
|
if (is_checked) {
|
|
this.attribute_filters[attribute_name] = this.attribute_filters[attribute_name] || [];
|
|
this.attribute_filters[attribute_name].push(attribute_value);
|
|
} else {
|
|
this.attribute_filters[attribute_name] = this.attribute_filters[attribute_name] || [];
|
|
this.attribute_filters[attribute_name] = this.attribute_filters[attribute_name].filter(v => v !== attribute_value);
|
|
}
|
|
|
|
if (this.attribute_filters[attribute_name].length === 0) {
|
|
delete this.attribute_filters[attribute_name];
|
|
}
|
|
} else if ($checkbox.is('.field-filter')) {
|
|
const {
|
|
filterName: filter_name,
|
|
filterValue: filter_value
|
|
} = $checkbox.data();
|
|
|
|
if (is_checked) {
|
|
this.field_filters[filter_name] = this.field_filters[filter_name] || [];
|
|
this.field_filters[filter_name].push(filter_value);
|
|
} else {
|
|
this.field_filters[filter_name] = this.field_filters[filter_name] || [];
|
|
this.field_filters[filter_name] = this.field_filters[filter_name].filter(v => v !== filter_value);
|
|
}
|
|
|
|
if (this.field_filters[filter_name].length === 0) {
|
|
delete this.field_filters[filter_name];
|
|
}
|
|
}
|
|
|
|
const query_string = get_query_string({
|
|
field_filters: JSON.stringify(if_key_exists(this.field_filters)),
|
|
attribute_filters: JSON.stringify(if_key_exists(this.attribute_filters)),
|
|
});
|
|
window.history.pushState('filters', '', '/all-products?' + query_string);
|
|
|
|
$('.page_content input').prop('disabled', true);
|
|
this.get_items_with_filters()
|
|
.then(html => {
|
|
$('.products-list').html(html);
|
|
})
|
|
.then(data => {
|
|
$('.page_content input').prop('disabled', false);
|
|
return data;
|
|
})
|
|
.catch(() => {
|
|
$('.page_content input').prop('disabled', false);
|
|
});
|
|
}, 1000));
|
|
}
|
|
|
|
make_filters() {
|
|
|
|
}
|
|
|
|
bind_search() {
|
|
$('input[type=search]').on('keydown', (e) => {
|
|
if (e.keyCode === 13) {
|
|
// Enter
|
|
const value = e.target.value;
|
|
if (value) {
|
|
window.location.search = 'search=' + e.target.value;
|
|
} else {
|
|
window.location.search = '';
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
restore_filters_state() {
|
|
const filters = frappe.utils.get_query_params();
|
|
let {field_filters, attribute_filters} = filters;
|
|
|
|
if (field_filters) {
|
|
field_filters = JSON.parse(field_filters);
|
|
for (let fieldname in field_filters) {
|
|
const values = field_filters[fieldname];
|
|
const selector = values.map(value => {
|
|
return `input[data-filter-name="${fieldname}"][data-filter-value="${value}"]`;
|
|
}).join(',');
|
|
$(selector).prop('checked', true);
|
|
}
|
|
this.field_filters = field_filters;
|
|
}
|
|
if (attribute_filters) {
|
|
attribute_filters = JSON.parse(attribute_filters);
|
|
for (let attribute in attribute_filters) {
|
|
const values = attribute_filters[attribute];
|
|
const selector = values.map(value => {
|
|
return `input[data-attribute-name="${attribute}"][data-attribute-value="${value}"]`;
|
|
}).join(',');
|
|
$(selector).prop('checked', true);
|
|
}
|
|
this.attribute_filters = attribute_filters;
|
|
}
|
|
}
|
|
|
|
get_items_with_filters() {
|
|
const { attribute_filters, field_filters } = this;
|
|
const args = {
|
|
field_filters: if_key_exists(field_filters),
|
|
attribute_filters: if_key_exists(attribute_filters)
|
|
};
|
|
|
|
return new Promise((resolve, reject) => {
|
|
frappe.call('erpnext.portal.product_configurator.utils.get_products_html_for_website', args)
|
|
.then(r => {
|
|
if (r.exc) reject(r.exc);
|
|
else resolve(r.message);
|
|
})
|
|
.fail(reject);
|
|
});
|
|
}
|
|
}
|
|
|
|
new ProductListing();
|
|
|
|
function get_query_string(object) {
|
|
const url = new URLSearchParams();
|
|
for (let key in object) {
|
|
const value = object[key];
|
|
if (value) {
|
|
url.append(key, value);
|
|
}
|
|
}
|
|
return url.toString();
|
|
}
|
|
|
|
function if_key_exists(obj) {
|
|
let exists = false;
|
|
for (let key in obj) {
|
|
if (obj.hasOwnProperty(key) && obj[key]) {
|
|
exists = true;
|
|
break;
|
|
}
|
|
}
|
|
return exists ? obj : undefined;
|
|
}
|
|
});
|