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
164 lines
4.9 KiB
HTML
164 lines
4.9 KiB
HTML
{% extends "templates/web.html" %}
|
|
|
|
{% block title %}{{ _('Products') }}{% endblock %}
|
|
{% block header %}
|
|
<h1>{{ _('Products') }}</h1>
|
|
{% endblock header %}
|
|
|
|
{% block page_content %}
|
|
<div class="row">
|
|
<div class="col-8">
|
|
<div class="input-group input-group-sm mb-3">
|
|
<input type="search" class="form-control" placeholder="{{_('Search')}}"
|
|
aria-label="{{_('Product Search')}}" aria-describedby="product-search"
|
|
value="{{ frappe.form_dict.search or '' }}"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-4 pl-0">
|
|
<button class="btn btn-light btn-sm btn-block d-md-none"
|
|
type="button"
|
|
data-toggle="collapse"
|
|
data-target="#product-filters"
|
|
aria-expanded="false"
|
|
aria-controls="product-filters"
|
|
style="white-space: nowrap;"
|
|
>
|
|
{{ _('Toggle Filters') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-12 order-2 col-md-8 order-md-1 products-list">
|
|
{% if items %}
|
|
{% for item in items %}
|
|
{% include "erpnext/www/all-products/item_row.html" %}
|
|
{% endfor %}
|
|
{% else %}
|
|
{% include "erpnext/www/all-products/not_found.html" %}
|
|
{% endif %}
|
|
</div>
|
|
<div class="col-12 order-1 col-md-4 order-md-2">
|
|
|
|
{% if frappe.form_dict.start or frappe.form_dict.field_filters or frappe.form_dict.search %}
|
|
<a class="mb-3 d-inline-block" href="/all-products">{{ _('Clear filters') }}</a>
|
|
{% endif %}
|
|
|
|
<div class="collapse d-md-block" id="product-filters">
|
|
{% for field_filter in field_filters %}
|
|
{%- set item_field = field_filter[0] %}
|
|
{%- set values = field_filter[1] %}
|
|
<div class="mb-4">
|
|
<h6>{{ item_field.label }}</h6>
|
|
|
|
{% if values | len > 20 %}
|
|
<!-- show inline filter if values more than 20 -->
|
|
<input type="text" class="form-control form-control-sm mb-2 product-filter-filter"/>
|
|
{% endif %}
|
|
|
|
{% if values %}
|
|
<div class="filter-options">
|
|
{% for value in values %}
|
|
<div class="custom-control custom-checkbox" data-value="{{ value }}">
|
|
<input type="checkbox"
|
|
class="product-filter field-filter custom-control-input"
|
|
id="{{value}}"
|
|
data-filter-name="{{ item_field.fieldname }}"
|
|
data-filter-value="{{ value }}"
|
|
>
|
|
<label class="custom-control-label" for="{{value}}">
|
|
{{ value }}
|
|
</label>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<i class="text-muted">{{ _('No values') }}</i>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
|
|
{% for attribute in attribute_filters %}
|
|
<div class="mb-4">
|
|
<h6>{{ attribute.name }}</h6>
|
|
|
|
{% if values | len > 20 %}
|
|
<!-- show inline filter if values more than 20 -->
|
|
<input type="text" class="form-control form-control-sm mb-2 product-filter-filter"/>
|
|
{% endif %}
|
|
|
|
{% if attribute.item_attribute_values %}
|
|
<div class="filter-options">
|
|
{% for attr_value in attribute.item_attribute_values %}
|
|
<div class="custom-control custom-checkbox" data-value="{{ value }}">
|
|
<input type="checkbox"
|
|
class="product-filter attribute-filter custom-control-input"
|
|
id="{{attr_value.name}}"
|
|
data-attribute-name="{{ attribute.name }}"
|
|
data-attribute-value="{{ attr_value.attribute_value }}"
|
|
{% if attr_value.checked %} checked {% endif %}
|
|
>
|
|
<label class="custom-control-label" for="{{attr_value.name}}">
|
|
{{ attr_value.attribute_value }}
|
|
</label>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<i class="text-muted">{{ _('No values') }}</i>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<script>
|
|
frappe.ready(() => {
|
|
$('.product-filter-filter').on('keydown', frappe.utils.debounce((e) => {
|
|
const $input = $(e.target);
|
|
const keyword = ($input.val() || '').toLowerCase();
|
|
const $filter_options = $input.next('.filter-options');
|
|
|
|
$filter_options.find('.custom-control').show();
|
|
$filter_options.find('.custom-control').each((i, el) => {
|
|
const $el = $(el);
|
|
const value = $el.data('value').toLowerCase();
|
|
if (!value.includes(keyword)) {
|
|
$el.hide();
|
|
}
|
|
});
|
|
}, 300));
|
|
})
|
|
</script>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-12">
|
|
{% if frappe.form_dict.start|int > 0 %}
|
|
<button class="btn btn-outline-secondary btn-prev" data-start="{{ frappe.form_dict.start|int - page_length }}">{{ _("Prev") }}</button>
|
|
{% endif %}
|
|
{% if items|length >= page_length %}
|
|
<button class="btn btn-outline-secondary btn-next" data-start="{{ frappe.form_dict.start|int + page_length }}">{{ _("Next") }}</button>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
frappe.ready(() => {
|
|
$('.btn-prev, .btn-next').click((e) => {
|
|
const $btn = $(e.target);
|
|
$btn.prop('disabled', true);
|
|
const start = $btn.data('start');
|
|
let query_params = frappe.utils.get_query_params();
|
|
query_params.start = start;
|
|
let path = window.location.pathname + '?' + frappe.utils.get_url_from_dict(query_params);
|
|
window.location.href = path;
|
|
});
|
|
});
|
|
</script>
|
|
|
|
{% endblock %}
|
|
|
|
|