Valorar restaurantes

Se han añadido las funcionalidades y vistas para añadir, editar, listar y enseñar las valoraciones creadas por los usuarios a los clientes
This commit is contained in:
Pablo Franco Sánchez 2021-04-17 13:46:35 +02:00
parent 39b8515549
commit 0a131ae48f
13 changed files with 513 additions and 10 deletions

View file

@ -0,0 +1,67 @@
package org.springframework.cheapy.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.Range;
@Entity
@Table(name = "review_client")
public class ReviewClient extends BaseEntity{
private static final long serialVersionUID = 1L;
@NotBlank(message = "Debe rellenar la valoración sobre el bar")
@Column(length=16777215)
private String opinion;
@NotNull(message= "Por favor rellene este campo")
@Range(min = 1, max = 5,message="Las estrellas deben ir entre 1 y 5")
private Integer stars;
@ManyToOne
@JoinColumn(name = "username", referencedColumnName = "username")
private User escritor;
@ManyToOne
@JoinColumn(name = "client", referencedColumnName = "id")
private Client bar;
public User getEscritor() {
return escritor;
}
public Client getBar() {
return bar;
}
public void setBar(Client bar) {
this.bar = bar;
}
public void setEscritor(User escritor) {
this.escritor = escritor;
}
public String getOpinion() {
return opinion;
}
public void setOpinion(String opinion) {
this.opinion = opinion;
}
public Integer getStars() {
return stars;
}
public void setStars(Integer stars) {
this.stars = stars;
}
}

View file

@ -0,0 +1,19 @@
package org.springframework.cheapy.repository;
import java.util.List;
import org.springframework.cheapy.model.Client;
import org.springframework.cheapy.model.ReviewClient;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
public interface ReviewClientRepository extends PagingAndSortingRepository<ReviewClient, Integer> {
List<ReviewClient> findByBar(String bar);
List<ReviewClient> findAllReviewClientByBar(Pageable p, Client client);
List<ReviewClient> findAllReviewClientByBar(Client client);
ReviewClient findReviewClientById(int id);
}

View file

