Skip to content
Open
2 changes: 1 addition & 1 deletion app/controllers/spree/reviews_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def load_product
end

def permitted_review_attributes
[:rating, :title, :review, :name, :show_identifier]
[:rating, :title, :review, :name, :show_identifier, :product_worth, :product_recommend, :vendor_recommend]
end

def review_params
Expand Down
6 changes: 4 additions & 2 deletions app/models/spree/product_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ def stars
avg_rating.try(:round) || 0
end



def recalculate_rating
self[:reviews_count] = reviews.reload.approved.count
self[:reviews_count] = reviews.count
self[:avg_rating] = if reviews_count > 0
reviews.approved.sum(:rating).to_f / reviews_count
reviews.sum(:rating).to_f / reviews.count

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert to reviews_count

else
0
end
Expand Down
12 changes: 10 additions & 2 deletions app/models/spree/review.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ class Spree::Review < ActiveRecord::Base
belongs_to :user, class_name: Spree.user_class.to_s
has_many :feedback_reviews

after_save :recalculate_product_rating, if: :approved?
after_save :recalculate_product_rating
after_destroy :recalculate_product_rating

validates :name, :review, presence: true
Expand All @@ -13,7 +13,6 @@ class Spree::Review < ActiveRecord::Base
less_than_or_equal_to: 5,
message: Spree.t(:you_must_enter_value_for_rating)
}

default_scope { order('spree_reviews.created_at DESC') }

scope :localized, ->(lc) { where('spree_reviews.locale = ?', lc) }
Expand All @@ -23,6 +22,15 @@ class Spree::Review < ActiveRecord::Base
scope :approved, -> { where(approved: true) }
scope :not_approved, -> { where(approved: false) }
scope :default_approval_filter, -> { Spree::Reviews::Config[:include_unapproved_reviews] ? all : approved }
scope :raiting_five, -> { where(rating: '5').count }

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change raiting_five to rating__with_five

scope :raiting_four, -> { where(rating: '4').count }
scope :raiting_three, -> { where(rating: '3').count }
scope :raiting_two, -> { where(rating: '2').count }
scope :raiting_one, -> { where(rating: '1').count }

enum product_worth: %i[yes no dont_know], _prefix: :product_worth
enum product_recommend: %i[yes no dont_know], _prefix: :product_recommend
enum vendor_recommend: %i[yes no dont_know], _prefix: :vendor_recommend

def feedback_stars
return 0 if feedback_reviews.size <= 0
Expand Down
77 changes: 49 additions & 28 deletions app/views/spree/reviews/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,38 +1,59 @@
<%= form_for review, url: product_reviews_path(product), html: { method: :post } do |f| %>
<%= render 'spree/shared/error_messages', target: review %>
<%= render 'spree/shared/error_messages', target: review %>

<div class="form-group">
<%= f.label :rating %>
<%= render 'spree/reviews/stars', stars: review.rating, edit_enabled: true %>
</div>
<div class="form-group">
<%= f.label :rating %>
<%= render 'spree/reviews/stars', stars: review.rating, edit_enabled: true %>
</div>

<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, maxlength: 255, size: 50, class: 'form-control', required: true %>
</div>

<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, maxlength: 255, size: 50, class: 'form-control' %>
</div>

<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, maxlength: 255, size: 50, class: 'form-control', required: true %>
<div class="form-group">
<%= f.label :review %>
<%= f.text_area :review, wrap: 'virtual', rows: 4, cols: 50, class: 'form-control', required: true %>
</div>

<div class="radio mt-2">
<p class="mb-1"><b>Is this product worth?</b></p>
<%= f.radio_button :product_worth, "yes", style: "display:none" %> <span class="m-1 select-label product_worth_select_value" data-product_worth-value = "yes"> YES </span>
<%= f.radio_button :product_worth, "no", style: "display:none" %> <span class="m-1 select-label product_worth_select_value" data-product_worth-value = "no" > NO </span>
<%= f.radio_button :product_worth, "dont_know", style: "display:none" %> <span class="m-1 select-label product_worth_select_value" data-product_worth-value = "dont_know" > Don't know </span>
</div>

