diff --git a/fixtures/test/service_request.yaml b/fixtures/test/service_request.yaml index 95e6c00..202fd1f 100644 --- a/fixtures/test/service_request.yaml +++ b/fixtures/test/service_request.yaml @@ -11,6 +11,7 @@ App\Entity\ServiceRequest: recipient: '@user_17' startAt: '' endAt: '' + createdAt: # ongoing service request, can be finalized manually # @see ServiceRequestStatusWorkflowControllerFinalizeTest diff --git a/fixtures/test/user.yaml b/fixtures/test/user.yaml index 8f41e95..17baa41 100644 --- a/fixtures/test/user.yaml +++ b/fixtures/test/user.yaml @@ -75,6 +75,7 @@ App\Entity\User: address: '@address_region_hauts_de_france' schedule: '9h30 - 17h30' phoneNumber: null + createdAt: # —— Users ————————————————————————————————————————————————————————————————— # user with vacation mode @@ -111,6 +112,7 @@ App\Entity\User: confirmationExpiresAt: firstname: lastname: + createdAt: # user with an expired confirmation token # user with an unconfirmed email diff --git a/src/Controller/Admin/DashboardController.php b/src/Controller/Admin/DashboardController.php index 259af95..6909cf8 100755 --- a/src/Controller/Admin/DashboardController.php +++ b/src/Controller/Admin/DashboardController.php @@ -11,8 +11,13 @@ use App\Entity\Page; use App\Entity\ServiceRequest; use App\Entity\User; use App\Entity\UserGroup; +use App\Enum\User\UserType; use App\Repository\GroupRepository; +use App\Repository\ServiceRequestRepository; +use App\Repository\UserRepository; use App\Security\Checker\AuthorizationChecker; +use Doctrine\ORM\NonUniqueResultException; +use Doctrine\ORM\NoResultException; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard; use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem; @@ -55,6 +60,8 @@ final class DashboardController extends AbstractDashboardController private readonly GroupRepository $groupRepository, private readonly AdminUrlGenerator $adminUrlGenerator, private readonly AuthorizationChecker $authorizationChecker, + private readonly UserRepository $userRepository, + private readonly ServiceRequestRepository $requestRepository ) { } @@ -74,6 +81,10 @@ final class DashboardController extends AbstractDashboardController ; } + /** + * @throws NonUniqueResultException + * @throws NoResultException + */ #[Route('/admin', name: 'admin')] public function index(): Response { @@ -87,6 +98,11 @@ final class DashboardController extends AbstractDashboardController return $this->render('admin/dashboard.html.twig', [ 'group_count' => $this->groupRepository->count([]), + 'user_count' => $this->userRepository->getUserCountByType(UserType::USER), + 'place_count' => $this->userRepository->getUserCountByType(UserType::PLACE), + 'month_users_count' => $this->userRepository->getNewUsersOfMonthByType(UserType::USER), + 'month_places_count' => $this->userRepository->getNewUsersOfMonthByType(UserType::PLACE), + 'month_requests_count' => $this->requestRepository->getNewServiceRequestsOfMonth(), ]); } diff --git a/src/Repository/ServiceRequestRepository.php b/src/Repository/ServiceRequestRepository.php index 207c63b..971ced9 100644 --- a/src/Repository/ServiceRequestRepository.php +++ b/src/Repository/ServiceRequestRepository.php @@ -10,6 +10,8 @@ use App\Entity\User; use App\Enum\ServiceRequest\ServiceRequestStatus; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\NonUniqueResultException; +use Doctrine\ORM\NoResultException; use Doctrine\ORM\Query; use Doctrine\Persistence\ManagerRegistry; @@ -126,4 +128,26 @@ final class ServiceRequestRepository extends ServiceEntityRepository { return $this->getActionSoon('endAt'); } + + /** + * @throws NonUniqueResultException + * @throws NoResultException + */ + public function getNewServiceRequestsOfMonth(): int + { + $today = new \DateTime(); + + /** @var int */ + return $this + ->createQueryBuilder('sr') + ->select('COUNT(sr.id)') + ->where('sr.createdAt >= :firstDay') + ->andWhere('sr.createdAt <= :lastDay') + ->setParameters([ + 'firstDay' => $today->modify('first day of this month')->format('Y-m-d'), + 'lastDay' => $today->modify('last day of this month')->format('Y-m-d'), + ]) + ->getQuery() + ->getSingleScalarResult(); + } } diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index cfc22d8..f82f0a2 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -7,6 +7,8 @@ namespace App\Repository; use App\Entity\User; use App\Enum\User\UserType; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\ORM\NonUniqueResultException; +use Doctrine\ORM\NoResultException; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; @@ -105,4 +107,44 @@ class UserRepository extends ServiceEntityRepository implements PasswordUpgrader ->orderBy('p.name', 'ASC') ; } + + /** + * @throws NonUniqueResultException + * @throws NoResultException + */ + public function getUserCountByType(UserType $type): int + { + /** @var int */ + return $this + ->createQueryBuilder('u') + ->select('COUNT(u.id)') + ->where('u.type = :type') + ->setParameter('type', $type) + ->getQuery() + ->getSingleScalarResult(); + } + + /** + * @throws NonUniqueResultException + * @throws NoResultException + */ + public function getNewUsersOfMonthByType(UserType $type): int + { + $today = new \DateTime(); + + /** @var int */ + return $this + ->createQueryBuilder('u') + ->select('COUNT(u.id)') + ->where('u.type = :type') + ->andWhere('u.createdAt >= :firstDay') + ->andWhere('u.createdAt <= :lastDay') + ->setParameters([ + 'firstDay' => $today->modify('first day of this month')->format('Y-m-d'), + 'lastDay' => $today->modify('last day of this month')->format('Y-m-d'), + 'type' => $type, + ]) + ->getQuery() + ->getSingleScalarResult(); + } } diff --git a/templates/admin/dashboard.html.twig b/templates/admin/dashboard.html.twig index 0e66af8..e230e50 100644 --- a/templates/admin/dashboard.html.twig +++ b/templates/admin/dashboard.html.twig @@ -3,6 +3,8 @@ {% trans_default_domain 'admin' %} +{% set i18n_prefix = _self|i18n_prefix %} + {% block content_title %}Dashboard{% endblock %} {% block page_actions %} @@ -17,13 +19,54 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Nombre de groupes{{ (i18n_prefix ~ '.group')|trans }}
{{ group_count }}{{ (i18n_prefix ~ '.group_count')|trans({'%group_count%': group_count}) }}
{{ (i18n_prefix ~ '.users')|trans }}
+

