diff --git a/.changes/unreleased/Feature-20251125-165811.yaml b/.changes/unreleased/Feature-20251125-165811.yaml new file mode 100644 index 000000000..3cea3958e --- /dev/null +++ b/.changes/unreleased/Feature-20251125-165811.yaml @@ -0,0 +1,6 @@ +kind: Feature +body: Add a counter for invitations awaiting reply +time: 2025-11-25T16:58:11.780678466+01:00 +custom: + Issue: "459" + SchemaChange: No schema change diff --git a/src/Bundle/ChillCalendarBundle/Menu/UserMenuBuilder.php b/src/Bundle/ChillCalendarBundle/Menu/UserMenuBuilder.php index 672b53460..df04e9bf0 100644 --- a/src/Bundle/ChillCalendarBundle/Menu/UserMenuBuilder.php +++ b/src/Bundle/ChillCalendarBundle/Menu/UserMenuBuilder.php @@ -11,17 +11,24 @@ declare(strict_types=1); namespace Chill\CalendarBundle\Menu; +use Chill\CalendarBundle\Repository\InviteRepository; use Chill\MainBundle\Routing\LocalMenuBuilderInterface; +use Chill\MainBundle\Security\ChillSecurity; use Knp\Menu\MenuItem; -use Symfony\Component\Security\Core\Security; use Symfony\Contracts\Translation\TranslatorInterface; -class UserMenuBuilder implements LocalMenuBuilderInterface +final readonly class UserMenuBuilder implements LocalMenuBuilderInterface { - public function __construct(private readonly Security $security, public TranslatorInterface $translator) {} + public function __construct( + private ChillSecurity $security, + private TranslatorInterface $translator, + private InviteRepository $inviteRepository, + ) {} - public function buildMenu($menuId, MenuItem $menu, array $parameters) + public function buildMenu($menuId, MenuItem $menu, array $parameters): void { + $invitationsPending = $this->inviteRepository->countPendingInvitesByUser($this->security->getUser()); + if ($this->security->isGranted('ROLE_USER')) { $menu->addChild('My calendar list', [ 'route' => 'chill_calendar_calendar_list_my', @@ -30,12 +37,14 @@ class UserMenuBuilder implements LocalMenuBuilderInterface 'order' => 8, 'icon' => 'tasks', ]); - $menu->addChild('invite.list.title', [ - 'route' => 'chill_calendar_invitations_list_my', - ]) + $menu->addChild( + $this->translator->trans('invite.menu with counter', ['nb' => $invitationsPending]), + ['route' => 'chill_calendar_invitations_list_my'] + ) ->setExtras([ 'order' => 9, 'icon' => 'tasks', + 'counter' => 0 < $invitationsPending ? $invitationsPending : null, ]); } } diff --git a/src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php b/src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php index 8fe28f500..6ba967871 100644 --- a/src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php +++ b/src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php @@ -75,6 +75,25 @@ class InviteRepository implements ObjectRepository ->getSingleScalarResult(); } + public function countPendingInvitesByUser(User $user): int + { + $qb = $this->entityRepository->createQueryBuilder('i'); + + $qb->select('COUNT(i)') + ->where( + $qb->expr()->andX( + $qb->expr()->eq('i.user', ':user'), + $qb->expr()->eq('i.status', ':status') + ) + ) + ->setParameters([ + 'user' => $user, + 'status' => Invite::PENDING, + ]); + + return $qb->getQuery()->getSingleScalarResult(); + } + public function buildAcceptedInviteByUserAndDateRangeQuery(User $user, \DateTimeImmutable $from, \DateTimeImmutable $to) { $qb = $this->entityRepository->createQueryBuilder('i'); diff --git a/src/Bundle/ChillCalendarBundle/translations/messages+intl-icu.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages+intl-icu.fr.yml index 4bbc105b9..7c8e59231 100644 --- a/src/Bundle/ChillCalendarBundle/translations/messages+intl-icu.fr.yml +++ b/src/Bundle/ChillCalendarBundle/translations/messages+intl-icu.fr.yml @@ -6,3 +6,11 @@ chill_calendar: few {# rendez-vous sont ignorés par le filtre de date. Modifiez le filtre de date pour les voir apparaitre.} other {# rendez-vous sont ignorés par le filtre de date. Modifiez le filtre de date pour les voir apparaitre.} } +invite: + menu with counter: >- + {nb, plural, + =0 {Mes invitations} + one {# invitation} + few {# invitations} + other {# invitations} + } diff --git a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml index b4bdd0679..60ac1d5f7 100644 --- a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml @@ -98,6 +98,7 @@ invite: list: none: Il n'y aucun invitation title: Mes invitations + number of invitations waiting: Invitations en attente # exports Exports of calendar: Exports des rendez-vous