diff --git a/assets/styles/app.css b/assets/styles/app.css index 7f06974fa912757577ec7ced42b0c9727f629612..6d727b5b5cffb63d91195791bfb8e14ab9cbce3b 100644 --- a/assets/styles/app.css +++ b/assets/styles/app.css @@ -313,4 +313,20 @@ button { .type-abonnement.selected { background-color: green; color: white; +} + +.btn-like { + background-color: #ffffff; + border: 0px #ccc; + padding: 5px 10px; + cursor: pointer; + font-size: 30px; +} + +.aime { + color: red; +} + +.non_aime { + color: lightgray; } \ No newline at end of file diff --git a/src/Controller/AnnonceDetailController.php b/src/Controller/AnnonceDetailController.php index 27a62fa414002ac0bd21172716c64882aa23f96a..823a01038c275c20804e69f3f2248c8c2f981b03 100644 --- a/src/Controller/AnnonceDetailController.php +++ b/src/Controller/AnnonceDetailController.php @@ -18,8 +18,7 @@ class AnnonceDetailController extends AbstractController { private $doctrine; - public function __construct(ManagerRegistry $doctrine) - { + public function __construct(ManagerRegistry $doctrine) { $this->doctrine = $doctrine; } @@ -27,17 +26,15 @@ class AnnonceDetailController extends AbstractController { $entityManager = $this->doctrine->getManager(); $annonce = $entityManager->getRepository(Prestations::class)->find($id); + $nbAimees = $annonce->getUtilisateursAimant()->count(); $prets = $entityManager->getRepository(Pret::class)->findAll(); $services = $entityManager->getRepository(Services::class)->findAll(); $user = $this->getUser(); - if (!$annonce) { - throw $this->createNotFoundException('Annonce non trouvée'); - } - return [ 'entityManager' => $entityManager, 'annonce' => $annonce, + 'nbAimees' => $nbAimees, 'prets' => $prets, 'services' => $services, 'user' => $user, @@ -50,17 +47,14 @@ class AnnonceDetailController extends AbstractController public function detail($id) { $data = $this->getCommonData($id); + $prest = $data['annonce']; + if ($prest) { + $prest->setNbVues($prest->getNbVues() + 1); + $data['entityManager']->flush(); + } return $this->render('annonce_detail/annonce.html.twig', $data); } - #[Route('/annonce/detail', name: 'app_annonce_detail')] - public function index(): Response - { - return $this->render('annonce_detail/annonce.html.twig', [ - 'controller_name' => 'AnnonceDetailController', - ]); - } - #[Route('/deleteTransaction/{prestationId}', name: 'app_delete_transaction')] public function deleteTransaction($prestationId): Response { @@ -100,6 +94,12 @@ class AnnonceDetailController extends AbstractController $entityManager = $this->doctrine->getManager(); $prestation = $data['annonce']; + $notification = new Notification(); + $notification->setDescription("Annulation de la réservation de l'annonce " . $prestation->getTitre() . " par " . $this->getUser()->getLogin()); + $notification->setType("Annulation réservation annonce"); + $notification->setDate(new DateTime()); + $notification->setUserId($prestation->getProprietaire()); + $this->doctrine->getManager()->persist($notification); $prestation->setIdClient(null); $litiges = $prestation->getLitiges(); @@ -123,4 +123,32 @@ class AnnonceDetailController extends AbstractController $data['entityManager']->flush(); return $this->redirectToRoute('annonce_detail', ['id' => $id]); } + + #[Route('/aimerPrestation/{id}', name: 'app_aimer_prestation')] + public function aimerPrestation($id): Response + { + $data = $this->getCommonData($id); + $user = $data['user']; + $prestation = $data['annonce']; + + if ($user != null) { + $notification = new Notification(); + $notification->setDescription($user->getLogin(). " a aimé votre annonce " . $prestation->getTitre()); + $notification->setType("Annonce aimée"); + $notification->setDate(new DateTime()); + $notification->setUserId($prestation->getProprietaire()); + $this->doctrine->getManager()->persist($notification); + $prestation->setIdClient(null); + } else return $this->redirectToRoute('app_login'); + + if ($user->getPrestationsAimees()->contains($prestation)) { + $user->removePrestationsAimee($prestation); + $prestation->removeUtilisateursAimant($user); + } else { + $user->addPrestationsAimee($prestation); + $prestation->addUtilisateursAimant($user); + } + $data['entityManager']->flush(); + return $this->redirectToRoute('annonce_detail', ['id' => $id]); + } } diff --git a/src/Entity/Prestations.php b/src/Entity/Prestations.php index e2e3ba9fb214ce22378ea802fade09fe540cd74f..5fa55c5d95055ed7c609d06ee89ebbaa13194ea7 100644 --- a/src/Entity/Prestations.php +++ b/src/Entity/Prestations.php @@ -50,9 +50,16 @@ class Prestations #[ORM\OneToMany(mappedBy: 'id_prestation', targetEntity: Litige::class, orphanRemoval: true)] private Collection $litiges; + #[ORM\Column] + private ?int $nbVues = null; + + #[ORM\ManyToMany(targetEntity: Utilisateur::class, mappedBy: 'prestations_aimees')] + private Collection $utilisateurs_aimant; + public function __construct() { $this->litiges = new ArrayCollection(); + $this->utilisateurs_aimant = new ArrayCollection(); } public function getId(): ?int @@ -207,5 +214,40 @@ class Prestations } return $this; - } + } + + public function getNbVues(): ?int + { + return $this->nbVues; + } + + public function setNbVues(int $nbVues): static + { + $this->nbVues = $nbVues; + + return $this; + } + + /** + * @return Collection<int, Utilisateur> + */ + public function getUtilisateursAimant(): Collection + { + return $this->utilisateurs_aimant; + } + + public function addUtilisateursAimant(Utilisateur $utilisateursAimant): static + { + if (!$this->utilisateurs_aimant->contains($utilisateursAimant)) + $this->utilisateurs_aimant->add($utilisateursAimant); + + return $this; + } + + public function removeUtilisateursAimant(Utilisateur $utilisateursAimant): static + { + $this->utilisateurs_aimant->removeElement($utilisateursAimant); + + return $this; + } } diff --git a/src/Entity/Utilisateur.php b/src/Entity/Utilisateur.php index ab1131b048feab0d4ef142f140f5796effdd9254..0823522b864223770ee0426ff6f5fff8145952e2 100644 --- a/src/Entity/Utilisateur.php +++ b/src/Entity/Utilisateur.php @@ -72,6 +72,9 @@ class Utilisateur extends Personne #[ORM\Column] private ?bool $sommeil = null; + #[ORM\ManyToMany(targetEntity: Prestations::class, inversedBy: 'utilisateurs_aimant')] + private Collection $prestations_aimees; + public function __construct() { $this->inscriptions = new ArrayCollection(); @@ -80,6 +83,7 @@ class Utilisateur extends Personne $this->prestations_client = new ArrayCollection(); $this->prestations_proprietaire = new ArrayCollection(); $this->litiges = new ArrayCollection(); + $this->prestations_aimees = new ArrayCollection(); } public function getNbFlorains(): ?int @@ -466,4 +470,34 @@ class Utilisateur extends Personne return $this; } + + /** + * @return Collection<int, Prestations> + */ + public function getPrestationsAimees(): Collection + { + return $this->prestations_aimees; + } + + public function addPrestationsAimee(Prestations $prestationsAimee): static + { + if (!$this->prestations_aimees->contains($prestationsAimee)) { + $this->prestations_aimees->add($prestationsAimee); + } + + return $this; + } + + public function removePrestationsAimee(Prestations $prestationsAimee): static + { + $this->prestations_aimees->removeElement($prestationsAimee); + + return $this; + } + + public function aimePrestation(Prestations $prestation): bool + { + if (!$this->prestations_aimees) return false; + return $this->prestations_aimees->contains($prestation); + } } diff --git a/templates/annonce_detail/annonce.html.twig b/templates/annonce_detail/annonce.html.twig index 21887b511bf31b7132f53490cd83f7dae0f2ab69..67f15c20251975d986ee085335ed297d41be9c39 100644 --- a/templates/annonce_detail/annonce.html.twig +++ b/templates/annonce_detail/annonce.html.twig @@ -7,75 +7,101 @@ .example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; } .example-wrapper code { background: #F5F5F5; padding: 2px 6px; } </style> -<div class="annonce"> - <div class="annonce_img"> - <h1>{{ annonce.Titre }}</h1> - <img src={{asset('/img/logo.png')}} alt="logo eco-presto" width="50%"/> - {% if app.user.id is defined and (app.user.id == annonce.proprietaire.id or is_granted('ROLE_ADMIN'))%} - <button class="btn-suppression" id="deleteTransactionButton">Supprimer l'annonce</button> +{% if annonce %} + <div class="annonce"> + <div class="annonce_img"> + <h1>{{ annonce.Titre }}</h1> + <img src={{asset('/img/logo.png')}} alt="logo eco-presto" width="50%"/> + {% if app.user.id is defined and (app.user.id == annonce.proprietaire.id or is_granted('ROLE_ADMIN'))%} + <button class="btn-suppression" id="deleteTransactionButton">Supprimer l'annonce</button> - <script> - document.getElementById('deleteTransactionButton').addEventListener('click', function() { - // Afficher une boîte de dialogue de confirmation - var confirmation = confirm('Êtes-vous sûr de vouloir supprimer cette transaction ?'); + <script> + document.getElementById('deleteTransactionButton').addEventListener('click', function() { + // Afficher une boîte de dialogue de confirmation + var confirmation = confirm('Êtes-vous sûr de vouloir supprimer cette transaction ?'); - // Si l'utilisateur confirme, rediriger vers la page de suppression de la transaction - if (confirmation) { - window.location.href = '{{ path('app_delete_transaction', {'prestationId': annonce.id} ) }}'; - } - }); - </script> + // Si l'utilisateur confirme, rediriger vers la page de suppression de la transaction + if (confirmation) { + window.location.href = '{{ path('app_delete_transaction', {'prestationId': annonce.id} ) }}'; + } + }); + </script> - {% elseif app.user.id is defined %} - {% if not is_granted ("ROLE_ADMIN") and not app.user.isSommeil() %} - {% if annonce.IdClient != NULL %} - {% if user.id == annonce.IdClient.Id %} - <a href="{{ path('app_reserver_prestation', {'id': annonce.id, 'interet': false}) }}"><button class="btn-suppression" id="btnAnnuler">Annuler la réservation</button></a> + {% elseif app.user.id is defined %} + {% if not is_granted ("ROLE_ADMIN") and not app.user.isSommeil() %} + {% if annonce.IdClient != NULL %} + {% if user.id == annonce.IdClient.Id %} + <a href="{{ path('app_reserver_prestation', {'id': annonce.id, 'interet': false}) }}"><button class="btn-suppression" id="btnAnnuler">Annuler la réservation</button></a> + {% else %} + <p>Déjà réservé</p> + <a href=""><button class="btn-connexion2" id="btnListeAttente">Se mettre en liste d'attente</button></a> + {% endif %} {% else %} - <p>Déjà réservé</p> - <a href=""><button class="btn-connexion2" id="btnListeAttente">Se mettre en liste d'attente</button></a> + <a href="{{ path('app_reserver_prestation', {'id': annonce.id, 'interet': true}) }}"><button class="btn-connexion" id="btnRepondre">Répondre à l'annonce</button></a> {% endif %} - {% else %} - <a href="{{ path('app_reserver_prestation', {'id': annonce.id, 'interet': true}) }}"><button class="btn-connexion" id="btnRepondre">Répondre à l'annonce</button></a> - {% endif %} - {% endif %} - {% endif %} - - {% if not is_granted('ROLE_ADMIN') and (annonce.fournisseur != NULL) and (annonce.IdClient != NULL) %} - <a href="{{ path('app_litige_creation', {'id': annonce.id}) }}"><button class="btn-suppression" id="btnCreerLitige">Créer un litige</button></a> - {% endif %} - </div> - - <div class="annonce_desc"> - <h3>Description</h3> - {% for pret in prets %} - {% if pret.id == annonce.id %} - <p class="tag_pret" id="tag">Prêt</p> + {% endif %} {% endif %} - {% endfor %} - {% for service in services %} - {% if service.id == annonce.id %} - <p class="tag_service" id="tag">Service</p> + + {% if not is_granted('ROLE_ADMIN') and (annonce.fournisseur != NULL) and (annonce.IdClient != NULL) %} + <a href="{{ path('app_litige_creation', {'id': annonce.id}) }}"><button class="btn-suppression" id="btnCreerLitige">Créer un litige</button></a> {% endif %} - {% endfor %} - <br/> - {{ annonce.DescrPrestation }} <br/> - <hr> - <h3>Prix</h3> - {{ annonce.CoutPrestation }} florains <br/> - <hr> - <h3>Date de validité</h3> - {{ annonce.DateDebut | date('d-m-Y')}} + </div> - {% if is_granted('ROLE_ADMIN') and annonce.litiges|length > 0 %} - <hr> - <h3>Litiges</h3> - {% for litige in annonce.litiges %} - {{litige.idUtilisateur.login}} : {{litige.descrLitige}} <bt> {{litige.getStringStatus}} {{litige.dateLitige|date('d/m/y')}} - <a href="{{ path('litige_detail', {'id': litige.id}) }}"><button class="btn-connexion2" id="btnLitige">Résoudre ce litige</button></a> - <br/> + <div class="annonce_desc"> + {% if user %} + {% if user.id != annonce.proprietaire.id %} + <a href="{{ path('app_aimer_prestation', {'id': annonce.id}) }}"><button class="btn-like"> + {% if user.aimePrestation(annonce) %} + <span class="aime">❤</span> + {% else %} + <span class="non_aime">❤</span> + {% endif %} + </button></a> + {% endif %} + {% else %} + <a href="{{ path('app_aimer_prestation', {'id': annonce.id}) }}"><button class="btn-like"> + <span class="non_aime">❤</span> + </button></a> + {% endif %} + <h3>Description</h3> + {% for pret in prets %} + {% if pret.id == annonce.id %} + <p class="tag_pret" id="tag">Prêt</p> + {% endif %} + {% endfor %} + {% for service in services %} + {% if service.id == annonce.id %} + <p class="tag_service" id="tag">Service</p> + {% endif %} {% endfor %} - {% endif %} + <br/> + {{ annonce.DescrPrestation }} <br/> + <hr> + <h3>Prix</h3> + {{ annonce.CoutPrestation }} florains <br/> + <hr> + <h3>Date de validité</h3> + {{ annonce.DateDebut | date('d-m-Y')}} + <hr> + <h3>Statistiques</h3> + <p>{{ annonce.nbVues }}👁 | {{ nbAimees }} <u>J'aime</u></p> + + {% if is_granted('ROLE_ADMIN') and annonce.litiges|length > 0 %} + <hr> + <h3>Litiges</h3> + {% for litige in annonce.litiges %} + {{litige.idUtilisateur.login}} : {{litige.descrLitige}} <bt> {{litige.getStringStatus}} {{litige.dateLitige|date('d/m/y')}} + <a href="{{ path('litige_detail', {'id': litige.id}) }}"><button class="btn-connexion2" id="btnLitige">Résoudre ce litige</button></a> + <br/> + {% endfor %} + {% endif %} + </div> + </div> +{% else %} + <div class="annonce"> + <div class="annonce_img"> + <h1>Annonce inexistante ou supprimée</h1> + </div> </div> -</div> +{% endif %} {% endblock %} diff --git a/templates/notifications/index.html.twig b/templates/notifications/index.html.twig index c7dabcffb90dc76918b8ef4c53d3ff638847798e..00328b7ccb5cedfbb3bf85f3c0b76bf1732bf216 100644 --- a/templates/notifications/index.html.twig +++ b/templates/notifications/index.html.twig @@ -10,18 +10,18 @@ <h1>Notifications</h1> <table class="table_notif"> - <tr> - <td>Date</td> - <td>Type</td> - <td>Description</td> - </tr> {% if notifs %} - {% for notif in notifs %} + <tr> + <td><b>Date</b></td> + <td><b>Type</b></td> + <td><b>Description</b></td> + </tr> + {% for notif in notifs|reverse %} <tr> <td>{{ notif.date|date('d/m/y') }}</td> <td>{{ notif.type }}</td> <td>{{ notif.description }}</td> - </tr>> + </tr> {% endfor %} {% else %} <p>Aucune notification trouvée.</p> diff --git a/templates/security/userCoord.html.twig b/templates/security/userCoord.html.twig index 8f92a07ba6fd55e9671d7c5d52a8e05171b2ddd1..993bb472943d545faa8965f3a3f1412ce6817a25 100644 --- a/templates/security/userCoord.html.twig +++ b/templates/security/userCoord.html.twig @@ -18,7 +18,7 @@ <li><strong>Code postal:</strong> {{ user.codepostal }}</li> <li><strong>Ville:</strong> {{ user.ville }}</li> <li><strong>Téléphone:</strong> {{ user.telephone }}</li> - <li><strong>Status abonnement:</strong> {% if user.statusabonnement == 0 %} Abonnement standard {% else %} Abonnement premium {% endif %}</li> + <li><strong>Statut abonnement:</strong> {% if user.statusabonnement == 0 %} Abonnement standard {% else %} Abonnement premium {% endif %}</li> </ul> </div> <button class="btn-connexion2" onclick="window.location.href='{{ path("app_modif_user") }}'">Retour</button>