diff --git a/src/Controller/Administrative/Feedback/IndexController.php b/src/Controller/Administrative/Feedback/IndexController.php index 273c2ed..136150a 100644 --- a/src/Controller/Administrative/Feedback/IndexController.php +++ b/src/Controller/Administrative/Feedback/IndexController.php @@ -2,6 +2,7 @@ namespace App\Controller\Administrative\Feedback; +use App\Entity\Teamer; use App\Repository\FeedbackRepository; use App\Service\Common\FeedbackFilterHandler; use Knp\Component\Pager\PaginatorInterface; @@ -46,4 +47,15 @@ class IndexController extends AbstractController 'filterDto' => $filterDto, ]); } + + #[Route('/administrative/feedback/teamer/{uuid}', name: 'app_administrative_feedback_index_teamer')] + #[IsGranted('ROLE_ADMINISTRATIVE')] + public function byTeamer(Teamer $teamer): Response + { + // The link means "show me this teamer's feedback", so previously stored + // criteria must not silently hide any of it. + $this->filterHandler->applyTeamerFilter($teamer); + + return $this->redirectToRoute('app_administrative_feedback_index'); + } } diff --git a/src/Form/FeedbackFilterType.php b/src/Form/FeedbackFilterType.php index 7d39f80..02737bb 100644 --- a/src/Form/FeedbackFilterType.php +++ b/src/Form/FeedbackFilterType.php @@ -2,6 +2,7 @@ namespace App\Form; +use App\Entity\Teamer; use App\Model\FeedbackFilterDto; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; @@ -15,6 +16,14 @@ class FeedbackFilterType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options): void { $builder + ->add('teamer', AutocompleteEntityType::class, [ + 'label' => 'Teamer', + 'required' => false, + 'class' => Teamer::class, + 'label_property' => 'name', + 'label_function' => fn (Teamer $teamer) => (string) $teamer, + 'endpoint_route' => 'app_admin_autocomplete_teamer', + ]) ->add('name', TextType::class, [ 'label' => 'Name', 'required' => false, diff --git a/src/Model/FeedbackFilterDto.php b/src/Model/FeedbackFilterDto.php index 2123759..10cdcd1 100644 --- a/src/Model/FeedbackFilterDto.php +++ b/src/Model/FeedbackFilterDto.php @@ -2,13 +2,28 @@ namespace App\Model; +use App\Entity\Teamer; + class FeedbackFilterDto extends AbstractFilterDto { + protected ?Teamer $teamer = null; protected ?string $name = null; protected ?\DateTimeImmutable $dateFrom = null; protected ?\DateTimeImmutable $dateTo = null; protected ?int $averageRating = null; + public function getTeamer(): ?Teamer + { + return $this->teamer; + } + + public function setTeamer(?Teamer $teamer): static + { + $this->teamer = $teamer; + + return $this; + } + public function getName(): ?string { return $this->name; diff --git a/src/Repository/FeedbackRepository.php b/src/Repository/FeedbackRepository.php index e375a1a..17da4bc 100644 --- a/src/Repository/FeedbackRepository.php +++ b/src/Repository/FeedbackRepository.php @@ -38,6 +38,13 @@ class FeedbackRepository extends ServiceEntityRepository ->innerJoin('teamer.user', 'user') ; + if (null !== $teamer = $filterDto->getTeamer()) { + $qb + ->andWhere($qb->expr()->eq('feedback.teamer', ':teamer')) + ->setParameter('teamer', $teamer) + ; + } + if (null !== $name = $filterDto->getName()) { $qb ->andWhere($qb->expr()->orX( diff --git a/src/Service/Common/FeedbackFilterHandler.php b/src/Service/Common/FeedbackFilterHandler.php index ddfd2ec..47a455c 100644 --- a/src/Service/Common/FeedbackFilterHandler.php +++ b/src/Service/Common/FeedbackFilterHandler.php @@ -2,6 +2,7 @@ namespace App\Service\Common; +use App\Entity\Teamer; use App\Model\AbstractFilterDto; use App\Model\FeedbackFilterDto; @@ -18,6 +19,15 @@ class FeedbackFilterHandler extends AbstractFilterHandler return $filterDto; } + if (isset($data['teamer_id'])) { + $teamer = $this + ->entityManager + ->getRepository(Teamer::class) + ->find($data['teamer_id']) + ; + $filterDto->setTeamer($teamer); + } + if (isset($data['name'])) { $filterDto->setName($data['name']); } @@ -34,10 +44,16 @@ class FeedbackFilterHandler extends AbstractFilterHandler return $filterDto; } + public function applyTeamerFilter(Teamer $teamer): void + { + $this->saveFilterSettings((new FeedbackFilterDto())->setTeamer($teamer)); + } + protected function saveFilterSettings(AbstractFilterDto $filterDto): void { /* @var FeedbackFilterDto $filterDto */ $this->getSession()->set($this->namespace, [ + 'teamer_id' => $filterDto->getTeamer()?->getId(), 'name' => $filterDto->getName(), 'date_from' => $filterDto->getDateFrom(), 'date_to' => $filterDto->getDateTo(), diff --git a/src/Twig/Components/RatingStars.php b/src/Twig/Components/RatingStars.php index 8d14706..dfcb5b5 100644 --- a/src/Twig/Components/RatingStars.php +++ b/src/Twig/Components/RatingStars.php @@ -2,10 +2,12 @@ namespace App\Twig\Components; +use App\Entity\Teamer; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; #[AsTwigComponent(template: 'components/rating_stars.html.twig')] class RatingStars { public ?int $rating; + public ?Teamer $teamer = null; } diff --git a/templates/administrative/assignment/detail.html.twig b/templates/administrative/assignment/detail.html.twig index 368d16c..7a892eb 100644 --- a/templates/administrative/assignment/detail.html.twig +++ b/templates/administrative/assignment/detail.html.twig @@ -51,7 +51,7 @@ {% include '_partials/_teamer_deleted_badge.html.twig' with { 'teamer': application.teamer } %} {{ icon('info', 'w-4 h-4') }} - + {{ ('label.application.status.' ~ application.status)|trans }} @@ -162,7 +162,7 @@ {% include '_partials/_teamer_deleted_badge.html.twig' with { 'teamer': disposition.teamer } %} {{ icon('info', 'w-4 h-4') }} - + {{ ('label.disposition.status.' ~ disposition.status)|trans }} diff --git a/templates/administrative/assignment/index.html.twig b/templates/administrative/assignment/index.html.twig index 95526cc..318cbfe 100644 --- a/templates/administrative/assignment/index.html.twig +++ b/templates/administrative/assignment/index.html.twig @@ -142,7 +142,7 @@ {{ assignment.activeDispositions|length }}/{{ assignment.availableDispositions }}
    {% for disposition in assignment.activeDispositions %} -
  • +
  • {{ disposition.teamer }} -
    +
  • {% endfor %}
