feat: additional filter options for documents
This commit is contained in:
@@ -32,6 +32,7 @@ services:
|
||||
autoconfigure: true
|
||||
bind:
|
||||
$logger: '@monolog.logger.myep'
|
||||
$destinations: '%destinations%'
|
||||
|
||||
App\:
|
||||
resource: '../src/'
|
||||
@@ -166,7 +167,3 @@ services:
|
||||
$defaults:
|
||||
from: '%default_email_from%'
|
||||
to: '%default_email_to%'
|
||||
|
||||
App\Form\AssignmentFilterType:
|
||||
arguments:
|
||||
$destinations: '%destinations%'
|
||||
@@ -4,6 +4,7 @@ namespace App\Controller\Common;
|
||||
|
||||
use App\Form\DocumentFilterType;
|
||||
use App\Htmx\HxRedirectResponse;
|
||||
use App\Repository\AssignmentRepository;
|
||||
use App\Service\Common\DocumentFilterHandler;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -13,8 +14,10 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class DocumentFilterController extends AbstractController
|
||||
{
|
||||
public function __construct(private readonly DocumentFilterHandler $filterHandler)
|
||||
{
|
||||
public function __construct(
|
||||
private readonly DocumentFilterHandler $filterHandler,
|
||||
private readonly AssignmentRepository $assignmentRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/common/document/filter', name: 'app_common_document_filter')]
|
||||
@@ -22,8 +25,12 @@ class DocumentFilterController extends AbstractController
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$formData = $this->filterHandler->getFilterSettings();
|
||||
$filterOptions = $this->assignmentRepository->getFilterOptions();
|
||||
$formOptions = [
|
||||
'job_profiles' => $filterOptions['jobProfiles'],
|
||||
];
|
||||
|
||||
$form = $this->createForm(DocumentFilterType::class, $formData);
|
||||
$form = $this->createForm(DocumentFilterType::class, $formData, $formOptions);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
|
||||
@@ -19,8 +19,15 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class AssignmentFilterType extends AbstractType
|
||||
{
|
||||
private array $hotelChoices = [];
|
||||
|
||||
public function __construct(private readonly Security $security, private readonly array $destinations)
|
||||
{
|
||||
$destinations = $this->destinations;
|
||||
sort($destinations);
|
||||
foreach ($destinations as $item) {
|
||||
$this->hotelChoices[$item] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
@@ -99,18 +106,13 @@ class AssignmentFilterType extends AbstractType
|
||||
])
|
||||
;
|
||||
}
|
||||
$hotelChoices = [];
|
||||
$destinations = $this->destinations;
|
||||
sort($destinations);
|
||||
foreach ($destinations as $item) {
|
||||
$hotelChoices[$item] = $item;
|
||||
}
|
||||
|
||||
$builder
|
||||
->add('hotels', MultiselectType::class, [
|
||||
'label' => 'Haus/Destination',
|
||||
'required' => false,
|
||||
'empty_label' => 'nicht filtern',
|
||||
'choices' => $hotelChoices,
|
||||
'choices' => $this->hotelChoices,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\JobProfile;
|
||||
use App\Entity\Teamer;
|
||||
use App\Entity\Upload;
|
||||
use App\Model\DocumentFilterDto;
|
||||
@@ -13,6 +14,17 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class DocumentFilterType extends AbstractType
|
||||
{
|
||||
private array $hotelChoices = [];
|
||||
|
||||
public function __construct(private readonly array $destinations)
|
||||
{
|
||||
$destinations = $this->destinations;
|
||||
sort($destinations);
|
||||
foreach ($destinations as $item) {
|
||||
$this->hotelChoices[$item] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
@@ -32,6 +44,20 @@ class DocumentFilterType extends AbstractType
|
||||
'Honorarvertrag' => Upload::TYPE_CONTRACT,
|
||||
],
|
||||
])
|
||||
->add('jobProfiles', MultiselectEntityType::class, [
|
||||
'label' => 'Job-Profil',
|
||||
'class' => JobProfile::class,
|
||||
'required' => false,
|
||||
'empty_label' => 'nicht filtern',
|
||||
'choice_label' => 'name',
|
||||
'choices' => $options['job_profiles'],
|
||||
])
|
||||
->add('hotels', MultiselectType::class, [
|
||||
'label' => 'Haus/Destination',
|
||||
'required' => false,
|
||||
'empty_label' => 'nicht filtern',
|
||||
'choices' => $this->hotelChoices,
|
||||
])
|
||||
->add('dateFrom', DatepickerType::class, [
|
||||
'label' => 'Einsatzzeitraum von',
|
||||
'attr' => [
|
||||
@@ -44,6 +70,18 @@ class DocumentFilterType extends AbstractType
|
||||
'placeholder' => 'nicht filtern',
|
||||
],
|
||||
])
|
||||
->add('status', ChoiceType::class, [
|
||||
'label' => 'Status',
|
||||
'required' => false,
|
||||
'placeholder' => 'nicht filtern',
|
||||
'choices' => [
|
||||
'neu' => Upload::STATUS_NEW,
|
||||
'in Bearbeitung' => Upload::STATUS_PENDING,
|
||||
'bestätigt' => Upload::STATUS_CHECKED,
|
||||
'abgelehnt' => Upload::STATUS_REJECTED,
|
||||
'bezahlt' => Upload::STATUS_PAID,
|
||||
],
|
||||
])
|
||||
->add('apply', SubmitType::class, [
|
||||
'label' => 'filtern',
|
||||
])
|
||||
@@ -58,6 +96,7 @@ class DocumentFilterType extends AbstractType
|
||||
$resolver
|
||||
->setDefaults([
|
||||
'data_class' => DocumentFilterDto::class,
|
||||
'job_profiles' => [],
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
@@ -8,8 +8,11 @@ class DocumentFilterDto extends AbstractFilterDto
|
||||
{
|
||||
protected ?Teamer $teamer = null;
|
||||
protected ?string $type = null;
|
||||
protected array $jobProfiles = [];
|
||||
protected array $hotels = [];
|
||||
protected ?\DateTimeImmutable $dateFrom = null;
|
||||
protected ?\DateTimeImmutable $dateTo = null;
|
||||
protected ?string $status = null;
|
||||
|
||||
public function getTeamer(): ?Teamer
|
||||
{
|
||||
@@ -35,6 +38,30 @@ class DocumentFilterDto extends AbstractFilterDto
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getJobProfiles(): array
|
||||
{
|
||||
return $this->jobProfiles;
|
||||
}
|
||||
|
||||
public function setJobProfiles(array $jobProfiles): static
|
||||
{
|
||||
$this->jobProfiles = $jobProfiles;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHotels(): ?array
|
||||
{
|
||||
return $this->hotels;
|
||||
}
|
||||
|
||||
public function setHotels(array $hotels): static
|
||||
{
|
||||
$this->hotels = $hotels;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateFrom(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->dateFrom;
|
||||
@@ -58,4 +85,16 @@ class DocumentFilterDto extends AbstractFilterDto
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStatus(): ?string
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function setStatus(?string $status): static
|
||||
{
|
||||
$this->status = $status;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -123,6 +123,27 @@ class UploadRepository extends ServiceEntityRepository
|
||||
;
|
||||
}
|
||||
|
||||
if (null !== $status = $filterDto->getStatus()) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->eq('upload.status', ':status'))
|
||||
->setParameter('status', $status)
|
||||
;
|
||||
}
|
||||
|
||||
if ($jobProfiles = $filterDto->getJobProfiles()) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->in('assignment.jobProfile', ':jobProfiles'))
|
||||
->setParameter('jobProfiles', $jobProfiles)
|
||||
;
|
||||
}
|
||||
|
||||
foreach ($filterDto->getHotels() as $hotel) {
|
||||
$qb
|
||||
->andWhere($qb->expr()->like('destination.hotel', ':hotel'))
|
||||
->setParameter('hotel', '%'.$hotel.'%')
|
||||
;
|
||||
}
|
||||
|
||||
return $qb->getQuery();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Service\Common;
|
||||
|
||||
use App\Entity\JobProfile;
|
||||
use App\Entity\Teamer;
|
||||
use App\Model\AbstractFilterDto;
|
||||
use App\Model\DocumentFilterDto;
|
||||
@@ -33,6 +34,23 @@ class DocumentFilterHandler extends AbstractFilterHandler
|
||||
$filterDto->setTeamer($teamer);
|
||||
}
|
||||
|
||||
if (isset($data['job_profiles']) && 0 < count($data['job_profiles'])) {
|
||||
$jobProfiles = $this
|
||||
->entityManager
|
||||
->getRepository(JobProfile::class)
|
||||
->findBy(['id' => $data['job_profiles']])
|
||||
;
|
||||
$filterDto->setJobProfiles($jobProfiles);
|
||||
}
|
||||
|
||||
if (isset($data['hotels']) && 0 < count($data['hotels'])) {
|
||||
$filterDto->setHotels($data['hotels']);
|
||||
}
|
||||
|
||||
if (isset($data['status'])) {
|
||||
$filterDto->setStatus($data['status']);
|
||||
}
|
||||
|
||||
return $filterDto;
|
||||
}
|
||||
|
||||
@@ -44,6 +62,11 @@ class DocumentFilterHandler extends AbstractFilterHandler
|
||||
'type' => $filterDto->getType(),
|
||||
'date_from' => $filterDto->getDateFrom(),
|
||||
'date_to' => $filterDto->getDateTo(),
|
||||
'job_profiles' => array_map(function (JobProfile $jobProfile) {
|
||||
return $jobProfile->getId();
|
||||
}, $filterDto->getJobProfiles()),
|
||||
'hotels' => $filterDto->getHotels(),
|
||||
'status' => $filterDto->getStatus(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,9 @@
|
||||
{{ 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.type) }}
|
||||
{{ form_row(filterForm.status) }}
|
||||
{{ form_row(filterForm.jobProfiles) }}
|
||||
{{ form_row(filterForm.hotels) }}
|
||||
{{ form_row(filterForm.teamer) }}
|
||||
{{ form_row(filterForm.dateFrom) }}
|
||||
{{ form_row(filterForm.dateTo) }}
|
||||
|
||||
Reference in New Issue
Block a user