feat: (wip) Ratings and Reviews
- Added Ratings and Reviews section in Item full page view - Added provision to write a review with popup - Created Item Review Doctype to store User-Item unique reviews - Added privision to enable/disable wishlist and reviews in e commerce settings - Hide cart and wishlist actions everywhere (even navbar) depending on settings - Moved some more inline css to scss - Small logic fixes TODO: Reviews full page view with paging
This commit is contained in:
parent
07d7cf01b4
commit
b15ff57a66
@ -20,6 +20,10 @@
|
||||
"show_quantity_in_website",
|
||||
"show_apply_coupon_code_in_website",
|
||||
"allow_items_not_in_stock",
|
||||
"add_ons_section",
|
||||
"enable_wishlist",
|
||||
"column_break_18",
|
||||
"enable_reviews",
|
||||
"section_break_18",
|
||||
"company",
|
||||
"price_list",
|
||||
@ -274,12 +278,34 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Slideshow",
|
||||
"options": "Website Slideshow"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "add_ons_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Add-ons"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "enable_wishlist",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable Wishlist"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_18",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "enable_reviews",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable Reviews and Ratings"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-03-01 20:24:56.548673",
|
||||
"modified": "2021-03-23 17:15:01.956630",
|
||||
"modified_by": "Administrator",
|
||||
"module": "E-commerce",
|
||||
"name": "E Commerce Settings",
|
||||
|
0
erpnext/e_commerce/doctype/item_review/__init__.py
Normal file
0
erpnext/e_commerce/doctype/item_review/__init__.py
Normal file
8
erpnext/e_commerce/doctype/item_review/item_review.js
Normal file
8
erpnext/e_commerce/doctype/item_review/item_review.js
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Item Review', {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
});
|
112
erpnext/e_commerce/doctype/item_review/item_review.json
Normal file
112
erpnext/e_commerce/doctype/item_review/item_review.json
Normal file
@ -0,0 +1,112 @@
|
||||
{
|
||||
"actions": [],
|
||||
"beta": 1,
|
||||
"creation": "2021-03-23 16:47:26.542226",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"website_item",
|
||||
"user",
|
||||
"customer",
|
||||
"column_break_3",
|
||||
"item",
|
||||
"published_on",
|
||||
"reviews_section",
|
||||
"review_title",
|
||||
"rating",
|
||||
"comment"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "website_item",
|
||||
"fieldtype": "Link",
|
||||
"label": "Website Item",
|
||||
"options": "Website Item"
|
||||
},
|
||||
{
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "User",
|
||||
"options": "User"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fetch_from": "website_item.item_code",
|
||||
"fieldname": "item",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Item",
|
||||
"options": "Item",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "reviews_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Reviews"
|
||||
},
|
||||
{
|
||||
"fieldname": "rating",
|
||||
"fieldtype": "Rating",
|
||||
"in_list_view": 1,
|
||||
"label": "Rating"
|
||||
},
|
||||
{
|
||||
"fieldname": "comment",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Comment"
|
||||
},
|
||||
{
|
||||
"fieldname": "review_title",
|
||||
"fieldtype": "Data",
|
||||
"label": "Review Title"
|
||||
},
|
||||
{
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"label": "Customer",
|
||||
"options": "Customer"
|
||||
},
|
||||
{
|
||||
"fieldname": "published_on",
|
||||
"fieldtype": "Data",
|
||||
"label": "Published on"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2021-03-24 22:27:28.094535",
|
||||
"modified_by": "Administrator",
|
||||
"module": "E-commerce",
|
||||
"name": "Item Review",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1
|
||||
},
|
||||
{
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Website Manager",
|
||||
"share": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
47
erpnext/e_commerce/doctype/item_review/item_review.py
Normal file
47
erpnext/e_commerce/doctype/item_review/item_review.py
Normal file
@ -0,0 +1,47 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from datetime import datetime
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
from frappe.contacts.doctype.contact.contact import get_contact_name
|
||||
|
||||
class ItemReview(Document):
|
||||
pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_item_review(web_item, title, rating, comment=None):
|
||||
""" Add an Item Review by a user if non-existent. """
|
||||
if not frappe.db.exists("Item Review", {"user": frappe.session.user, "website_item": web_item}):
|
||||
doc = frappe.get_doc({
|
||||
"doctype": "Item Review",
|
||||
"user": frappe.session.user,
|
||||
"customer": get_customer(),
|
||||
"website_item": web_item,
|
||||
"item": frappe.db.get_value("Website Item", web_item, "item_code"),
|
||||
"review_title": title,
|
||||
"rating": rating,
|
||||
"comment": comment
|
||||
})
|
||||
doc.published_on = datetime.today().strftime("%d %B %Y")
|
||||
doc.insert()
|
||||
|
||||
def get_customer():
|
||||
user = frappe.session.user
|
||||
contact_name = get_contact_name(user)
|
||||
customer = None
|
||||
|
||||
if contact_name:
|
||||
contact = frappe.get_doc('Contact', contact_name)
|
||||
for link in contact.links:
|
||||
if link.link_doctype == "Customer":
|
||||
customer = link.link_name
|
||||
break
|
||||
|
||||
if customer:
|
||||
return frappe.db.get_value("Customer", customer)
|
||||
else:
|
||||
frappe.throw("You are not verified to write a review yet. Please contact us for verification.")
|
10
erpnext/e_commerce/doctype/item_review/test_item_review.py
Normal file
10
erpnext/e_commerce/doctype/item_review/test_item_review.py
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestItemReview(unittest.TestCase):
|
||||
pass
|
@ -176,6 +176,7 @@ class WebsiteItem(WebsiteGenerator):
|
||||
self.set_metatags(context)
|
||||
self.set_shopping_cart_data(context)
|
||||
self.get_product_details_section(context)
|
||||
self.get_reviews(context)
|
||||
|
||||
context.wished = False
|
||||
if frappe.db.exists("Wishlist Items", {"item_code": self.item_code, "parent": frappe.session.user}):
|
||||
@ -340,7 +341,7 @@ class WebsiteItem(WebsiteGenerator):
|
||||
def get_product_details_section(self, context):
|
||||
""" Get section with tabs or website specifications. """
|
||||
context.show_tabs = self.show_tabbed_section
|
||||
if self.show_tabbed_section and self.tabs:
|
||||
if self.show_tabbed_section and (self.tabs or self.website_specifications):
|
||||
context.tabs = self.get_tabs()
|
||||
else:
|
||||
context.website_specifications = self.website_specifications
|
||||
@ -361,6 +362,28 @@ class WebsiteItem(WebsiteGenerator):
|
||||
|
||||
return tab_values
|
||||
|
||||
def get_reviews(self, context):
|
||||
if context.shopping_cart.cart_settings.enable_reviews:
|
||||
context.reviews = frappe.db.get_all("Item Review", filters={"item": self.item_code},
|
||||
fields=["*"], limit=4)
|
||||
|
||||
rating_data = frappe.db.get_all("Item Review", filters={"item": self.item_code},
|
||||
fields=["avg(rating) as average, count(*) as total"])[0]
|
||||
context.average_rating = rating_data.average
|
||||
context.average_whole_rating = flt(context.average_rating, 0)
|
||||
|
||||
# get % of reviews per rating
|
||||
reviews_per_rating = []
|
||||
for i in range(1,6):
|
||||
count = frappe.db.get_all("Item Review", filters={"item": self.item_code, "rating": i},
|
||||
fields=["count(*) as count"])[0].count
|
||||
|
||||
percent = flt((count / rating_data.total or 1) * 100, 0) if count else 0
|
||||
reviews_per_rating.append(percent)
|
||||
|
||||
context.reviews_per_rating = reviews_per_rating
|
||||
context.total_reviews = rating_data.total
|
||||
|
||||
def invalidate_cache_for_web_item(doc):
|
||||
"""Invalidate Website Item Group cache and rebuild ItemVariantsCacheManager."""
|
||||
from erpnext.stock.doctype.item.item import invalidate_item_variants_cache_for_website
|
||||
|
@ -34,7 +34,7 @@
|
||||
"in_create": 1,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2021-03-18 16:10:29.534522",
|
||||
"modified": "2021-03-24 20:42:58.402031",
|
||||
"modified_by": "Administrator",
|
||||
"module": "E-commerce",
|
||||
"name": "Wishlist",
|
||||
@ -55,7 +55,7 @@
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Stock Manager",
|
||||
"role": "Website Manager",
|
||||
"share": 1
|
||||
}
|
||||
],
|
||||
|
@ -69,7 +69,8 @@ class ProductQuery:
|
||||
item.formatted_price = (product_info.get('price') or {}).get('formatted_price')
|
||||
item.price = product_info['price'].get('price_list_rate')
|
||||
|
||||
if self.settings.show_stock_availability and item.get("website_warehouse"):
|
||||
if self.settings.show_stock_availability:
|
||||
if item.get("website_warehouse"):
|
||||
stock_qty = frappe.utils.flt(
|
||||
frappe.db.get_value("Bin",
|
||||
{
|
||||
@ -79,6 +80,8 @@ class ProductQuery:
|
||||
"actual_qty")
|
||||
)
|
||||
item.in_stock = "green" if stock_qty else "red"
|
||||
elif not frappe.db.get_value("Item", item.item_code, "is_stock_item"):
|
||||
item.in_stock = "green" # non-stock item will always be available
|
||||
|
||||
item.wished = False
|
||||
if frappe.db.exists("Wishlist Items", {"item_code": item.item_code, "parent": frappe.session.user}):
|
||||
|
@ -26,7 +26,7 @@
|
||||
{%- set item = frappe.get_doc("Item", item) -%}
|
||||
{{ item_card(
|
||||
item, is_featured=values['card_' + index + '_featured'],
|
||||
True, "Center"
|
||||
is_full_width=True, align="Center"
|
||||
) }}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
|
@ -135,7 +135,7 @@ body.product-page {
|
||||
|
||||
.item-card {
|
||||
padding: var(--padding-sm);
|
||||
min-width: 250px;
|
||||
min-width: 260px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -702,3 +702,71 @@ body.product-page {
|
||||
.item-website-specification {
|
||||
font-size: .875rem;
|
||||
}
|
||||
|
||||
.ratings-reviews-section {
|
||||
border-top: 1px solid #E2E6E9;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.reviews-header {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: var(--gray-800);
|
||||
}
|
||||
|
||||
.rating-summary-title {
|
||||
margin-top: 0.15rem;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.user-review-title {
|
||||
margin-top: 0.15rem;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.rating {
|
||||
--star-fill: var(--gray-300);
|
||||
.star-hover {
|
||||
--star-fill: var(--yellow-100);
|
||||
}
|
||||
.star-click {
|
||||
--star-fill: var(--yellow-300);
|
||||
}
|
||||
}
|
||||
|
||||
.review {
|
||||
max-width: 80%;
|
||||
line-height: 1.6;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 1px solid #E2E6E9;
|
||||
}
|
||||
|
||||
.review-signature {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
color: var(--gray-500);
|
||||
font-weight: 400;
|
||||
|
||||
.reviewer {
|
||||
padding-right: 8px;
|
||||
margin-right: 8px;
|
||||
border-right: 1px solid var(--gray-400);
|
||||
}
|
||||
}
|
||||
|
||||
.rating-progress-bar-section {
|
||||
padding-bottom: 2rem;
|
||||
border-bottom: 1px solid #E2E6E9;
|
||||
margin-right: -10px;
|
||||
|
||||
.rating-bar-title {
|
||||
margin-left: -15px;
|
||||
}
|
||||
|
||||
.rating-progress-bar {
|
||||
margin-bottom: 4px;
|
||||
height: 7px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ class ItemGroup(NestedSet, WebsiteGenerator):
|
||||
def get_context(self, context):
|
||||
context.show_search=True
|
||||
context.page_length = cint(frappe.db.get_single_value('E Commerce Settings', 'products_per_page')) or 6
|
||||
context.e_commerce_settings = frappe.get_cached_doc('E Commerce Settings', 'E Commerce Settings')
|
||||
context.search_link = '/product_search'
|
||||
|
||||
if frappe.form_dict:
|
||||
|
@ -37,6 +37,11 @@
|
||||
|
||||
<!-- Advanced Custom Website Content -->
|
||||
{{ doc.website_content or '' }}
|
||||
|
||||
<!-- Reviews and Comments -->
|
||||
{% if shopping_cart.cart_settings.enable_reviews %}
|
||||
{% include "templates/generators/item/item_reviews.html"%}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -57,6 +57,7 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- Add to Wishlist -->
|
||||
{% if cart_settings.enable_wishlist %}
|
||||
<a href="/wishlist"
|
||||
class="btn btn-view-in-wishlist hidden"
|
||||
role="button"
|
||||
@ -83,8 +84,10 @@
|
||||
</span>
|
||||
{{ _("Add to Wishlist") }}
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Contact Us -->
|
||||
{% if cart_settings.show_contact_us_button %}
|
||||
{% include "templates/generators/item/item_inquiry.html" %}
|
||||
{% endif %}
|
||||
|
127
erpnext/templates/generators/item/item_reviews.html
Normal file
127
erpnext/templates/generators/item/item_reviews.html
Normal file
@ -0,0 +1,127 @@
|
||||
{% from "erpnext/templates/includes/macros.html" import ratings_with_title %}
|
||||
|
||||
<div class="mt-8 ratings-reviews-section">
|
||||
<!-- Ratings Summary -->
|
||||
<div class="col-md-4 order-md-1 mt-8" style="max-width: 300px;">
|
||||
<h2 class="reviews-header">
|
||||
{{ _("Customer Ratings") }}
|
||||
</h2>
|
||||
|
||||
{% if reviews %}
|
||||
{% set rating_title = frappe.utils.cstr(average_rating) + " " + _("out of 5") %}
|
||||
{{ ratings_with_title(average_whole_rating, rating_title, "lg", "rating-summary-title") }}
|
||||
{% endif %}
|
||||
|
||||
<!-- Rating Progress Bars -->
|
||||
<div class="rating-progress-bar-section">
|
||||
{% for percent in reviews_per_rating %}
|
||||
<div class="mt-4 col-sm-4 small rating-bar-title">
|
||||
{{ loop.index }} star
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<div class="progress rating-progress-bar" title="{{ percent }} % of reviews are {{ loop.index }} star">
|
||||
<div class="progress-bar" role="progressbar"
|
||||
aria-valuenow="{{ percent }}"
|
||||
aria-valuemin="0" aria-valuemax="100"
|
||||
style="width: {{ percent }}%; background-color: var(--text-on-green);">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-1 small">
|
||||
{{ percent }}%
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Write a Review for legitimate users -->
|
||||
{% if frappe.session.user != "Guest" %}
|
||||
<button class="btn btn-light btn-write-review mr-2 mt-4 mb-4 w-100">
|
||||
{{ _("Write a Review") }}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Reviews and Comments -->
|
||||
<div class="col-12 order-2 col-md-9 order-md-2 mt-8 ml-16">
|
||||
<h2 class="reviews-header">
|
||||
{{ _("Reviews") }}
|
||||
</h2>
|
||||
{% if reviews %}
|
||||
{% for review in reviews %}
|
||||
<!-- User review -->
|
||||
<div class="mb-3 review">
|
||||
{{ ratings_with_title(review.rating, _(review.review_title), "md", "user-review-title") }}
|
||||
|
||||
<div class="review-signature">
|
||||
<span class="reviewer">{{ _(review.customer) }}</span>
|
||||
<span>{{ review.published_on }}</span>
|
||||
</div>
|
||||
<div class="product-description mb-4 mt-4">
|
||||
<p>
|
||||
{{ _(review.comment) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if total_reviews > 4 %}
|
||||
<div class="mt-6 mb-6"style="color: var(--primary);">
|
||||
<a href="/reviews">{{ _("View all reviews") }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<h6 class="text-muted mt-6">
|
||||
{{ _("No Reviews") }}
|
||||
</h6>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
frappe.ready(() => {
|
||||
$('.page_content').on('click', '.btn-write-review', (e) => {
|
||||
// Bind action on write a review button
|
||||
const $btn = $(e.currentTarget);
|
||||
|
||||
let d = new frappe.ui.Dialog({
|
||||
title: __("Write a Review"),
|
||||
fields: [
|
||||
{fieldname: "title", fieldtype: "Data", label: "Headline", reqd: 1},
|
||||
{fieldname: "rating", fieldtype: "Rating", label: "Overall Rating", reqd: 1},
|
||||
{fieldtype: "Section Break"},
|
||||
{fieldname: "comment", fieldtype: "Small Text", label: "Your Review"}
|
||||
],
|
||||
primary_action: function() {
|
||||
var data = d.get_values();
|
||||
$btn.prop('hidden', true);
|
||||
frappe.call({
|
||||
method: "erpnext.e_commerce.doctype.item_review.item_review.add_item_review",
|
||||
args: {
|
||||
web_item: "{{ doc.name }}",
|
||||
title: data.title,
|
||||
rating: data.rating,
|
||||
comment: data.comment
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: __("Submitting Review ..."),
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
frappe.msgprint({
|
||||
message: __("Thank you for submitting your review"),
|
||||
title: __("Review Submitted"),
|
||||
indicator: "green"
|
||||
});
|
||||
d.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
primary_action_label: __('Submit')
|
||||
});
|
||||
d.show();
|
||||
});
|
||||
});
|
||||
</script>
|
@ -1,8 +1,9 @@
|
||||
{% if website_specifications -%}
|
||||
<div class="row mt-5 item-website-specification">
|
||||
<!-- Is reused to render within tabs as well as independently -->
|
||||
{% if website_specifications %}
|
||||
<div class="mt-5 item-website-specification">
|
||||
<div class="col-md-11">
|
||||
{% if not show_tabs %}
|
||||
<h2 class="product-title mb-5">Product Details</h2>
|
||||
<h3 class="product-title mb-5 mt-8">Product Details</h3>
|
||||
{% endif %}
|
||||
<table class="table table-bordered table-hover">
|
||||
{% for d in website_specifications -%}
|
||||
@ -14,4 +15,4 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{% endif %}
|
||||
|
@ -59,7 +59,7 @@
|
||||
|
||||
{% endmacro %}
|
||||
|
||||
{%- macro item_card(item, is_featured=False, is_full_width=False, align="Left") -%}
|
||||
{%- macro item_card(item, settings=None, is_featured=False, is_full_width=False, align="Left") -%}
|
||||
{%- set align_items_class = resolve_class({
|
||||
'align-items-end': align == 'Right',
|
||||
'align-items-center': align == 'Center',
|
||||
@ -79,12 +79,12 @@
|
||||
<img class="card-img" src="{{ image }}" alt="{{ title }}">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{{ item_card_body(title, description, item, is_featured, align) }}
|
||||
{{ item_card_body(title, settings, description, item, is_featured, align) }}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="col-md-12">
|
||||
{{ item_card_body(title, description, item, is_featured, align) }}
|
||||
{{ item_card_body(title, settings, description, item, is_featured, align) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@ -105,13 +105,13 @@
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
{{ item_card_body(title, description, item, is_featured, align) }}
|
||||
{{ item_card_body(title, settings, description, item, is_featured, align) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro item_card_body(title, description, item, is_featured, align) -%}
|
||||
{%- macro item_card_body(title, settings, description, item, is_featured, align) -%}
|
||||
{%- set align_class = resolve_class({
|
||||
'text-right': align == 'Right',
|
||||
'text-center': align == 'Center' and not is_featured,
|
||||
@ -125,7 +125,7 @@
|
||||
{% if item.in_stock %}
|
||||
<span class="indicator {{ item.in_stock }} card-indicator"></span>
|
||||
{% endif %}
|
||||
{% if not item.has_variants %}
|
||||
{% if not item.has_variants and settings.enable_wishlist %}
|
||||
<div class="like-action"
|
||||
data-item-code="{{ item.item_code }}"
|
||||
data-price="{{ item.price }}"
|
||||
@ -152,7 +152,7 @@
|
||||
{{ _('Explore') }}
|
||||
</div>
|
||||
</a>
|
||||
{% else %}
|
||||
{% elif settings.enabled %}
|
||||
<div id="{{ item.name }}" class="btn btn-sm btn-add-to-cart-list not-added"
|
||||
data-item-code="{{ item.item_code }}">
|
||||
{{ _('Add to Cart') }}
|
||||
@ -220,3 +220,19 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro ratings_with_title(avg_rating, title, size, rating_header_class) -%}
|
||||
<div style="display: flex;">
|
||||
<div class="rating">
|
||||
{% for i in range(1,6) %}
|
||||
{% set fill_class = 'star-click' if i <= avg_rating else '' %}
|
||||
<svg class="icon icon-{{ size }} {{ fill_class }}">
|
||||
<use href="#icon-star"></use>
|
||||
</svg>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<p class="ml-4 {{ rating_header_class }}">
|
||||
<span>{{ title }}</span>
|
||||
</p>
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
|
@ -9,12 +9,14 @@
|
||||
<span class="badge badge-primary shopping-badge" id="cart-count"></span>
|
||||
</a>
|
||||
</li>
|
||||
{% if frappe.db.get_single_value("E Commerce Settings", "enable_wishlist") %}
|
||||
<li class="wishlist wishlist-icon hidden">
|
||||
<a class="nav-link" href="/wishlist">
|
||||
<svg class="icon icon-lg">
|
||||
<use href="#icon-heart"></use>
|
||||
<use href="#icon-heart-active"></use>
|
||||
</svg>
|
||||
<span class="badge badge-primary shopping-badge" id="wish-count"></span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
0
erpnext/templates/pages/reviews.html
Normal file
0
erpnext/templates/pages/reviews.html
Normal file
@ -1,4 +1,4 @@
|
||||
{% from "erpnext/templates/includes/macros.html" import item_card, item_card_body %}
|
||||
|
||||
{{ item_card(item) }}
|
||||
{{ item_card(item, e_commerce_settings) }}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user