{{ (i18n_prefix ~ '.month_users_count')|trans({'%month_users_count%': month_users_count}) }}

+

{{ (i18n_prefix ~ '.user_count')|trans({'%user_count%': user_count}) }}

+
{{ (i18n_prefix ~ '.places')|trans }}
+

{{ (i18n_prefix ~ '.month_places_count')|trans({'%month_places_count%': month_places_count}) }}

+

{{ (i18n_prefix ~ '.place_count')|trans({'%place_count%': place_count}) }}

+
{{ (i18n_prefix ~ '.loans')|trans }}
+

{{ (i18n_prefix ~ '.month_requests_count')|trans({'%month_requests_count%': month_requests_count}) }}

+
{% endblock %} diff --git a/translations/templates/admin/dashboard/admin.fr.xlf b/translations/templates/admin/dashboard/admin.fr.xlf new file mode 100644 index 0000000..ed7e125 --- /dev/null +++ b/translations/templates/admin/dashboard/admin.fr.xlf @@ -0,0 +1,59 @@ + + + +
+ +
+ + + templates.admin.dashboard.group + Groupes + + + + templates.admin.dashboard.group_count + Nombre de groupe: %group_count% + + + + templates.admin.dashboard.users + Utilisateurs + + + + templates.admin.dashboard.month_users_count + Nombre de nouveaux utilisateurs du mois: %month_users_count% + + + + templates.admin.dashboard.user_count + Nombre total: %user_count% + + + + templates.admin.dashboard.places + Lieux + + + + templates.admin.dashboard.month_places_count + Nombre de nouveaux lieux du mois: %month_places_count% + + + + templates.admin.dashboard.place_count + Nombre total: %place_count% + + + + templates.admin.dashboard.loans + Emprunts + + + + templates.admin.dashboard.month_requests_count + Nombre d’emprunts du mois: %month_requests_count% + + +
+