mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-01 11:19:09 +00:00
feat: Shop by Category
- Added Shop by Category Page - Tabbed sections for item fields in Shop by Category Page - Added Shop by Category Section in E commerce Settings - Nested Navigation & Breadcrumbs in Item group pages - Added scrollable & clickable Sub categories in Item Group page - Made breadcrumbs slightly dynamic in Item Page - Added image to Brand doctype
This commit is contained in:
0
erpnext/www/shop-by-category/__init__.py
Normal file
0
erpnext/www/shop-by-category/__init__.py
Normal file
28
erpnext/www/shop-by-category/category_card_section.html
Normal file
28
erpnext/www/shop-by-category/category_card_section.html
Normal file
@@ -0,0 +1,28 @@
|
||||
{%- macro card(title, image, type, url=None, text_primary=False) -%}
|
||||
<!-- style defined at shop-by-category index -->
|
||||
<div class="card category-card" data-type="{{ type }}" data-name="{{ title }}">
|
||||
{% if image %}
|
||||
<img class="card-img-top" src="{{ image }}" alt="{{ title }}" style="height:80%">
|
||||
{% else %}
|
||||
<div class="placeholder-div">
|
||||
<span class="placeholder">AB</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card-body text-center text-muted">
|
||||
{{ title or '' }}
|
||||
</div>
|
||||
<a href="{{ url or '#' }}" class="stretched-link"></a>
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
|
||||
<div class="col-12 item-card-group-section">
|
||||
<div class="row products-list product-category-section">
|
||||
{%- for row in data -%}
|
||||
{%- set title = row.name -%}
|
||||
{%- set image = row.get("image") -%}
|
||||
{%- if title -%}
|
||||
{{ card(title, image, type, row.get("route")) }}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</div>
|
||||
60
erpnext/www/shop-by-category/index.html
Normal file
60
erpnext/www/shop-by-category/index.html
Normal file
@@ -0,0 +1,60 @@
|
||||
{% extends "templates/web.html" %}
|
||||
{% block title %}{{ _('Shop by Category') }}{% endblock %}
|
||||
|
||||
{% block head_include %}
|
||||
<style>
|
||||
.category-slideshow {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.category-card {
|
||||
height: 300px !important;
|
||||
width: 300px !important;
|
||||
margin: 30px !important;
|
||||
}
|
||||
.placeholder-div {
|
||||
height:80%;
|
||||
width: -webkit-fill-available;
|
||||
padding: 50px;
|
||||
text-align: center;
|
||||
background-color: #F9FAFA;
|
||||
border-top-left-radius: calc(0.75rem - 1px);
|
||||
border-top-right-radius: calc(0.75rem - 1px);
|
||||
}
|
||||
.placeholder {
|
||||
font-size: 72px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script type="text/javascript" src="/shop-by-category/index.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
<div class="shop-by-category-content">
|
||||
<div class="category-slideshow">
|
||||
{% if slideshow %}
|
||||
<!-- slideshow -->
|
||||
{{ web_block(
|
||||
"Hero Slider",
|
||||
values=slideshow,
|
||||
add_container=0,
|
||||
add_top_padding=0,
|
||||
add_bottom_padding=0,
|
||||
) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="category-tabs">
|
||||
{% if tabs %}
|
||||
<!-- tabs -->
|
||||
{{ web_block(
|
||||
"Section with Tabs",
|
||||
values=tabs,
|
||||
add_container=0,
|
||||
add_top_padding=0,
|
||||
add_bottom_padding=0
|
||||
) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
12
erpnext/www/shop-by-category/index.js
Normal file
12
erpnext/www/shop-by-category/index.js
Normal file
@@ -0,0 +1,12 @@
|
||||
$(() => {
|
||||
$('.category-card').on('click', (e) => {
|
||||
let category_type = e.currentTarget.dataset.type;
|
||||
let category_name = e.currentTarget.dataset.name;
|
||||
|
||||
if (category_type != "item_group") {
|
||||
let filters = {};
|
||||
filters[category_type] = [category_name];
|
||||
window.location.href = "/all-products?field_filters=" + JSON.stringify(filters);
|
||||
}
|
||||
});
|
||||
});
|
||||
73
erpnext/www/shop-by-category/index.py
Normal file
73
erpnext/www/shop-by-category/index.py
Normal file
@@ -0,0 +1,73 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
||||
sitemap = 1
|
||||
|
||||
def get_context(context):
|
||||
settings = frappe.get_doc("E Commerce Settings")
|
||||
context.categories_enabled = settings.enable_field_filters
|
||||
|
||||
if context.categories_enabled:
|
||||
categories = [row.fieldname for row in settings.filter_fields]
|
||||
context.tabs = get_tabs(categories)
|
||||
|
||||
if settings.slideshow:
|
||||
context.slideshow = get_slideshow(settings.slideshow)
|
||||
|
||||
context.no_cache = 1
|
||||
|
||||
def get_slideshow(slideshow):
|
||||
values = {
|
||||
'show_indicators': 1,
|
||||
'show_controls': 1,
|
||||
'rounded': 1,
|
||||
'slider_name': "Categories"
|
||||
}
|
||||
slideshow = frappe.get_doc("Website Slideshow", slideshow)
|
||||
slides = slideshow.get({"doctype": "Website Slideshow Item"})
|
||||
for index, slide in enumerate(slides):
|
||||
values[f"slide_{index + 1}_image"] = slide.image
|
||||
values[f"slide_{index + 1}_title"] = slide.heading
|
||||
values[f"slide_{index + 1}_subtitle"] = slide.description
|
||||
values[f"slide_{index + 1}_theme"] = slide.get("theme") or "Light"
|
||||
values[f"slide_{index + 1}_content_align"] = slide.get("content_align") or "Centre"
|
||||
values[f"slide_{index + 1}_primary_action"] = slide.url
|
||||
|
||||
return values
|
||||
|
||||
def get_tabs(categories):
|
||||
tab_values = {
|
||||
'title': _("Shop by Category"),
|
||||
}
|
||||
|
||||
categorical_data = get_category_records(categories)
|
||||
for index, tab in enumerate(categorical_data):
|
||||
tab_values[f"tab_{index + 1}_title"] = frappe.unscrub(tab)
|
||||
# pre-render cards for each tab
|
||||
tab_values[f"tab_{index + 1}_content"] = frappe.render_template(
|
||||
"erpnext/www/shop-by-category/category_card_section.html",
|
||||
{"data": categorical_data[tab], "type": tab}
|
||||
)
|
||||
return tab_values
|
||||
|
||||
def get_category_records(categories):
|
||||
categorical_data = {}
|
||||
for category in categories:
|
||||
if category == "item_group":
|
||||
categorical_data["item_group"] = frappe.db.sql("""
|
||||
Select name, parent_item_group, is_group, image, route
|
||||
from `tabItem Group`
|
||||
where parent_item_group='All Item Groups'
|
||||
and show_in_website=1""", as_dict=1)
|
||||
else:
|
||||
doctype = frappe.unscrub(category)
|
||||
fields = ["name"]
|
||||
if frappe.get_meta(doctype, cached=True).get_field("image"):
|
||||
fields += ["image"]
|
||||
|
||||
categorical_data[category] = frappe.db.sql("""
|
||||
Select {fields}
|
||||
from `tab{doctype}`""".format(doctype=doctype, fields=",".join(fields)), as_dict=1)
|
||||
|
||||
return categorical_data
|
||||
|
||||
Reference in New Issue
Block a user