diff --git a/templates/administrative/teamer/index.html.twig b/templates/administrative/teamer/index.html.twig index 1c5c471..edffa98 100644 --- a/templates/administrative/teamer/index.html.twig +++ b/templates/administrative/teamer/index.html.twig @@ -74,7 +74,7 @@ {{ icon('user', 'w-10 h-10 text-gray-200') }} {% endif %} - + diff --git a/templates/administrative/teamer/modal_info.html.twig b/templates/administrative/teamer/modal_info.html.twig index 70e034f..d78eeb5 100644 --- a/templates/administrative/teamer/modal_info.html.twig +++ b/templates/administrative/teamer/modal_info.html.twig @@ -63,7 +63,7 @@ {{ icon('user', 'w-32 h-32 text-gray-200') }} {% endif %} - +
    {% if teamer.communication.phone %}
  • diff --git a/templates/common/modal_feedback_filter.html.twig b/templates/common/modal_feedback_filter.html.twig index bc9f955..cdda1c6 100644 --- a/templates/common/modal_feedback_filter.html.twig +++ b/templates/common/modal_feedback_filter.html.twig @@ -5,6 +5,7 @@ {% block content %} {{ form_start(filterForm, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
    + {{ form_row(filterForm.teamer) }} {{ form_row(filterForm.name) }} {{ form_row(filterForm.dateFrom) }} {{ form_row(filterForm.dateTo) }} diff --git a/templates/components/rating_stars.html.twig b/templates/components/rating_stars.html.twig index e14a9dc..3dcd79f 100644 --- a/templates/components/rating_stars.html.twig +++ b/templates/components/rating_stars.html.twig @@ -1,5 +1,15 @@ -
    - {% for grade in range(1, 5) %} - {{ icon('star', html_classes('w-4 h-4', { 'text-gray-200': (rating/100)|round < grade, 'text-primary': (rating/100)|round >= grade })) }} - {% endfor %} -
    \ No newline at end of file +{% set stars %} +
    + {% for grade in range(1, 5) %} + {{ icon('star', html_classes('w-4 h-4', { 'text-gray-200': (rating/100)|round < grade, 'text-primary': (rating/100)|round >= grade })) }} + {% endfor %} +
    +{% endset %} +{% if teamer is not null and rating and is_granted('ROLE_ADMINISTRATIVE') %} + {{ stars }} +{% else %} + {{ stars }} +{% endif %}