Hi Andrei,
I suggest to add "product like/dislike by customer" feature in nop 3.80. I have done it with for several clients. source code=======>.
1.=====>modify Product.cs
#region liker_customer added by sohel
private ICollection<Customer> _likerCustomers;
/// <summary>
/// Gets or sets the product tags
/// </summary>
public virtual ICollection<Customer> LikerCustomers
{
get { return _likerCustomers ?? (_likerCustomers = new List<Customer>()); }
protected set { _likerCustomers = value; }
}
#endregion
2.=====>modify Customer.cs
#region liked_products added by sohel
private ICollection<Product> _likedProducts;
/// <summary>
/// Gets or sets the product tags
/// </summary>
public virtual ICollection<Product> LikedProducts
{
get { return _likedProducts ?? (_likedProducts = new List<Product>()); }
protected set { _likedProducts = value; }
}
#endregion
3.=====>modify ProductMap.cs
//added by sohel
this.HasMany(p => p.LikerCustomers)
.WithMany(c => c.LikedProducts)
.Map(m => m.ToTable("Bs_Product_Customer_Like_Mapping"));
4.=====>Modify Nop.Web ====> ProductController.cs
#region product like/unlike added by sohel
[HttpPost]
[ActionName("ProductLike")]
//[ValidateAntiForgeryToken]
public ActionResult ProductLike(int productId)
{
var product = _productService.GetProductById(productId);
if(product==null)
throw new Exception("No product found with this id."); ;
if (!_workContext.CurrentCustomer.IsRegistered())
throw new Exception("Anonymous like is not allowed! Please Login and then try again.");
var customer = _workContext.CurrentCustomer;
string responseError = string.Empty;
if(product.LikerCustomers.Contains(customer))
throw new Exception("You are already liked the product. Please the refresh page.");
try
{
product.LikerCustomers.Add(customer);
_productService.UpdateProduct(product);
int productLikeCount = product.LikerCustomers.Count;
return Json(new { success = true, liked_unliked = 1, productlikecounthtml = productLikeCount.ToString(), message = "Your like request Success! " });
}
catch (Exception exc)
{
ModelState.AddModelError("", exc.Message);
responseError += exc.Message;
}
return Json(new { success = false, message = responseError });
}
[HttpPost]
[ActionName("ProductUnLike")]
//[ValidateAntiForgeryToken]
public ActionResult ProductUnLike(int productId)
{
if (!_workContext.CurrentCustomer.IsRegistered())
throw new Exception("Anonymous like is not allowed! Please Login and then try again.");
var product = _productService.GetProductById(productId);
if (product == null)
throw new Exception("No product found with this id.");
var customer = _workContext.CurrentCustomer;
if (!product.LikerCustomers.Contains(customer))
throw new Exception("You are already unliked the product. Please refresh the page.");
string responseError = string.Empty;
try
{
product.LikerCustomers.Remove(customer);
_productService.UpdateProduct(product);
int productLikeCount = product.LikerCustomers.Count;
return Json(new { success = true, liked_unliked = 1, productlikecounthtml = productLikeCount.ToString(), message = "Your unlike request Success! " });
}
catch (Exception exc)
{
ModelState.AddModelError("", exc.Message);
responseError += exc.Message;
}
return Json(new { success = false, message = responseError });
}
#endregion
5. Java Script=====>
/*
** //product like counter update added by Md. Minul Islam sohel Bs-23
*/
var ProductLike = {
loadWaiting: false,
usepopupnotifications: false,
like_unlike_selector: '',
init: function (usepopupnotifications, like_unlike_selector) {
this.loadWaiting = false;
this.usepopupnotifications = usepopupnotifications;
this.like_unlike_selector = like_unlike_selector;
},
setLoadWaiting: function (display) {
displayAjaxLoading(display);
this.loadWaiting = display;
},
like: function (urllike, like_unlike_selector) {
if (this.loadWaiting != false) {
return;
}
this.setLoadWaiting(true);
this.init(false, like_unlike_selector);
$.ajax({
cache: false,
url: urllike,
type: 'post',
success: this.success_process,
complete: this.resetLoadWaiting,
error: this.ajaxFailure
});
},
unlike: function (urlunlike, like_unlike_selector) {
if (this.loadWaiting != false) {
return;
}
this.setLoadWaiting(true);
this.init(false,like_unlike_selector);
$.ajax({
cache: false,
url: urlunlike,
type: 'post',
success: this.success_process,
complete: this.resetLoadWaiting,
error: this.ajaxFailure
});
},
guestlike: function () {
displayPopupNotification("Please <a href=\"/login\" class=\"ico-login\" style=\"color:red;text-decoration: underline;\"> Log in</a> to like the products", 'error', true);
},
success_process: function (response) {
if (response.message) {
//display notification
if (response.success == true) {
//success
if (response.productlikecounthtml) {
$(ProductLike.like_unlike_selector).html(response.productlikecounthtml);
$(ProductLike.like_unlike_selector).toggle();
}
if (ProductLike.usepopupnotifications == true) {
displayPopupNotification(response.message, 'success', true);
}
else {
//specify timeout for success messages
displayBarNotification(response.message, 'success', 3500);
}
}
else {
//error
if (ProductLike.usepopupnotifications == true) {
displayPopupNotification(response.message, 'error', true);
}
else {
//no timeout for errors
displayBarNotification(response.message, 'error', 0);
}
}
return false;
}
if (response.redirect) {
location.href = response.redirect;
return true;
}
return false;
},
resetLoadWaiting: function () {
ProductLike.setLoadWaiting(false);
},
ajaxFailure: function () {
alert('Failed to like or unlike the product. Please refresh the page and try one more time.');
}
};
6. ====> Modify _ProductBox.cshtml
@{
// product like unlike url added by sohel
var urlLike = Url.RouteUrl("CustomerProductLike", new { productId = Model.Id });
var urlUnLike = Url.RouteUrl("CustomerProductUnLike", new { productId = Model.Id });
var isGuestCustomer = EngineContext.Current.Resolve<IWorkContext>().CurrentCustomer.IsGuest();
}
@if (@isGuestCustomer)
{
<a style="@(!(Model.IsLikedByCurrentCustomer) ? "display:block" : "display:none")" class="item-like-counter_@(Model.Id) like-btn item-like-counter disabled" onclick="ProductLike.guestlike()">@Model.ProductLikeCount</a>
<a style="@(!(Model.IsLikedByCurrentCustomer) ? "display:none" : "display:block")" class="item-like-counter_@(Model.Id) unlike-btn item-like-counter disabled">@Model.ProductLikeCount</a>
}
else
{
<a style="@(!(Model.IsLikedByCurrentCustomer) ? "display:block" : "display:none")" class="item-like-counter_@(Model.Id) like-btn item-like-counter" onclick="ProductLike.like('@urlLike','.item-like-counter_@(Model.Id)');return false; ">@Model.ProductLikeCount</a>
<a style="@(!(Model.IsLikedByCurrentCustomer) ? "display:none" : "display:block")" class="item-like-counter_@(Model.Id) unlike-btn item-like-counter" onclick="ProductLike.unlike('@urlUnLike','.item-like-counter_@(Model.Id)');return false; ">@Model.ProductLikeCount</a>
}