<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, maxlength: 255, size: 50, class: 'form-control' %>
<div class="radio mt-2">
<p class="mb-1"><b>Do you recommend this product?</b></p>
<%= f.radio_button :product_recommend, "yes", style: "display:none" %> <span class="m-1 select-label product_recommend_select_value" data-product_recommend-value = "yes"> YES </span>
<%= f.radio_button :product_recommend, "no", style: "display:none" %> <span class="m-1 select-label product_recommend_select_value" data-product_recommend-value = "no"> NO </span>
<%= f.radio_button :product_recommend, "dont_know", style: "display:none" %> <span class="m-1 select-label product_recommend_select_value" data-product_recommend-value = "dont_know"> Don't know </span>
</div>

<div class="form-group">
<%= f.label :review %>
<%= f.text_area :review, wrap: 'virtual', rows: 10, cols: 50, class: 'form-control', required: true %>
<div class="radio mt-2 mb-5">
<p class="mb-1"><b>Was the experience with the vendor good?</b></p>
<%= f.radio_button :vendor_recommend, "yes", style: "display:none" %> <span class="m-1 select-label vendor_recommend_select_value" data-vendor_recommend-value = "yes"> YES </span>
<%= f.radio_button :vendor_recommend, "no", style: "display:none" %> <span class="m-1 select-label vendor_recommend_select_value" data-vendor_recommend-value = "no"> NO </span>
<%= f.radio_button :vendor_recommend, "dont_know", style: "display:none" %> <span class="m-1 select-label vendor_recommend_select_value" data-vendor_recommend-value = "dont_know"> Don't know </span>
</div>

<% if Spree::Reviews::Config[:show_identifier] %>
<div class="checkbox">
<%= f.label :show_identifier do %>
<%= f.check_box :show_identifier, checked: true %>
<%= Spree::Review.human_attribute_name(:show_identifier) %>
<% end %>
</div>
<% end %>
<% if Spree::Reviews::Config[:show_identifier] %>
<div class="checkbox">
<%= f.label :show_identifier do %>
<%= f.check_box :show_identifier, checked: true %>
<%= Spree::Review.human_attribute_name(:show_identifier) %>
<% end %>
</div>
<% end %>

<div class="form-actions">
<%= f.submit Spree.t(:submit_your_review), class: 'btn btn-primary' %>
<%= Spree.t(:or) %>
<%= link_to Spree.t(:cancel), product_path(@product), class: 'btn btn-outline-primary', rel: 'nofollow' %>
</div>
<% end %>
<div class="form-actions">
<%= f.submit Spree.t(:submit_your_review), class: 'btn btn-primary' %>
<%= Spree.t(:or) %>
<%= link_to Spree.t(:cancel), product_path(@product), class: 'btn btn-outline-primary', rel: 'nofollow' %>
</div>
<% end %>
6 changes: 2 additions & 4 deletions app/views/spree/reviews/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="container">
<div class="row my-4">
<div class="col-12">
<h3 class="product-section-title"><%= Spree.t(:reviews) %></h3>
<h3 class="product-section-title mt-3"><%= Spree.t(:reviews) %></h3>
<% if Spree::Reviews::Config[:include_unapproved_reviews] == false and @product.reviews.approved.count == 0 %>
<p class="reviews-none"><%= Spree.t(:no_reviews_available) %></p>
<% else %>
Expand All @@ -15,11 +15,9 @@
<%= render 'spree/shared/review', review: review %>
<% end %>
<% end %>

<%= link_to Spree.t(:write_your_own_review), new_product_review_path(@product), class: 'btn btn-primary', rel: 'nofollow' %>
<%= Spree.t(:or) %>
<%= link_to Spree.t(:back_to) + " " +@product.name, product_path(@product), class: 'btn btn-outline-primary', rel: 'nofollow' %>

<% if Spree.version.to_f < 4.0 %>
<% if @approved_reviews.respond_to?(:total_pages) %>
<div class="mt-4">
Expand All @@ -40,4 +38,4 @@
<% end %>
</div>
</div>
</div>
</div>
25 changes: 25 additions & 0 deletions app/views/spree/shared/_product_added_modal.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<% @review = Spree::Review.new(product: @product) %>
<div class="modal product-added-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-md" role="document">
<div class="modal-content">
<div class="modal-header align-items-center pb-2 pt-2 border-0">
<h1 class="mb-0">Post a review</h1>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">
<%= icon(name: 'close',
classes: 'd-block d-lg-none',
width: 16,
height: 16) %>
<%= icon(name: 'close',
classes: 'd-none d-lg-block',
width: 30,
height: 30) %>
</span>
</button>
</div>
<div class="modal-body p-4">
<%= render 'spree/reviews/form', review: @review, product: @product %>
</div>
</div>
</div>
</div>
77 changes: 67 additions & 10 deletions app/views/spree/shared/_rating.html.erb
Original file line number Diff line number Diff line change
@@ -1,15 +1,72 @@
<% stars = product.stars %>
<% reviews_count = product.reviews_count %>
<% @average_rating = product.reviews.count > 0 ? product.reviews.sum(:rating).to_f / product.reviews.count : 0 %>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this line and use stars