@ -7,9 +7,11 @@ import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cheapy.model.Client;
import org.springframework.cheapy.model.Code;
import org.springframework.cheapy.model.ReviewClient;
import org.springframework.cheapy.model.Usuario;
import org.springframework.cheapy.repository.ClientRepository;
import org.springframework.cheapy.repository.CodeRepository;
import org.springframework.cheapy.repository.ReviewClientRepository;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
@ -21,11 +23,13 @@ public class ClientService {
private ClientRepository clientRepository;
private CodeRepository codeRepository;
private ReviewClientRepository reviewRepositoy;
@Autowired
public ClientService(final ClientRepository clientRepository, CodeRepository codeRepository) {
public ClientService(final ClientRepository clientRepository, CodeRepository codeRepository, ReviewClientRepository reviewRepositoy) {
this.clientRepository = clientRepository;
this.codeRepository = codeRepository;
this.reviewRepositoy = reviewRepositoy;
}
@Transactional
@ -57,4 +61,13 @@ public class ClientService {
public List<Client> findAllClient() throws DataAccessException {
return this.clientRepository.findAllClient();
}
public Integer mediaValoraciones(Client client) {
List<ReviewClient> valoraciones =this.reviewRepositoy.findAllReviewClientByBar(client);
if(valoraciones.size()!=0) {
return Integer.valueOf( (int) valoraciones.stream().mapToInt(x->x.getStars()).average().getAsDouble());
}else {
return 0;
}
}
}

View file

@ -0,0 +1,41 @@
package org.springframework.cheapy.service;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cheapy.model.Client;
import org.springframework.cheapy.model.Review;
import org.springframework.cheapy.model.ReviewClient;
import org.springframework.cheapy.repository.ReviewClientRepository;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
@Service
public class ReviewClientService {
private ReviewClientRepository repo;
@Autowired
public ReviewClientService(ReviewClientRepository repo) {
super();
this.repo = repo;
}
@Transactional
public void saveReview(final ReviewClient entity) {
this.repo.save(entity);
}
@Transactional
public List<ReviewClient> findByClient(String idClient){
return this.repo.findByBar(idClient);
}
public ReviewClient findReviewById(int reviewId) {
return this.repo.findReviewClientById(reviewId);
}
public List<ReviewClient> findAllReviewsByBar(Pageable p, Client client) {
return this.repo.findAllReviewClientByBar(p, client);
}
}

View file

@ -161,9 +161,11 @@ public class ClientController {
}
@GetMapping(value = "/restaurant/{clientId}")
public String showRestaurant(final ModelMap model, @PathVariable("clientId") Integer id) {
Client client = this.clientRepo.findById(id).get();
Integer valoraciones=this.clientService.mediaValoraciones(client);
model.put("client", client);
model.put("reviews", valoraciones);
return "clients/restaurantShow";
}
}

View file

@ -0,0 +1,139 @@
package org.springframework.cheapy.web;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import org.springframework.cheapy.model.Client;
import org.springframework.cheapy.model.Review;
import org.springframework.cheapy.model.ReviewClient;
import org.springframework.cheapy.model.User;
import org.springframework.cheapy.service.ClientService;
import org.springframework.cheapy.service.ReviewClientService;
import org.springframework.cheapy.service.UserService;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import net.bytebuddy.asm.Advice.This;
@Controller
public class ReviewClientController {
private static final String VIEWS_REVIEWS_CREATE_OR_UPDATE_FORM = "reviewsClient/createOrUpdateReviewForm";
private final ReviewClientService reviewService;
private final UserService userService;
private final ClientService clientService;
public ReviewClientController(ReviewClientService reviewService, UserService userService, ClientService clientService) {
super();
this.clientService = clientService;
this.reviewService = reviewService;
this.userService = userService;
}
private boolean checkIdentity(final int reviewId) {
boolean res = false;
User user = this.userService.getCurrentUser();
ReviewClient review = this.reviewService.findReviewById(reviewId);
User reviewsAuthor = review.getEscritor();
if (user.equals(reviewsAuthor)) {
res = true;
}
return res;
}
private boolean checkClient(final String client) {
User user = this.userService.getCurrentUser();
Client bar = this.clientService.findByUsername(client);
return (bar == null||user==null)? false: true;
}
@GetMapping("/reviewsClient/new/{idClient}")
public String initCreationForm(final Map<String, Object> model, @PathVariable("idClient") final String idClient) {
if(!checkClient(idClient)) {
return "error";
}
ReviewClient review = new ReviewClient();
model.put("review", review);
return ReviewClientController.VIEWS_REVIEWS_CREATE_OR_UPDATE_FORM;
}
@PostMapping("/reviewsClient/new/{idClient}")
public String processCreationForm(@Valid final ReviewClient review, @PathVariable("idClient") final String idClient,final BindingResult result) {
if (result.hasErrors()) {
return ReviewClientController.VIEWS_REVIEWS_CREATE_OR_UPDATE_FORM;
} else {
User escritor = this.userService.getCurrentUser();
review.setEscritor(escritor);
Client bar = this.clientService.findByUsername(idClient);
review.setBar(bar);
this.reviewService.saveReview(review);
return "redirect:/reviewsClient/" + review.getId();
}
}
@GetMapping("/reviewsClient/{reviewId}")
public String processShowForm(@PathVariable("reviewId") final int reviewId, final Map<String, Object> model) {
ReviewClient review = this.reviewService.findReviewById(reviewId);
model.put("review", review);
return "reviewsClient/reviewsShow";
}
@GetMapping("/reviewsClientList/{idClient}/{page}")
public String processFindForm(@PathVariable("page") final int page, @PathVariable("idClient") final String idClient, final Map<String, Object> model) {
Pageable elements = PageRequest.of(page, 6);
Client client = this.clientService.findByUsername(idClient);
List<ReviewClient> reviewsLs = this.reviewService.findAllReviewsByBar(elements,client);
model.put("reviewsLs", reviewsLs);
model.put("client", idClient);
return "reviewsClient/reviewsList";
}
@GetMapping("/reviewsClient/{reviewId}/edit")
public String updateReviewInit(@PathVariable("reviewId") final int reviewId, final ModelMap model) {
if (!this.checkIdentity(reviewId)) {
return "error";
}
ReviewClient review = this.reviewService.findReviewById(reviewId);
model.addAttribute("review", review);
return ReviewClientController.VIEWS_REVIEWS_CREATE_OR_UPDATE_FORM;
}
@PostMapping("/reviewsClient/{reviewId}/edit")
public String updateReviewPost(@Valid final ReviewClient reviewEdit, final BindingResult result, final ModelMap model) {
if (!this.checkIdentity(reviewEdit.getId())) {
return "error";
}
if (result.hasErrors()) {
model.addAttribute("review", reviewEdit);
return ReviewClientController.VIEWS_REVIEWS_CREATE_OR_UPDATE_FORM;
} else {
Client bar = this.reviewService.findReviewById(reviewEdit.getId()).getBar();
User escritor = this.userService.getCurrentUser();
reviewEdit.setEscritor(escritor);
reviewEdit.setBar(bar);
this.reviewService.saveReview(reviewEdit);
return "redirect:/reviewsClient/" + reviewEdit.getId();
}
}
}

View file

@ -63,3 +63,14 @@ INSERT INTO nu_offers(start, end, code, status, client_id, gold, discount_gold,
INSERT INTO nu_offers(start, end, code, status, client_id, gold, discount_gold, silver, discount_silver, bronze, discount_bronze) VALUES ('2021-08-15 12:00:00', '2021-08-16 12:00:00', 'NU-6', 'active',2,20,30,15,10,10,5);
INSERT INTO nu_offers(start, end, code, status, client_id, gold, discount_gold, silver, discount_silver, bronze, discount_bronze) VALUES ('2021-08-15 12:00:00', '2021-08-16 12:00:00', 'NU-7', 'active',2,20,35,15,15,10,5);
INSERT INTO nu_offers(start, end, code, status, client_id, gold, discount_gold, silver, discount_silver, bronze, discount_bronze) VALUES ('2021-08-16 12:00:00', '2021-08-17 12:00:00', null, 'hidden',1,15,25,10,15,5,10);
INSERT INTO review_client(opinion, stars, username, client ) VALUES ('Es un bar muy bueno para ir a comer',5,'paco',1);
INSERT INTO review_client(opinion, stars, username, client ) VALUES ('Las ofertas eran buenas pero el servicio mejorable',2,'lolo',1);
INSERT INTO review_client(opinion, stars, username, client ) VALUES ('Nos trataron genial a mi y a mi amigo',4,'pepe',1);
INSERT INTO review_client(opinion, stars, username, client ) VALUES ('Abren a todas horas!!!',5,'paco',1);
INSERT INTO review_client(opinion, stars, username, client ) VALUES ('La comida de hoy estaba muy rica',4,'lolo',1);
INSERT INTO review_client(opinion, stars, username, client ) VALUES ('Recomiendo ir por la noche, tiene muy buenas vistas',4,'pepe',1);
INSERT INTO review_client(opinion, stars, username, client ) VALUES ('No retrasmiten futbol',1,'pepe',1);
INSERT INTO review_client(opinion, stars, username, client ) VALUES ('Un sitio perfecto para llevar a tu pareja',5,'paco',2);
INSERT INTO review_client(opinion, stars, username, client ) VALUES ('En hora punta nunca hay sitio',2,'lolo',2);
INSERT INTO review_client(opinion, stars, username, client ) VALUES ('Fui una vez por probar y ahora voy todas las tardes',4,'pepe',2);

View file

@ -45,15 +45,36 @@
</tr><tr>
<th><fmt:message key="foodClient"/></th>
<td><c:out value="${client.food}%"/> </td>
</tr>
</thead>
</table>
<div style="font-size: 150%" >
<fmt:message key="reviews"/>
<cheapy:showStars value="${reviews}"></cheapy:showStars>
</div>
<div class="btn-menu">
</div>
<div class="text-left">
<spring:url value="/reviewsClientList/{client}/0" var="reviewsListUrl">
<spring:param name="client" value="${client.usuar.username}"/>
</spring:url>
<button type="button" class="btn-pag" role="link" onclick="window.location='${fn:escapeXml(reviewsListUrl)}'" style="font-family: 'Lobster'; font-size: 20px;">
Valoraciones</button>
<sec:authorize access="hasAnyAuthority('usuario')">
<spring:url value="/reviewsClient/new/{client}/" var="reviewsCreateUrl">
<spring:param name="client" value="${client.usuar.username}"/>
</spring:url>
<button type="button" class="btn-pag" role="link" onclick="window.location='${fn:escapeXml(reviewsCreateUrl)}'" style="font-family: 'Lobster'; font-size: 20px;">
Valorar</button>
</sec:authorize>
</div>
</div>
</cheapy:layout>

View file

@ -10,7 +10,7 @@
<cheapy:layout pageName="reviewsN">
<h2 style="font-family: 'Lobster'; text-align:center; font-size:200%; color: rgb(0, 64, 128); padding:10px">
<c:if test="${review['new']}">Nueva </c:if> Reseña
<c:if test="${review['new']}">Nueva </c:if> Reseña
</h2>
<form:form modelAttribute="review" class="form-horizontal" id="add-review-form">
<div class="form-group has-feedback">
@ -29,7 +29,7 @@
Crear reseña</button>
</c:when>
<c:otherwise>
<button class="btn btn-default" type="submit">Modificar Reseña</button>
<button class="btn btn-default" type="submit">Modificar Reseña</button>
</c:otherwise>
</c:choose>
</div>

View file

@ -0,0 +1,42 @@
<%@ page session="false" trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="cheapy" tagdir="/WEB-INF/tags" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<link href='https://fonts.googleapis.com/css?family=Lobster' rel='stylesheet'>
<cheapy:layout pageName="reviewsN">
<h2 style="font-family: 'Lobster'; text-align:center; font-size:200%; color: rgb(0, 64, 128); padding:10px">
<c:if test="${review['new']}">Nueva </c:if> Reseña
</h2>
<form:form modelAttribute="review" class="form-horizontal" id="add-review-form">
<div class="form-group has-feedback">
<form:hidden path="id"/>
<cheapy:textAreaField label="Opinión" name="opinion"/>
<!-- <cheapy:inputField label="Estrellas" name="stars"/> -->
<cheapy:ratingStar label="Valoración" name="stars" disabled="false"></cheapy:ratingStar>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="btn-mod">
<c:choose>
<c:when test="${review['new']}">
<button class="btn btn-default" type="submit" style="font-family: 'Lobster'; font-size: 20px;">
<span class="glyphicon glyphicon-floppy-save" aria-hidden="true" style="padding: 5px"> </span>
Crear reseña</button>
</c:when>
<c:otherwise>
<button class="btn btn-default" type="submit">Modificar Reseña</button>
</c:otherwise>
</c:choose>
</div>
</div>
</div>
</form:form>
</cheapy:layout>

View file

@ -0,0 +1,93 @@
<%@ page session="false" trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="cheapy" tagdir="/WEB-INF/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<link href='https://fonts.googleapis.com/css?family=Lobster' rel='stylesheet'>
<cheapy:layout pageName="reviews">
<h2 style="font-family: 'Lobster'; text-align:center; font-size:200%; color: rgb(0, 64, 128); padding:10px"><fmt:message key="reviews"/></h2>
<table id="reviewTable" class="table table-striped">
<thead>
<tr>
<!-- <th style="width: 150px;">Restaurante</th> -->
<th><fmt:message key="user"/></th>
<th><fmt:message key="stars"/></th>
<th><fmt:message key="opinion"/></th>
<th> </th>
</tr>
</thead>
<tbody>
<c:choose>
<c:when test="${empty reviewsLs}">
<tr><td colspan="4"><em><c:out value="No se ha realizado ninguna valoración por el momento."/></em></td></tr>
</c:when>
<c:otherwise>
<c:forEach items="${reviewsLs}" var="review">
<tr>
<!-- <td> -->
<%-- <c:out value="nombre por definir"/> <!-- ${review.usuario.nombre},${review.usuario.apellidos} --> --%>
<!-- </td> -->
<td>
<c:out value="${review.escritor.username}"/>
</td>
<td>
<!--<c:out value="${review.stars}"/> -->
<cheapy:showStars value='${review.stars}'></cheapy:showStars>
</td>
<td>
<c:out value="${review.opinion}"/>
</td>
<td>
<spring:url value="/reviewsClient/{reviewId}" var="reviewUrl">
<spring:param name="reviewId" value="${review.id}"/>
</spring:url>
<div class="btn-detalles">
<button type="button" role="link" onclick="window.location='${fn:escapeXml(reviewUrl)}'" style="font-family: 'Lobster'; font-size: 20px;">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true" style="padding: 5px"> </span>
<fmt:message key="details"/></button>
</div>
</td>
</tr>
</c:forEach>
</c:otherwise>
</c:choose>
</tbody>
</table>
<div class="text-center">
<c:out value='Página ${page}'></c:out>
</div>
<c:if test='${page!=0}'>
<div class="text-left">
<spring:url value="/reviewsClientList/{client}/{page}" var="reviewsListUrl">
<spring:param name="page" value="${page-1}"/>
<spring:param name="client" value="${client}"/>
</spring:url>
<button type="button" class="btn-pag" role="link" onclick="window.location='${fn:escapeXml(reviewsListUrl)}'" style="font-family: 'Lobster'; font-size: 20px;">
<span class="glyphicon glyphicon glyphicon-arrow-left" aria-hidden="true" style="padding: 5px"> </span>
Pág. anterior</button>
</div>
</c:if>
<c:if test="${fn:length(reviewsLs) == 6}">
<div class="text-right">
<spring:url value="/reviewsClientList/{client}/{page}" var="reviewsListUrl">
<spring:param name="page" value="${page+1}"/>
<spring:param name="client" value="${client}"/>
</spring:url>
<button type="button" class="btn-pag" role="link" onclick="window.location='${fn:escapeXml(reviewsListUrl)}'" style="font-family: 'Lobster'; font-size: 20px;">
<span class="glyphicon glyphicon glyphicon-arrow-right" aria-hidden="true" style="padding: 5px"> </span>
Pág. siguiente</button>
</div>
</c:if>
</cheapy:layout>

View file

@ -0,0 +1,52 @@
<%@ page session="false" trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="cheapy" tagdir="/WEB-INF/tags" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<link href='https://fonts.googleapis.com/css?family=Lobster' rel='stylesheet'>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<cheapy:layout pageName="review">
<h2 style="font-family: 'Lobster'; text-align:center; font-size:200%; color: rgb(0, 64, 128); padding:10px"><fmt:message key="review"/></h2>
<form:form modelAttribute="review" class="form-horizontal" id="add-review-form">
<table class="table table-striped" id="review-table">
<tr>
<th><fmt:message key="stars"/></th>
<!-- <td><c:out value="${review.stars}"/></td>-->
<td><cheapy:ratingStar label="" name="stars" disabled="true"></cheapy:ratingStar></td>
</tr>
<tr>
<th><fmt:message key="opinion"/></th>
<td><c:out value="${review.opinion}"/></td>
</tr>
</table>
</form:form>
<sec:authorize access="isAuthenticated()">
<sec:authentication var="principal" property="principal" />
<div class="btns-edit">
<c:if test="${principal.username eq review.escritor.username}">
<spring:url value="{reviewId}/edit" var="editUrl">
<spring:param name="reviewId" value="${review.id}"/>
</spring:url>
<button type="button" role="link" onclick="window.location='${fn:escapeXml(editUrl)}'" style="font-family: 'Lobster'; font-size: 20px;">
<span class="glyphicon glyphicon glyphicon-edit" aria-hidden="true" style="padding: 5px"> </span>
Editar opinión</button>
</c:if>
</div>
</sec:authorize>
</cheapy:layout>

View file

@ -2,11 +2,14 @@
<%@ tag language="java" pageEncoding="ISO-8859-1"%>
<%@ attribute name="value" required="true" rtexprvalue="true" type="Integer"
description="Number of starts" %>
<%@ attribute name="label" required="false" rtexprvalue="true"
description="Label appears in red color if input is considered as invalid after submission" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<form>
<c:if test="${label}">
<label class="col-sm-2 control-label">${label}</label>
</c:if>
<div class="rating">
<input type="radio" class="form-control" disabled name="rating" value="5" id="5" <%= value.equals(5) ?"checked='checked'" : ""%> /><label for="5"><span style="font-size: 100%" class="estrella_vacia">&#9734;</span></label>
<input type="radio" class="form-control" disabled name="rating" value="4" id="4" <%= value.equals(4) ? "checked='checked'" : "" %> /><label for="4"><span style="font-size: 100%" class="estrella_vacia">&#9734;</span></label>