From b0507a44ea4f6e26726582a9b8a893d37ab4bd56 Mon Sep 17 00:00:00 2001 From: Matis MAZINGUE Date: Fri, 14 Jun 2024 09:41:05 +0200 Subject: [PATCH] like (#19) Co-authored-by: Matis MAZINGUE Co-authored-by: clfreville2 Reviewed-on: https://codefirst.iut.uca.fr/git/clement.freville2/herbarium/pulls/19 Co-authored-by: Matis MAZINGUE Co-committed-by: Matis MAZINGUE --- public/css/app.css | 12 +++++++++++ public/js/like_toggle.js | 27 ++++++++++++++++++++++++ src/Controller/PostController.php | 26 +++++++++++++++++++++++ src/Entity/Post.php | 31 ++++++++++++++++++++++++++++ src/Entity/User.php | 34 +++++++++++++++++++++++++++++++ templates/base.html.twig | 1 + templates/post/index.html.twig | 17 +++++++++++++++- 7 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 public/css/app.css create mode 100644 public/js/like_toggle.js diff --git a/public/css/app.css b/public/css/app.css new file mode 100644 index 0000000..5da752c --- /dev/null +++ b/public/css/app.css @@ -0,0 +1,12 @@ +.no-style { + background: none; + border: none; + padding: 0; + font: inherit; + color: inherit; + cursor: pointer; +} + +.no-style:focus { + outline: none; +} diff --git a/public/js/like_toggle.js b/public/js/like_toggle.js new file mode 100644 index 0000000..1f89096 --- /dev/null +++ b/public/js/like_toggle.js @@ -0,0 +1,27 @@ +document.addEventListener('DOMContentLoaded', function() { + document.querySelectorAll('.like-toggle').forEach(button => { + button.addEventListener('click', function (event) { + event.preventDefault(); + + let isLiked = this.classList.contains('liked'); + let url = isLiked ? this.dataset.unlikeUrl : this.dataset.likeUrl; + + fetch(url, { method: 'POST' }) + .then(response => response.json()) + .then(data => { + if (data.success) { + let likesCountElement = this.parentElement.querySelector('.likes-count'); + likesCountElement.textContent = data.likesCount; + this.classList.toggle('liked'); + this.classList.toggle('not-liked'); + this.innerHTML = isLiked ? '♡' : '❤️'; + } else { + console.error('Erreur lors du traitement du like/unlike.'); + } + }) + .catch(error => { + console.error('Erreur lors de la requête fetch:', error); + }); + }); + }); +}); diff --git a/src/Controller/PostController.php b/src/Controller/PostController.php index 7f4e77f..5be66b8 100644 --- a/src/Controller/PostController.php +++ b/src/Controller/PostController.php @@ -16,6 +16,7 @@ use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\CurrentUser; use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\UX\Turbo\TurboBundle; +use Symfony\Component\HttpFoundation\JsonResponse; class PostController extends AbstractController { @@ -170,4 +171,29 @@ class PostController extends AbstractController } return $this->redirectToRoute('app_post_show', ['id' => $comment->getRelatedPost()->getId()]); } + + #[Route('/post/{id}/like', name: 'app_posts_like', methods: ['POST'])] + #[IsGranted('ROLE_USER')] + public function addLike(#[CurrentUser] User $user, Post $post, EntityManagerInterface $entityManager): JsonResponse + { + $user->addLikedPost($post); + $entityManager->flush(); + + $likesCount = $post->getLikes()->count(); + + return new JsonResponse(['success' => true, 'likesCount' => $likesCount]); + } + + #[Route('/post/{id}/unlike', name: 'app_posts_unlike', methods: ['POST'])] + #[IsGranted('ROLE_USER')] + public function deleteLike(#[CurrentUser] User $user, Post $post, EntityManagerInterface $entityManager): JsonResponse + { + $user->removeLikedPost($post); + $entityManager->flush(); + + $likesCount = $post->getLikes()->count(); + + return new JsonResponse(['success' => true, 'likesCount' => $likesCount]); + } + } diff --git a/src/Entity/Post.php b/src/Entity/Post.php index fa0217a..b8b0046 100644 --- a/src/Entity/Post.php +++ b/src/Entity/Post.php @@ -84,9 +84,16 @@ class Post #[ORM\OneToMany(targetEntity: Comment::class, mappedBy: 'related_post', fetch: 'EXTRA_LAZY')] private Collection $comments; + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: User::class, inversedBy: 'liked_post')] + private Collection $likes; + public function __construct() { $this->comments = new ArrayCollection(); + $this->likes = new ArrayCollection(); } public function getId(): ?int @@ -256,4 +263,28 @@ class Post return $this; } + + /** + * @return Collection + */ + public function getLikes(): Collection + { + return $this->likes; + } + + public function addLike(User $user): static + { + if (!$this->likes->contains($user)) { + $this->likes->add($user); + } + + return $this; + } + + public function removeLike(User $user): static + { + $this->likes->removeElement($user); + + return $this; + } } diff --git a/src/Entity/User.php b/src/Entity/User.php index 8519d9d..81a6b3a 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -68,9 +68,16 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\OneToMany(targetEntity: Comment::class, mappedBy: 'author')] private Collection $comments; + /** + * @var Collection + */ + #[ORM\ManyToMany(targetEntity: Post::class, mappedBy: 'likes')] + private Collection $liked_post; + public function __construct() { $this->comments = new ArrayCollection(); + $this->liked_post = new ArrayCollection(); } public function getId(): ?int @@ -189,4 +196,31 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface return $this; } + + /** + * @return Collection + */ + public function getLikedPost(): Collection + { + return $this->liked_post; + } + + public function addLikedPost(Post $likedPost): static + { + if (!$this->liked_post->contains($likedPost)) { + $this->liked_post->add($likedPost); + $likedPost->addLike($this); + } + + return $this; + } + + public function removeLikedPost(Post $likedPost): static + { + if ($this->liked_post->removeElement($likedPost)) { + $likedPost->removeLike($this); + } + + return $this; + } } diff --git a/templates/base.html.twig b/templates/base.html.twig index 0ced7a9..903f586 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -6,6 +6,7 @@ {% block stylesheets %} + {% endblock %} {% block javascripts %} diff --git a/templates/post/index.html.twig b/templates/post/index.html.twig index d14adbc..20fc847 100644 --- a/templates/post/index.html.twig +++ b/templates/post/index.html.twig @@ -12,10 +12,25 @@

{{ post.commentary }}

{% endfor %} {% include '_pagination.html.twig' %} {% endblock %} + +{% block javascripts %} + {{ parent() }} + +{% endblock %}