<% reviews_count = product.reviews.count %>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to reviews_count

<% raiting_five = reviews_count != 0 ? product.reviews.raiting_five * 100 / reviews_count : 0 %>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make a helper for this

raiting_four = reviews_count != 0 ? product.reviews.raiting_four * 100 / reviews_count

<% raiting_four = reviews_count != 0 ? product.reviews.raiting_four * 100 / reviews_count : 0 %>
<% raiting_three = reviews_count != 0 ? product.reviews.raiting_three * 100 / reviews_count : 0 %>
<% raiting_two = reviews_count != 0 ? product.reviews.raiting_two * 100 / reviews_count : 0%>
<% raiting_one = reviews_count != 0 ? product.reviews.raiting_one * 100 / reviews_count : 0 %>

<div class="ratings">
<p><%= Spree.t(:average_customer_rating) %>:</p>
<p class="ratings-stars">
<span title="<%= txt_stars(stars) %>">
<%= render 'spree/reviews/stars', stars: stars %>
</span>
<p class="product-review-description">
Let us know your thoughts on a product or view reviews from our members,
independent experts and other websites.
</p>
<p class="ratings-basedupon">(<%= Spree.t(:based_upon_review_count, count: reviews_count) %>)</p>
<div class="d-flex">
<p class="ratings-stars product-review-rating-stars">
<% if product.reviews.count > 0 %>
<%= @average_rating.try(:round) %>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use stars

<% else %>
0
<% end %>
<span title="<%= txt_stars(@average_rating) %>">

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use stars

<%= render 'spree/reviews/stars', stars: @average_rating.try(:round) %>
</span>
</p>
</div>
<p class="ratings-basedupon product-review-basedupon"><%= Spree.t(:based_upon_review_count, count: reviews_count) %></p>

<div class="product-review-bars">
<div class="product-review-bar">
<p class="mb-0 mr-3">5</p>
<div class="progress product-review-progress-bar">
<div class="progress-bar bg-warning" role="progressbar" style="width: <%= raiting_five %>%" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mb-0"><%= raiting_five %>%</p>
</div>
<div class="product-review-bar">
<p class="mb-0 mr-3">4</p>
<div class="progress product-review-progress-bar">
<div class="progress-bar bg-warning" role="progressbar" style="width: <%= raiting_four %>%" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mb-0"><%= raiting_four %>%</p>
</div>
<div class="product-review-bar">
<p class="mb-0 mr-3">3</p>
<div class="progress product-review-progress-bar">
<div class="progress-bar bg-warning" role="progressbar" style="width: <%= raiting_three %>%" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mb-0"><%= raiting_three %>%</p>
</div>
<div class="product-review-bar">
<p class="mb-0 mr-3">2</p>
<div class="progress product-review-progress-bar">
<div class="progress-bar bg-warning" role="progressbar" style="width: <%= raiting_two %>%" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mb-0"><%= raiting_two %>%</p>
</div>
<div class="product-review-bar">
<p class="mb-0 mr-3">1</p>
<div class="progress product-review-progress-bar">
<div class="progress-bar bg-warning" role="progressbar" style="width: <%= raiting_one %>%" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mb-0"><%= raiting_one %>%</p>
</div>
</div>


<div itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
<span itemprop="ratingValue" content="<%= stars %>"></span>
<span itemprop="ratingValue" content="<%= @average_rating %>"></span>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert

