feat: link ratings widget with feedback list filtered by teamer
addresses #869at5mdu
This commit is contained in:
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
{% include '_partials/_teamer_deleted_badge.html.twig' with { 'teamer': application.teamer } %}
|
||||
{{ icon('info', 'w-4 h-4') }}
|
||||
</button>
|
||||
<twig:RatingStars rating="{{ application.teamer.averageRating }}" />
|
||||
<twig:RatingStars rating="{{ application.teamer.averageRating }}" :teamer="application.teamer" />
|
||||
</td>
|
||||
<td>
|
||||
{{ ('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') }}
|
||||
</button>
|
||||
<twig:RatingStars rating="{{ disposition.teamer.averageRating }}" />
|
||||
<twig:RatingStars rating="{{ disposition.teamer.averageRating }}" :teamer="disposition.teamer" />
|
||||
</td>
|
||||
<td>
|
||||
{{ ('label.disposition.status.' ~ disposition.status)|trans }}
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
<span>{{ assignment.activeDispositions|length }}/{{ assignment.availableDispositions }}</span>
|
||||
<ul>
|
||||
{% for disposition in assignment.activeDispositions %}
|
||||
<li>
|
||||
<li class="flex items-center space-x-1">
|
||||
<div role="button"
|
||||
title="Teamer:innen-Info anzeigen"
|
||||
aria-label="Teamer:innen-Info anzeigen"
|
||||
@@ -150,8 +150,8 @@
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
<span class="whitespace-nowrap">{{ disposition.teamer }}</span>
|
||||
<twig:RatingStars rating="{{ disposition.teamer.averageRating }}" />
|
||||
</div>
|
||||
<twig:RatingStars rating="{{ disposition.teamer.averageRating }}" :teamer="disposition.teamer" />
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
{{ icon('user', 'w-10 h-10 text-gray-200') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<twig:RatingStars rating="{{ teamer.averageRating }}" />
|
||||
<twig:RatingStars rating="{{ teamer.averageRating }}" :teamer="teamer" />
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
{{ icon('user', 'w-32 h-32 text-gray-200') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<twig:RatingStars rating="{{ teamer.averageRating }}"/>
|
||||
<twig:RatingStars rating="{{ teamer.averageRating }}" :teamer="teamer"/>
|
||||
<ul class="pb-8 divide-y divide-gray-200">
|
||||
{% if teamer.communication.phone %}
|
||||
<li class="py-2">
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
{% block content %}
|
||||
{{ form_start(filterForm, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
|
||||
<div class="flex flex-col space-y-2 pb-4">
|
||||
{{ form_row(filterForm.teamer) }}
|
||||
{{ form_row(filterForm.name) }}
|
||||
{{ form_row(filterForm.dateFrom) }}
|
||||
{{ form_row(filterForm.dateTo) }}
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
{% set stars %}
|
||||
<div class="inline-flex items-center">
|
||||
{% 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 %}
|
||||
</div>
|
||||
{% endset %}
|
||||
{% if teamer is not null and rating and is_granted('ROLE_ADMINISTRATIVE') %}
|
||||
<a href="{{ path('app_administrative_feedback_index_teamer', { 'uuid': teamer.uuid }) }}"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
title="Feedback anzeigen">{{ stars }}</a>
|
||||
{% else %}
|
||||
{{ stars }}
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user