<style type="text/css">
.rating-range{
font-weight: bold;
margin-top: 0px;
}
.progress-container {
display: flex;
justify-content: flex-start;
align-items: center;
gap: 12px;
}
.progress-container::before {
content: attr(data-count);
font-size: 12px;
}
.progress {
flex: 1;
display: flex;
height: 0.7rem;
overflow: hidden;
font-size: .75rem;
background-color: #e9ecef;
border-radius: 0.25rem;
}
.progress-bar {
display: flex;
flex-direction: column;
justify-content: center;
overflow: hidden;
color: #fff;
text-align: center;
white-space: nowrap;
background-color: #DE5D50;
transition: width .6s ease;
}
.reply {
background-color: #F8F9FA;
}
{# For Stars #}
.star-block {
position: relative;
display: inline-block;
}
.star {
font-size: 20px;
color: rgba(60,64,67,.38);
cursor: pointer;
transition: color 0.3s;
}
.star:hover,
.star.active {
color: #DE5D50;
}
.star-half {
display: inline-flex;
font-size: 20px;
color: rgba(60,64,67,.38);
cursor: pointer;
transition: color 0.3s;
}
.star-half > div:first-child {
overflow: hidden;
width: 10px;
z-index: 1;
color: #DE5D50;
}
.star-half > div:last-child {
position: relative;
margin-left:-10px;
}
.customer-reviews .star{
font-size: 15px;
padding: 1px;
}
.customer-reviews span{
padding-left: 10px;
}
.customer-reviews .remarks{
font-size: 12px;
}
{# For Profile image #}
.profile-placeholder {
width: 30px; /* Adjust the size as needed */
height: 30px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 15px; /* Adjust the font size as needed */
font-weight: bold;
color: #ffffff; /* Text color, change as needed */
}
.initials {
text-align: center;
line-height: 1; /* Center the text vertically */
}
.form-error-message{
color: #c04949;
}
#product_rating_area .ec-rectHeading.is_active i {
transform: rotate(180deg);
}
</style>
<script>
$(function() {
// append rating area
$('#product_rating_area').appendTo($('.ec-layoutRole__main, .ec-layoutRole__mainWithColumn, .ec-layoutRole__mainBetweenColumn'));
// rating submit
$('#star_submit').on('click', function(){
var ratingStar = $('#rating_star').val();
// var sex = $('input[name="rating[Sex]"]:checked').val();
var title = $('#rating_title').val();
var formError = false;
if(!ratingStar){
$('#star-err').show();
formError = true;
}else{
$('#star-err').hide();
}
if(!title){
$('#title-err').show();
formError = true;
}else{
$('#title-err').hide();
}
if(formError){
return;
}
$('#star_form').submit();
});
// show hide ratings
$('#product_rating_area .ec-rectHeading').on('click', function() {
$content = $('#ratingContent');
if ($content.css('display') == 'none') {
$(this).addClass('is_active');
$content.addClass('is_active');
$content.slideDown(300);
} else {
$(this).removeClass('is_active');
$content.removeClass('is_active');
$content.slideUp(300);
}
return false;
});
// show rating stars under title
var stars = "<div class='m-1'>";
var averageRating = '0.0';
var avg = Math.ceil(averageRating);
if(avg > 0){
for(var i = 1; i <= avg; i++){
if(i>averageRating){
stars += '<span class="star-half"><div>★</div><div>★</div></span>';
}else{
stars += '<span class="star active">★</span>';
}
}
}
var leftAvg = 5 - avg;
if(leftAvg > 0){
for(var i = 1; i <= leftAvg; i++){
stars += '<span class="star">★</span>';
}
}
stars += "<span class='average-number'> 0.0(0件)</span>";
stars += '</div>';
$('.ec-productRole__title').after(stars);
});
let selectedRating = 0;
function rateApp(rating) {
selectedRating = rating;
updateRatingDisplay(rating);
$('#rating_star').val(rating);
$('#ratingModal').modal('show');
}
function onHover(rating){
updateRatingDisplay(rating);
}
function hoverOut(){
updateRatingDisplay(selectedRating);
}
function updateRatingDisplay(rating) {
const stars = document.querySelectorAll('.rating');
stars.forEach((star, index) => {
star.classList.toggle('active', index < rating);
});
// rating for modal star
const modalStars = document.querySelectorAll('.modal-rating');
modalStars.forEach((star, index) => {
star.classList.toggle('active', index < rating);
});
}
function ratingList(productId){
$('#reviewModal').modal('show')
}
</script>
<div id="product_rating_area">
<div class="ec-role">
<div class="ec-rectHeading is_active">
<h4>
レビュー
<span style="float: right" class="chevron pull-right">
<i class="fas fa-angle-up fa-lg"></i>
</span>
</h4>
</div>
<div id="ratingContent" class="p-2">
<div class="row mb-2">
<div class="col-6">
<span class="star rating" onclick="rateApp(1)" onmouseover="onHover(1)" onmouseout="hoverOut()">★</span>
<span class="star rating" onclick="rateApp(2)" onmouseover="onHover(2)" onmouseout="hoverOut()">★</span>
<span class="star rating" onclick="rateApp(3)" onmouseover="onHover(3)" onmouseout="hoverOut()">★</span>
<span class="star rating" onclick="rateApp(4)" onmouseover="onHover(4)" onmouseout="hoverOut()">★</span>
<span class="star rating" onclick="rateApp(5)" onmouseover="onHover(5)" onmouseout="hoverOut()">★</span>
</div>
<div class="col-6 text-right">
<button class="ec-inlineBtn--action" data-bs-toggle="modal" data-bs-target="#ratingModal">レビューを書く</button>
</div>
</div>
{#{% if totalRatings > 3 %}
<div class="mb-2">
<h5 class="d-inline">全てのレビューを見る</h5>
<a class="mt-1" onclick="ratingList({{Product.id}})" class="btn"><i class="fa fa-arrow-right"></i></a>
</div>
{% endif %}
{% if totalRatings > 0 %}
<div class="row">
<div class="col-md-2">
<h1 class="rating-range">{{ averageRating|number_format(1) }}</h1>
{% set avg = averageRating|round(0, 'ceil') %}
{% if avg > 0 %}
{% for i in 1..avg %}
{% if loop.last == true and i > averageRating %}
<span class="star-half">
<div>★</div><div>★</div>
</span>
{% else %}
<span class="star active">★</span>
{% endif %}
{% endfor %}
{% endif %}
{% set rAvg = 5 - avg %}
{% if rAvg > 0 %}
{% for j in 1..rAvg %}<span class="star">★</span>{% endfor %}
{% endif %}
<p>{{ totalRatings }} reviews</p>
</div>
<div class="col-md-10">
<div class="progress-container" data-count="5">
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{ fiveStar }}%;">
<span class="sr-only"></span>
</div>
</div>
</div>
<div class="progress-container" data-count="4">
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{ fourStar }}%;">
<span class="sr-only"></span>
</div>
</div>
</div>
<div class="progress-container" data-count="3">
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{ threeStar }}%;">
<span class="sr-only"></span>
</div>
</div>
</div>
<div class="progress-container" data-count="2">
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{ twoStar }}%;">
<span class="sr-only"></span>
</div>
</div>
</div>
<div class="progress-container" data-count="1">
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{ oneStar }}%;">
<span class="sr-only"></span>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% for rating in ratings %}
<div class="row mt-3 customer-reviews">
<div class="col-md-12">
<div class="user-review" style="display: flex;">
{% set randomColor = rating.getRandomColor() %}
<div class="profile-placeholder" style="background-color: {{ randomColor }}">
<div class="initials">{{ rating.customer_name|first|upper }}</div>
</div>
<span class="mt-2">{{ rating.customer_name }}</span>
</div>
</div>
<div class="mt-2">
{% for i in 1..rating.star %}<span class="star active">★</span>{% endfor %}
{% set noStar = 5 - rating.star %}
{% if noStar > 0 %}
{% for j in 1..noStar %}<span class="star">★</span>{% endfor %}
{% endif %}
<span class='remarks'>{{ rating.create_date|date_min }}</span>
</div>
<h6 class="mt-1 mb-1 font-weight-bold">{{ rating.title }}</h6>
<p class="remarks">{{ rating.remarks }}</p>
{% if config.getCanReply() and rating.reply != "" %}
<div class="m-2"><p class="p-2 remarks reply">{{ rating.reply }}</p></div>
{% endif %}
</div>
{% endfor %}
{% if totalRatings > 3 %}
<button type="button" class="btn btn-light mt-3" onclick="ratingList({{Product.id}})">全てのレビューを見る</button>
{% endif %}#}
</div>
</div>
<div class="modal fade" id="ratingModal" tabindex="-1" role="dialog"
aria-labelledby="ratingModal" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{{ Product.name }}</h5>
<button class="btn-close" type="button" data-bs-dismiss="modal" aria-label="Close">
</button>
</div>
<form action="#" method="post" id="star_form" name="star_form">
<div class="modal-body">
<div class="row">
<div class="col text-center">
<span class="star modal-rating" onclick="rateApp(1)" onmouseover="onHover(1)" onmouseout="hoverOut()">★</span>
<span class="star modal-rating" onclick="rateApp(2)" onmouseover="onHover(2)" onmouseout="hoverOut()">★</span>
<span class="star modal-rating" onclick="rateApp(3)" onmouseover="onHover(3)" onmouseout="hoverOut()">★</span>
<span class="star modal-rating" onclick="rateApp(4)" onmouseover="onHover(4)" onmouseout="hoverOut()">★</span>
<span class="star modal-rating" onclick="rateApp(5)" onmouseover="onHover(5)" onmouseout="hoverOut()">★</span>
</div>
</div>
<div id='star-err' class="row" style="display: none;">
<div class="col text-center">
<span class="form-error-icon badge bg-danger text-uppercase">エラー</span> <span class="form-error-message">入力されていません。</span>
</div>
</div>
<div class="mb-2"></div>
{#{% if customer is null %}
<div class="row mb-2">
<div class="col-3">
<label class="ec-label form-label" for="rating_customer_name">投稿者名</label>
</div>
<div class="col">
<input type="text" id="rating_customer_name" name="rating[customer_name]" placeholder="投稿者名" required="required" class="form-control" />
<div id='name-err' style="display: none;">
<span class="form-error-icon badge bg-danger text-uppercase">エラー</span>
<span class="form-error-message">入力されていません。</span>
</div>
</div>
</div>
<div class="row mb-2">
<div class="col-3">
<label class="ec-label form-label" for="rating_email">メール</label>
</div>
<div class="col">
<input type="email" id="rating_email" name="rating[email]" placeholder="例:ec-cube@example.com" required="required" class="form-control" />
<div id='email-err' style="display: none;">
<span class="form-error-icon badge bg-danger text-uppercase">エラー</span>
<span class="form-error-message">入力されていません。</span>
</div>
</div>
</div>
<div class="row mb-2">
<div class="col-3">
<legend class="ec-label col-form-label">性別</legend>
</div>
<div class="col">
<div id="rating_Sex"><div class="form-check form-check-inline"><input type="radio" id="rating_Sex_1" name="rating[Sex]" class="form-check-input" value="1" />
<label class="form-check-label" for="rating_Sex_1">男性</label></div><div class="form-check form-check-inline"><input type="radio" id="rating_Sex_2" name="rating[Sex]" class="form-check-input" value="2" />
<label class="form-check-label" for="rating_Sex_2">女性</label></div></div>
</div>
</div>
{% endif %}#}
<div class="row mb-2">
<div class="col-3">
<label class="ec-label form-label required" for="rating_title">タイトル</label>
</div>
<div class="col">
<input type="text" id="rating_title" name="rating[title]" required="required" placeholder="タイトル" class="form-control" />
<div id='title-err' style="display: none;">
<span class="form-error-icon badge bg-danger text-uppercase">エラー</span>
<span class="form-error-message">入力されていません。</span>
</div>
</div>
</div>
<div class="row">
<div class="col-3">
<label class="ec-label form-label required" for="rating_remarks">本文</label>
</div>
<div class="col">
<textarea id="rating_remarks" name="rating[remarks]" required="required" placeholder="本文" class="form-control"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button id="star_submit" type="button" class="ec-inlineBtn--action">投稿する</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="reviewModal" tabindex="-1" role="dialog"
aria-labelledby="reviewModal" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{{ Product.name }}</h5>
<button class="btn-close" type="button" data-bs-dismiss="modal" aria-label="Close">
</button>
</div>
<div class="modal-body" id='ratingList'>
</div>
</div>
</div>
</div>
</div>