<span itemprop="reviewCount" content="<%= reviews_count %>"></span>
</div>
</div>
</div>
28 changes: 15 additions & 13 deletions app/views/spree/shared/_review.html.erb
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
<div class="review" itemprop="reviews" itemscope itemtype="http://schema.org/Review">
<div class="review mt-4" itemprop="reviews" itemscope itemtype="http://schema.org/Review">
<span class="reviews-rating" title="<%= txt_stars(review.rating) %>">
<%= render 'spree/reviews/stars', stars: review.rating %>
</span>
<span itemprop="name"><%= review.title %></span>
<br>
<span class="attribution"><%= Spree.t(:submitted_on) %>
<strong><%= l review.created_at.to_date %></strong>
<span itemprop="name"><strong><%= review.title %></strong></span>
<br>
<div itemprop="reviewBody">
<p class="mb-1 product-review-description"><%= review.review %></p>
</div>
<% if Spree::Reviews::Config[:feedback_rating] && (!Spree::Reviews::Config[:require_login] || spree_current_user) %>
<div class="feedback_review my-3" id="feedback_review_<%= review.id %>">
<%= render 'spree/feedback_reviews/form', review: review %>
</div>
<% end %>
<span class="attribution product-review-attribution">
<%#= Spree.t(:submitted_on) %>
<%= l review.created_at.to_date %>
</span>
<span itemprop="datePublished" content="<%= review.created_at.to_date.to_s %>"></span>
<span itemprop="reviewRating" content="<%= review.rating %>"></span>
<% if review.show_identifier %>
<% if Spree::Reviews::Config[:show_email] && review.user %>
<span itemprop="author"><%= review.user.email %></span>
<% else %>
<span itemprop="author"><%= review.name %></span>
<span itemprop="author" class="product-review-author">- <%= review.name %></span>
<% end %>
<% else %>
<span itemprop="author"><%= Spree.t(:anonymous) %></span>
<% end %>
<div itemprop="reviewBody">
<%= simple_format(review.review) %>
</div>
<% if Spree::Reviews::Config[:feedback_rating] && (!Spree::Reviews::Config[:require_login] || spree_current_user) %>
<div class="feedback_review my-3" id="feedback_review_<%= review.id %>">
<%= render 'spree/feedback_reviews/form', review: review %>
</div>
<% end %>
</div>
17 changes: 7 additions & 10 deletions app/views/spree/shared/_reviews.html.erb
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
<div id="reviews">
<h3 class="product-section-title"><%= Spree.t(:reviews) %></h3>
<% if Spree::Reviews::Config[:include_unapproved_reviews] == false and @product.reviews.approved.count == 0 %>
<p class="reviews-none"><%= Spree.t(:no_reviews_available) %></p>
<h3 class="product-section-title mt-3"><%= Spree.t(:reviews) %></h3>
<% if Spree::Reviews::Config[:include_unapproved_reviews] == false and @product.reviews.count == 0 %>
<p class="reviews-none product-review-description"><%= Spree.t(:no_reviews_available) %></p>
<% else %>
<%= render 'spree/shared/rating', product: @product, review: 0 %>
<% for review in (Spree::Reviews::Config[:track_locale] ? @product.reviews.localized(I18n.locale) : @product.reviews).default_approval_filter.preview %>
<%= render 'spree/shared/review', review: review %>
<% end %>
<% end %>
<%= link_to Spree.t(:write_your_own_review), new_product_review_path(@product), class: 'btn btn-primary', rel: 'nofollow' %>

<% unless Spree::Reviews::Config[:include_unapproved_reviews] == false and @product.reviews.approved.count == 0 %>
<%= Spree.t(:or) %>
<%= link_to Spree.t(:read_all_reviews), product_reviews_path(@product), class: 'btn btn-primary', rel: 'nofollow' %>
<% end %>
</div>
<div class="d-flex align-items-center mt-4">
<p class = 'review_new_button btn btn-primary mb-0'> <%= Spree.t(:write_your_own_review) %></p>
</div>
</div>
6 changes: 3 additions & 3 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ en:
average_customer_rating: Average rating
back_reviews: Back to the reviews
based_upon_review_count:
one: based upon one review
one: based upon 1 review
other: "based upon %{count} reviews"
by: by
editing_review_for_html: 'Editing review for %{link}'
Expand All @@ -34,7 +34,7 @@ en:
from: from
info_approve_review: Review approved
leave_us_a_review_for: "Please leave us a review and a rating for our '%{name}'"
no_reviews_available: "No reviews have been written for this product."
no_reviews_available: "Be the first to review this product"
out_of_5: "out of 5"
rating: rating
reviews: Reviews
Expand Down Expand Up @@ -64,6 +64,6 @@ en:
one: "1 voice"
other: "%{count} voices"
was_this_review_helpful: "Was this review helpful to you?"
write_your_own_review: Write your own review
write_your_own_review: Post a review
you_must_enter_value_for_rating: "You must enter a value for rating."
anonymous: Anonymous