diff --git a/productcomments.php b/productcomments.php index 851d063c..33c1a65a 100644 --- a/productcomments.php +++ b/productcomments.php @@ -974,8 +974,24 @@ private function renderProductCommentsList($product) $commentRepository = $this->get('product_comment_repository'); $averageGrade = $commentRepository->getAverageGrade($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); $commentsNb = $commentRepository->getCommentsNumber($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); + $summaryGrades = $commentRepository->getSummaryGrades($product->id, (bool) Configuration::get('PRODUCT_COMMENTS_MODERATE')); $isPostAllowed = $commentRepository->isPostAllowed($product->id, (int) $this->context->cookie->id_customer, (int) $this->context->cookie->id_guest); + $summary = [ + 5 => ['count' => 0, 'percent' => 0], + 4 => ['count' => 0, 'percent' => 0], + 3 => ['count' => 0, 'percent' => 0], + 2 => ['count' => 0, 'percent' => 0], + 1 => ['count' => 0, 'percent' => 0], + ]; + + foreach ($summaryGrades as $grade) { + $summary[(int) $grade['grade']] = [ + 'count' => (int) $grade['count'], + 'percent' => (100 / $commentsNb) * (int) $grade['count'], + ]; + } + /* configure pagination */ $commentsTotalPages = 0; $commentsPerPage = (int) Configuration::get('PRODUCT_COMMENTS_COMMENTS_PER_PAGE'); @@ -986,6 +1002,7 @@ private function renderProductCommentsList($product) $this->context->smarty->assign([ 'post_allowed' => $isPostAllowed, 'usefulness_enabled' => Configuration::get('PRODUCT_COMMENTS_USEFULNESS'), + 'summary' => $summary, 'average_grade' => $averageGrade, 'nb_comments' => $commentsNb, 'list_comments_url' => $this->context->link->getModuleLink( diff --git a/src/Repository/ProductCommentRepository.php b/src/Repository/ProductCommentRepository.php index 88db9688..8904c2bd 100644 --- a/src/Repository/ProductCommentRepository.php +++ b/src/Repository/ProductCommentRepository.php @@ -219,6 +219,36 @@ public function getAverageGrade($productId, $validatedOnly) return (float) $qb->execute()->fetch(\PDO::FETCH_COLUMN); } + /** + * @param int $productId + * @param bool $validatedOnly + * + * @return array + */ + public function getSummaryGrades($productId, $validatedOnly) + { + /** @var QueryBuilder $qb */ + $qb = $this->connection->createQueryBuilder(); + $qb + ->select('pc.grade, COUNT(*) as count') + ->from($this->databasePrefix . 'product_comment', 'pc') + ->andWhere('pc.id_product = :id_product') + ->andWhere('pc.deleted = :deleted') + ->setParameter('deleted', 0) + ->setParameter('id_product', $productId) + ->groupBy('pc.grade') + ; + + if ($validatedOnly) { + $qb + ->andWhere('pc.validate = :validate') + ->setParameter('validate', 1) + ; + } + + return $qb->execute()->fetchAll(); + } + /** * @param int $langId * @param int $shopId diff --git a/views/css/productcomments.css b/views/css/productcomments.css index be6a6086..32bde280 100644 --- a/views/css/productcomments.css +++ b/views/css/productcomments.css @@ -321,15 +321,6 @@ justify-content: space-between; } -#product-comments-list-header .comments-nb { - padding-left: 0; - padding-top: 3px; -} - -#product-comments-list-header .comments-nb .material-icons { - margin-right: 3px; -} - #product-comments-list .btn-comment { margin: 0 auto; display: block; @@ -675,3 +666,79 @@ #product-comments-list-pagination ul li.hidden { display: none; } + +/** + * Product comments summary + */ + +.product-comments-summary { + background: #fff; + padding: 1.5rem; + display: grid; + grid-template-columns: 1fr; + gap: 1rem; + margin-bottom: 1rem; +} + +.product-comments-summary__left { + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; +} + +.product-comments-summary__average-score { + font-size: 50px; + font-weight: 700; +} + +.product-comments-summary__stars { + margin-top: 0.5rem; + margin-bottom: 0.5rem; +} + +.product-comments-summary__stars .star-content { + margin: 0!important; +} + +.product-comments-summary__star-icon { + display: inline-block; + height: 1.25rem; + min-width: 1.5rem; + position: relative; +} + +.product-comments-summary__grade-item { + display: flex; + align-items: center; + margin-bottom: .5rem; +} + +.product-comments-summary__grade-label { + display: flex; + justify-content: center; + margin-right: .5rem; + width: 40px; +} + +.product-comments-summary__grade-value { + font-weight: 600; +} + +.product-comments-summary__progress { + flex-grow: 1; + height: 10px; + margin-bottom: 0; +} + +.product-comments-summary__stats { + text-align: right; + width: 50px; + margin-left: 1rem; +} + +@media (min-width: 768px) { + .product-comments-summary { + grid-template-columns: 4fr 8fr; + } +} diff --git a/views/js/list-comments.js b/views/js/list-comments.js index 297f1164..43d2fdd1 100644 --- a/views/js/list-comments.js +++ b/views/js/list-comments.js @@ -39,6 +39,7 @@ jQuery(document).ready(function () { const nextCount = totalPages + 1; const gapText = '…'; + $('.product-comments-summary__stars .grade-stars').rating(); $('#product-comments-list .grade-stars').rating(); $('.product-comments-additional-info .grade-stars').rating(); @@ -47,6 +48,7 @@ jQuery(document).ready(function () { }) document.addEventListener('updateRating', function() { + $('.product-comments-summary__stars .grade-stars').rating(); $('#product-comments-list .grade-stars').rating(); $('.product-comments-additional-info .grade-stars').rating(); }); diff --git a/views/templates/hook/product-comments-list.tpl b/views/templates/hook/product-comments-list.tpl index 1f353544..5d3df23c 100644 --- a/views/templates/hook/product-comments-list.tpl +++ b/views/templates/hook/product-comments-list.tpl @@ -28,12 +28,77 @@
-
- - {l s='Comments' d='Modules.Productcomments.Shop'} ({$nb_comments}) -
- {include file='module:productcomments/views/templates/hook/average-grade-stars.tpl' grade=$average_grade} +

+ {l s='Comments' d='Modules.Productcomments.Shop'} +

+ + {if $nb_comments > 0 && $post_allowed} +
+ +
+ {/if}
+ +{if $nb_comments > 0} +
+ +
+
+ {$average_grade|number_format:1} + /5.0 +
+ +
+
+
+ +
+ {if $nb_comments > 1} + {l s='Based on %s opinions' sprintf=[$nb_comments] d='Modules.Productcomments.Shop'} + {else} + {l s='Based on %s opinion' sprintf=[$nb_comments] d='Modules.Productcomments.Shop'} + {/if} +
+
+ +
+
+ {foreach $summary as $grade => $details} +
+
+ {$grade} +
+ +
+
+ +
+
+
+ +
+ {$details.count} +
+
+ {/foreach} +
+
+
+{else} + {include file='module:productcomments/views/templates/hook/empty-product-comment.tpl'} +{/if} {include file='module:productcomments/views/templates/hook/product-comment-item-prototype.tpl' assign="comment_prototype"} {include file='module:productcomments/views/templates/hook/empty-product-comment.tpl'} @@ -61,12 +126,6 @@ {/if} - {if $post_allowed && $nb_comments != 0} - - {/if} {* Appreciation post error modal *}