app/Plugin/ProductRating42_dummy/Resource/template/default/rating.twig line 1

Open in your IDE?
  1. <style type="text/css">
  2.     .rating-range{
  3.         font-weight: bold;
  4.         margin-top: 0px;
  5.     }
  6.     .progress-container {
  7.         display: flex;
  8.         justify-content: flex-start;
  9.         align-items: center;
  10.         gap: 12px;
  11.     }
  12.     .progress-container::before {
  13.         content: attr(data-count);
  14.         font-size: 12px;
  15.     }
  16.     .progress {
  17.         flex: 1;
  18.         display: flex;
  19.         height: 0.7rem;
  20.         overflow: hidden;
  21.         font-size: .75rem;
  22.         background-color: #e9ecef;
  23.         border-radius: 0.25rem;
  24.     }
  25.     .progress-bar {
  26.         display: flex;
  27.         flex-direction: column;
  28.         justify-content: center;
  29.         overflow: hidden;
  30.         color: #fff;
  31.         text-align: center;
  32.         white-space: nowrap;
  33.         background-color: #DE5D50;
  34.         transition: width .6s ease;
  35.     }
  36.     .reply {
  37.         background-color: #F8F9FA;
  38.     }
  39.     {# For Stars #}
  40.     .star-block {
  41.         position: relative;
  42.         display: inline-block;
  43.     }
  44.     .star {
  45.         font-size: 20px;
  46.         color: rgba(60,64,67,.38);
  47.         cursor: pointer;
  48.         transition: color 0.3s;
  49.     }
  50.     .star:hover,
  51.     .star.active {
  52.         color: #DE5D50;
  53.     }
  54.     .star-half {
  55.         display: inline-flex;
  56.         font-size: 20px;
  57.         color: rgba(60,64,67,.38);
  58.         cursor: pointer;
  59.         transition: color 0.3s;
  60.     }
  61.     .star-half > div:first-child {
  62.         overflow: hidden;
  63.         width: 10px;
  64.         z-index: 1;
  65.         color: #DE5D50;
  66.     }
  67.     .star-half > div:last-child {
  68.         position: relative;
  69.         margin-left:-10px;
  70.     }
  71.     .customer-reviews .star{
  72.         font-size: 15px;
  73.         padding: 1px;
  74.     }
  75.     .customer-reviews span{
  76.         padding-left: 10px;
  77.     }
  78.     .customer-reviews .remarks{
  79.         font-size: 12px;
  80.     }
  81.     {# For Profile image #}
  82.     .profile-placeholder {
  83.         width: 30px; /* Adjust the size as needed */
  84.         height: 30px;
  85.         border-radius: 50%;
  86.         display: flex;
  87.         align-items: center;
  88.         justify-content: center;
  89.         font-size: 15px; /* Adjust the font size as needed */
  90.         font-weight: bold;
  91.         color: #ffffff; /* Text color, change as needed */
  92.     }
  93.     .initials {
  94.         text-align: center;
  95.         line-height: 1; /* Center the text vertically */
  96.     }
  97.     .form-error-message{
  98.         color: #c04949;
  99.     }
  100.     #product_rating_area .ec-rectHeading.is_active i {
  101.         transform: rotate(180deg);
  102.     }
  103. </style>
  104. <script>
  105.     $(function() {
  106.         // append rating area
  107.         $('#product_rating_area').appendTo($('.ec-layoutRole__main, .ec-layoutRole__mainWithColumn, .ec-layoutRole__mainBetweenColumn'));
  108.         // rating submit
  109.         $('#star_submit').on('click', function(){
  110.             var ratingStar = $('#rating_star').val();
  111.             // var sex = $('input[name="rating[Sex]"]:checked').val();
  112.             var title = $('#rating_title').val();
  113.             var formError = false;
  114.             if(!ratingStar){
  115.                 $('#star-err').show();
  116.                 formError = true;
  117.             }else{
  118.                 $('#star-err').hide();
  119.             }
  120.             if(!title){
  121.                 $('#title-err').show();
  122.                 formError = true;
  123.             }else{
  124.                 $('#title-err').hide();
  125.             }
  126.             if(formError){
  127.                 return;
  128.             }
  129.             $('#star_form').submit();
  130.         });
  131.         // show hide ratings
  132.         $('#product_rating_area .ec-rectHeading').on('click', function() {
  133.             $content = $('#ratingContent');
  134.             if ($content.css('display') == 'none') {
  135.                 $(this).addClass('is_active');
  136.                 $content.addClass('is_active');
  137.                 $content.slideDown(300);
  138.             } else {
  139.                 $(this).removeClass('is_active');
  140.                 $content.removeClass('is_active');
  141.                 $content.slideUp(300);
  142.             }
  143.             return false;
  144.         });
  145.         // show rating stars under title
  146.         var stars = "<div class='m-1'>";
  147.         var averageRating = '0.0';
  148.         var avg = Math.ceil(averageRating);
  149.         if(avg > 0){
  150.             for(var i = 1; i <= avg; i++){
  151.                 if(i>averageRating){
  152.                     stars += '<span class="star-half"><div>★</div><div>★</div></span>';
  153.                 }else{
  154.                     stars += '<span class="star active">★</span>';
  155.                 }
  156.             }
  157.         }
  158.         var leftAvg = 5 - avg;
  159.         if(leftAvg > 0){
  160.             for(var i = 1; i <= leftAvg; i++){
  161.                 stars += '<span class="star">★</span>';
  162.             }
  163.         }
  164.         stars += "<span class='average-number'> 0.0(0件)</span>";
  165.         stars += '</div>';
  166.         $('.ec-productRole__title').after(stars);
  167.     });
  168.     let selectedRating = 0;
  169.     function rateApp(rating) {
  170.         selectedRating = rating;
  171.         updateRatingDisplay(rating);
  172.         $('#rating_star').val(rating);
  173.         $('#ratingModal').modal('show');
  174.     }
  175.     function onHover(rating){
  176.         updateRatingDisplay(rating);
  177.     }
  178.     function hoverOut(){
  179.         updateRatingDisplay(selectedRating);
  180.     }
  181.     function updateRatingDisplay(rating) {
  182.         const stars = document.querySelectorAll('.rating');
  183.         stars.forEach((star, index) => {
  184.             star.classList.toggle('active', index < rating);
  185.         });
  186.         // rating for modal star
  187.         const modalStars = document.querySelectorAll('.modal-rating');
  188.         modalStars.forEach((star, index) => {
  189.             star.classList.toggle('active', index < rating);
  190.         });
  191.     }
  192.     function ratingList(productId){
  193.         $('#reviewModal').modal('show')
  194.     }
  195. </script>
  196. <div id="product_rating_area">
  197.     <div class="ec-role">
  198.         <div class="ec-rectHeading is_active">
  199.             <h4>
  200.                 レビュー
  201.                 <span style="float: right" class="chevron pull-right">
  202.                         <i class="fas fa-angle-up fa-lg"></i>
  203.                     </span>
  204.             </h4>
  205.         </div>
  206.         <div id="ratingContent" class="p-2">
  207.             <div class="row mb-2">
  208.                 <div class="col-6">
  209.                     <span class="star rating" onclick="rateApp(1)" onmouseover="onHover(1)" onmouseout="hoverOut()">★</span>
  210.                     <span class="star rating" onclick="rateApp(2)" onmouseover="onHover(2)" onmouseout="hoverOut()">★</span>
  211.                     <span class="star rating" onclick="rateApp(3)" onmouseover="onHover(3)" onmouseout="hoverOut()">★</span>
  212.                     <span class="star rating" onclick="rateApp(4)" onmouseover="onHover(4)" onmouseout="hoverOut()">★</span>
  213.                     <span class="star rating" onclick="rateApp(5)" onmouseover="onHover(5)" onmouseout="hoverOut()">★</span>
  214.                 </div>
  215.                 <div class="col-6 text-right">
  216.                     <button class="ec-inlineBtn--action" data-bs-toggle="modal" data-bs-target="#ratingModal">レビューを書く</button>
  217.                 </div>
  218.             </div>
  219.             {#{% if totalRatings > 3 %}
  220.                 <div class="mb-2">
  221.                     <h5 class="d-inline">全てのレビューを見る</h5>
  222.                         <a class="mt-1" onclick="ratingList({{Product.id}})" class="btn"><i class="fa fa-arrow-right"></i></a>
  223.                 </div>
  224.             {% endif %}
  225.             {% if totalRatings > 0 %}
  226.                 <div class="row">
  227.                     <div class="col-md-2">
  228.                         <h1 class="rating-range">{{ averageRating|number_format(1) }}</h1>
  229.                         {% set avg = averageRating|round(0, 'ceil') %}
  230.                         {% if avg > 0 %}
  231.                             {% for i in 1..avg %}
  232.                                 {% if loop.last == true and i > averageRating %}
  233.                                     <span class="star-half">
  234.                                         <div>★</div><div>★</div>
  235.                                     </span>
  236.                                 {% else %}
  237.                                     <span class="star active">★</span>
  238.                                 {% endif %}
  239.                             {% endfor %}
  240.                         {% endif %}
  241.                         {% set rAvg = 5 - avg %}
  242.                         {% if rAvg > 0 %}
  243.                             {% for j in 1..rAvg %}<span class="star">★</span>{% endfor %}
  244.                         {% endif %}
  245.                         <p>{{ totalRatings }} reviews</p>
  246.                     </div>
  247.                     <div class="col-md-10">
  248.                         <div class="progress-container" data-count="5">
  249.                             <div class="progress">
  250.                                 <div class="progress-bar" role="progressbar" style="width: {{ fiveStar }}%;">
  251.                                     <span class="sr-only"></span>
  252.                                 </div>
  253.                             </div>
  254.                         </div>
  255.                         <div class="progress-container" data-count="4">
  256.                             <div class="progress">
  257.                                 <div class="progress-bar" role="progressbar" style="width: {{ fourStar }}%;">
  258.                                     <span class="sr-only"></span>
  259.                                 </div>
  260.                             </div>
  261.                         </div>
  262.                         <div class="progress-container" data-count="3">
  263.                             <div class="progress">
  264.                                 <div class="progress-bar" role="progressbar" style="width: {{ threeStar }}%;">
  265.                                     <span class="sr-only"></span>
  266.                                 </div>
  267.                             </div>
  268.                         </div>
  269.                         <div class="progress-container" data-count="2">
  270.                             <div class="progress">
  271.                                 <div class="progress-bar" role="progressbar" style="width: {{ twoStar }}%;">
  272.                                     <span class="sr-only"></span>
  273.                                 </div>
  274.                             </div>
  275.                         </div>
  276.                         <div class="progress-container" data-count="1">
  277.                             <div class="progress">
  278.                                 <div class="progress-bar" role="progressbar" style="width: {{ oneStar }}%;">
  279.                                     <span class="sr-only"></span>
  280.                                 </div>
  281.                             </div>
  282.                         </div>
  283.                     </div>
  284.                 </div>
  285.             {% endif %}
  286.             {% for rating in ratings %}
  287.                 <div class="row mt-3 customer-reviews">
  288.                     <div class="col-md-12">
  289.                         <div class="user-review" style="display: flex;">
  290.                             {% set randomColor = rating.getRandomColor() %}
  291.                             <div class="profile-placeholder" style="background-color: {{ randomColor }}">
  292.                                 <div class="initials">{{ rating.customer_name|first|upper }}</div>
  293.                             </div>
  294.                             <span class="mt-2">{{ rating.customer_name }}</span>
  295.                         </div>
  296.                     </div>
  297.                     <div class="mt-2">
  298.                         {% for i in 1..rating.star %}<span class="star active">★</span>{% endfor %}
  299.                         {% set noStar = 5 - rating.star %}
  300.                         {% if noStar > 0 %}
  301.                             {% for j in 1..noStar %}<span class="star">★</span>{% endfor %}
  302.                         {% endif %}
  303.                         <span class='remarks'>{{ rating.create_date|date_min }}</span>
  304.                     </div>
  305.                     <h6 class="mt-1 mb-1 font-weight-bold">{{ rating.title }}</h6>
  306.                     <p class="remarks">{{ rating.remarks }}</p>
  307.                     {% if config.getCanReply() and rating.reply != "" %}
  308.                         <div class="m-2"><p class="p-2 remarks reply">{{ rating.reply }}</p></div>
  309.                     {% endif %}
  310.                 </div>
  311.             {% endfor %}
  312.             {% if totalRatings > 3 %}
  313.                 <button type="button" class="btn btn-light mt-3" onclick="ratingList({{Product.id}})">全てのレビューを見る</button>
  314.             {% endif %}#}
  315.         </div>
  316.     </div>
  317.     <div class="modal fade" id="ratingModal" tabindex="-1" role="dialog"
  318.          aria-labelledby="ratingModal" aria-hidden="true">
  319.         <div class="modal-dialog" role="document">
  320.             <div class="modal-content">
  321.                 <div class="modal-header">
  322.                     <h5 class="modal-title">{{ Product.name }}</h5>
  323.                     <button class="btn-close" type="button" data-bs-dismiss="modal" aria-label="Close">
  324.                     </button>
  325.                 </div>
  326.                 <form action="#" method="post" id="star_form" name="star_form">
  327.                     <div class="modal-body">
  328.                         <div class="row">
  329.                             <div class="col text-center">
  330.                                 <span class="star modal-rating" onclick="rateApp(1)" onmouseover="onHover(1)" onmouseout="hoverOut()">★</span>
  331.                                 <span class="star modal-rating" onclick="rateApp(2)" onmouseover="onHover(2)" onmouseout="hoverOut()">★</span>
  332.                                 <span class="star modal-rating" onclick="rateApp(3)" onmouseover="onHover(3)" onmouseout="hoverOut()">★</span>
  333.                                 <span class="star modal-rating" onclick="rateApp(4)" onmouseover="onHover(4)" onmouseout="hoverOut()">★</span>
  334.                                 <span class="star modal-rating" onclick="rateApp(5)" onmouseover="onHover(5)" onmouseout="hoverOut()">★</span>
  335.                             </div>
  336.                         </div>
  337.                         <div id='star-err' class="row" style="display: none;">
  338.                             <div class="col text-center">
  339.                                 <span class="form-error-icon badge bg-danger text-uppercase">エラー</span> <span class="form-error-message">入力されていません。</span>
  340.                             </div>
  341.                         </div>
  342.                         <div class="mb-2"></div>
  343.                         {#{% if customer is null %}
  344.                             <div class="row mb-2">
  345.                                 <div class="col-3">
  346.                                     <label class="ec-label form-label" for="rating_customer_name">投稿者名</label>
  347.                                 </div>
  348.                                 <div class="col">
  349.                                     <input type="text" id="rating_customer_name" name="rating[customer_name]" placeholder="投稿者名" required="required" class="form-control" />
  350.                                     <div id='name-err' style="display: none;">
  351.                                         <span class="form-error-icon badge bg-danger text-uppercase">エラー</span>
  352.                                         <span class="form-error-message">入力されていません。</span>
  353.                                     </div>
  354.                                 </div>
  355.                             </div>
  356.                             <div class="row mb-2">
  357.                                 <div class="col-3">
  358.                                     <label class="ec-label form-label" for="rating_email">メール</label>
  359.                                 </div>
  360.                                 <div class="col">
  361.                                     <input type="email" id="rating_email" name="rating[email]" placeholder="例:ec-cube@example.com" required="required" class="form-control" />
  362.                                     <div id='email-err' style="display: none;">
  363.                                         <span class="form-error-icon badge bg-danger text-uppercase">エラー</span>
  364.                                         <span class="form-error-message">入力されていません。</span>
  365.                                     </div>
  366.                                 </div>
  367.                             </div>
  368.                             <div class="row mb-2">
  369.                                 <div class="col-3">
  370.                                     <legend class="ec-label col-form-label">性別</legend>
  371.                                 </div>
  372.                                 <div class="col">
  373.                                     <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" />
  374.                                             <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" />
  375.                                             <label class="form-check-label" for="rating_Sex_2">女性</label></div></div>
  376.                                 </div>
  377.                             </div>
  378.                         {% endif %}#}
  379.                         <div class="row mb-2">
  380.                             <div class="col-3">
  381.                                 <label class="ec-label form-label required" for="rating_title">タイトル</label>
  382.                             </div>
  383.                             <div class="col">
  384.                                 <input type="text" id="rating_title" name="rating[title]" required="required" placeholder="タイトル" class="form-control" />
  385.                                 <div id='title-err' style="display: none;">
  386.                                     <span class="form-error-icon badge bg-danger text-uppercase">エラー</span>
  387.                                     <span class="form-error-message">入力されていません。</span>
  388.                                 </div>
  389.                             </div>
  390.                         </div>
  391.                         <div class="row">
  392.                             <div class="col-3">
  393.                                 <label class="ec-label form-label required" for="rating_remarks">本文</label>
  394.                             </div>
  395.                             <div class="col">
  396.                                 <textarea id="rating_remarks" name="rating[remarks]" required="required" placeholder="本文" class="form-control"></textarea>
  397.                             </div>
  398.                         </div>
  399.                     </div>
  400.                     <div class="modal-footer">
  401.                         <button id="star_submit" type="button" class="ec-inlineBtn--action">投稿する</button>
  402.                     </div>
  403.                 </form>
  404.             </div>
  405.         </div>
  406.     </div>
  407.     <div class="modal fade" id="reviewModal" tabindex="-1" role="dialog"
  408.          aria-labelledby="reviewModal" aria-hidden="true">
  409.         <div class="modal-dialog" role="document">
  410.             <div class="modal-content">
  411.                 <div class="modal-header">
  412.                     <h5 class="modal-title">{{ Product.name }}</h5>
  413.                     <button class="btn-close" type="button" data-bs-dismiss="modal" aria-label="Close">
  414.                     </button>
  415.                 </div>
  416.                 <div class="modal-body" id='ratingList'>
  417.                 </div>
  418.             </div>
  419.         </div>
  420.     </div>
  421. </div>