Feat: Implement availabilities
This commit is contained in:
1 parent
cc9700a558
commit
25a016a02b
35 files changed
+827
-422
No files matched your search
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Availability;
|
||||
|
||||
use App\Entity\Availability;
|
||||
use App\Form\AvailabilityType;
|
||||
use App\Model\AjaxModalResponseDto;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class CreateController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/availability/create', name: 'app_admin_system_availability_create')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$response = new AjaxModalResponseDto();
|
||||
$action = $this->generateUrl('app_admin_system_availability_create');
|
||||
|
||||
$availability = new Availability();
|
||||
$form = $this->createForm(AvailabilityType::class, $availability, ['action' => $action, 'ajax_submit' => true]);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->entityManager->persist($availability);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Der Zeitraum wurde hinzugefügt.');
|
||||
$this->logger->info('Add availability', [
|
||||
'availability' => $availability,
|
||||
]);
|
||||
|
||||
$redirectUrl = $this->generateUrl('app_admin_system_availability_index');
|
||||
$response->setCloseAndRedirect($redirectUrl);
|
||||
} else {
|
||||
$content = $this->renderView('admin/system/availability/create.html.twig', [
|
||||
'form' => $form,
|
||||
]);
|
||||
$response->setContent($content);
|
||||
}
|
||||
|
||||
return $this->json($response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Availability;
|
||||
|
||||
use App\Entity\Availability;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class DeleteController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/availability/delete/{id}', name: 'app_admin_system_availability_delete', methods: ['POST'])]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Availability $availability): Response
|
||||
{
|
||||
$this->entityManager->remove($availability);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Die Verfügbarkeit wurde gelöscht');
|
||||
$this->logger->info('Delete availability', [
|
||||
'availability' => $availability,
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_availability_index');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Availability;
|
||||
|
||||
use App\Repository\AvailabilityRepository;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AvailabilityRepository $availabilityRepository,
|
||||
private readonly PaginatorInterface $paginator
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/availability', name: 'app_admin_system_availability_index')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$query = $this
|
||||
->availabilityRepository
|
||||
->getListQuery()
|
||||
;
|
||||
|
||||
$pagination = $this->paginator->paginate(
|
||||
$query,
|
||||
$request->query->getInt('page', 1),
|
||||
10,
|
||||
[
|
||||
'defaultSortFieldName' => 'availability.dateFrom',
|
||||
'defaultSortDirection' => 'asc',
|
||||
]
|
||||
);
|
||||
|
||||
return $this->render('admin/system/availability/index.html.twig', [
|
||||
'pagination' => $pagination,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,12 @@ namespace App\Controller\Admin\System\Fee;
|
||||
|
||||
use App\Entity\Fee;
|
||||
use App\Form\FeeType;
|
||||
use App\Model\AjaxModalResponseDto;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
@@ -22,10 +23,13 @@ class CreateController extends AbstractController
|
||||
|
||||
#[Route('/admin/system/fee/create', name: 'app_admin_system_fee_create')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Request $request): Response
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$response = new AjaxModalResponseDto();
|
||||
$action = $this->generateUrl('app_admin_system_fee_create');
|
||||
|
||||
$fee = new Fee();
|
||||
$form = $this->createForm(FeeType::class, $fee);
|
||||
$form = $this->createForm(FeeType::class, $fee, ['action' => $action, 'ajax_submit' => true]);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
@@ -37,11 +41,15 @@ class CreateController extends AbstractController
|
||||
'fee' => $fee->getName(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_fee_index');
|
||||
$redirectUrl = $this->generateUrl('app_admin_system_fee_index');
|
||||
$response->setCloseAndRedirect($redirectUrl);
|
||||
} else {
|
||||
$content = $this->renderView('admin/system/fee/create.html.twig', [
|
||||
'form' => $form
|
||||
]);
|
||||
$response->setContent($content);
|
||||
}
|
||||
|
||||
return $this->render('admin/system/fee/create.html.twig', [
|
||||
'form' => $form
|
||||
]);
|
||||
return $this->json($response);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Fee;
|
||||
|
||||
use App\Entity\Fee;
|
||||
use App\Form\FeeType;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class EditController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/fee/edit/{id}', name: 'app_admin_system_fee_edit')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Fee $fee, Request $request): Response
|
||||
{
|
||||
$form = $this->createForm(FeeType::class, $fee);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->entityManager->persist($fee);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Das Honorar wurde aktualisiert');
|
||||
$this->logger->info('Edit fee', [
|
||||
'fee' => $fee->getName(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_fee_index');
|
||||
}
|
||||
|
||||
return $this->render('admin/system/fee/edit.html.twig', [
|
||||
'form' => $form
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,12 @@ namespace App\Controller\Admin\System\Training;
|
||||
|
||||
use App\Entity\Training;
|
||||
use App\Form\TrainingType;
|
||||
use App\Model\AjaxModalResponseDto;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
@@ -22,10 +23,13 @@ class CreateController extends AbstractController
|
||||
|
||||
#[Route('/admin/system/training/create', name: 'app_admin_system_training_create')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Request $request): Response
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$response = new AjaxModalResponseDto();
|
||||
$action = $this->generateUrl('app_admin_system_training_create');
|
||||
|
||||
$training = new Training();
|
||||
$form = $this->createForm(TrainingType::class, $training);
|
||||
$form = $this->createForm(TrainingType::class, $training, ['action' => $action, 'ajax_submit' => true]);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
@@ -37,11 +41,15 @@ class CreateController extends AbstractController
|
||||
'training' => $training->getName(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_training_index');
|
||||
$redirectUrl = $this->generateUrl('app_admin_system_training_index');
|
||||
$response->setCloseAndRedirect($redirectUrl);
|
||||
} else {
|
||||
$content = $this->renderView('admin/system/training/create.html.twig', [
|
||||
'form' => $form
|
||||
]);
|
||||
$response->setContent($content);
|
||||
}
|
||||
|
||||
return $this->render('admin/system/training/create.html.twig', [
|
||||
'form' => $form
|
||||
]);
|
||||
return $this->json($response);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Training;
|
||||
|
||||
use App\Entity\Training;
|
||||
use App\Form\TrainingType;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class EditController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/training/edit/{id}', name: 'app_admin_system_training_edit')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Training $training, Request $request): Response
|
||||
{
|
||||
$form = $this->createForm(TrainingType::class, $training);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Die Fortbildung wurde aktualisiert');
|
||||
$this->logger->info('Edit training', [
|
||||
'training' => $training->getName(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_training_index');
|
||||
}
|
||||
|
||||
return $this->render('admin/system/training/edit.html.twig', [
|
||||
'form' => $form
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Teamer\Profile;
|
||||
|
||||
use App\Entity\Availability;
|
||||
use App\Entity\User;
|
||||
use App\Repository\AvailabilityRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class AvailabilitiesController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AvailabilityRepository $availabilityRepository,
|
||||
private readonly EntityManagerInterface $entityManager
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/teamer/profile/availabilities', name: 'app_teamer_profile_availabilities')]
|
||||
#[IsGranted('ROLE_TEAMER')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
$teamer = $user->getTeamer();
|
||||
|
||||
$selectableAvailabilities = $this->availabilityRepository->getSelectable($teamer);
|
||||
$form = $this->createFormBuilder($teamer)
|
||||
->add('availabilities', EntityType::class, [
|
||||
'label' => false,
|
||||
'class' => Availability::class,
|
||||
'choice_label' => function($choice) {
|
||||
return sprintf('%s - %s', $choice->getDateFrom()->format('d.m.Y'), $choice->getDateTo()->format('d.m.Y'));
|
||||
},
|
||||
'choices' => $selectableAvailabilities,
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
])
|
||||
->getForm()
|
||||
;
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $this->redirectToRoute('app_teamer_profile_availabilities');
|
||||
}
|
||||
|
||||
return $this->render('teamer/profile/availabilities.html.twig', [
|
||||
'availabilities' => $teamer->getAvailabilities(),
|
||||
'selectableAvailabilities' => $selectableAvailabilities,
|
||||
'form' => $form,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Teamer\Profile\Availability;
|
||||
|
||||
use App\Entity\Availability;
|
||||
use App\Entity\User;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class AddController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/teamer/profile/availability/add/{id}', name: 'app_teamer_profile_availability_add')]
|
||||
#[IsGranted('ROLE_TEAMER')]
|
||||
public function index(Availability $availability): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
$teamer = $user->getTeamer();
|
||||
|
||||
$teamer->addAvailability($availability);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->logger->info('Add availability', [
|
||||
'user' => $user->getUserIdentifier(),
|
||||
'availability' => $availability,
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_teamer_profile_availability_index');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Teamer\Profile\Availability;
|
||||
|
||||
use App\Entity\Availability;
|
||||
use App\Entity\User;
|
||||
use App\Form\AvailabilityType;
|
||||
use App\Model\AjaxModalResponseDto;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class CreateController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/teamer/profile/availability/create', name: 'app_teamer_profile_availability_create')]
|
||||
#[IsGranted('ROLE_TEAMER')]
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$response = new AjaxModalResponseDto();
|
||||
$action = $this->generateUrl('app_teamer_profile_availability_create');
|
||||
|
||||
$availability = new Availability();
|
||||
|
||||
$form = $this->createForm(AvailabilityType::class, $availability, ['action' => $action, 'ajax_submit' => true]);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
$teamer = $user->getTeamer();
|
||||
$teamer
|
||||
->addAvailability($availability)
|
||||
->addCustomAvailability($availability)
|
||||
;
|
||||
|
||||
$this->entityManager->persist($availability);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Der Zeitraum wurde hinzugefügt.');
|
||||
$this->logger->info('Add availability', [
|
||||
'availability' => $availability,
|
||||
]);
|
||||
|
||||
$redirectUrl = $this->generateUrl('app_teamer_profile_availability_index');
|
||||
$response->setCloseAndRedirect($redirectUrl);
|
||||
} else {
|
||||
$content = $this->renderView('teamer/profile/availability/create.html.twig', [
|
||||
'form' => $form,
|
||||
]);
|
||||
$response->setContent($content);
|
||||
}
|
||||
|
||||
return $this->json($response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Teamer\Profile\Availability;
|
||||
|
||||
use App\Entity\Availability;
|
||||
use App\Entity\User;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class DeleteController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/teamer/profile/availability/delete/{id}', name: 'app_teamer_profile_availability_delete')]
|
||||
#[IsGranted('DELETE', subject: 'availability')]
|
||||
public function index(Availability $availability): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
$teamer = $user->getTeamer();
|
||||
|
||||
if (null === $availability->getOwner()) {
|
||||
$teamer->removeAvailability($availability);
|
||||
} elseif ($teamer === $availability->getOwner()) {
|
||||
$this->entityManager->remove($availability);
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Der Zeitraum wurde entfernt/gelöscht.');
|
||||
$this->logger->info('Delete availability', [
|
||||
'user' => $this->getUser()->getUserIdentifier(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_teamer_profile_availability_index');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Teamer\Profile\Availability;
|
||||
|
||||
use App\Entity\Availability;
|
||||
use App\Entity\User;
|
||||
use App\Repository\AvailabilityRepository;
|
||||
use Carbon\Carbon;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
public function __construct(private readonly AvailabilityRepository $availabilityRepository)
|
||||
{}
|
||||
|
||||
#[Route('/teamer/profile/availabilities', name: 'app_teamer_profile_availability_index')]
|
||||
#[IsGranted('ROLE_TEAMER')]
|
||||
public function index(): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
$teamer = $user->getTeamer();
|
||||
|
||||
$availabilities = $teamer->getAvailabilities()->toArray();
|
||||
$selectedAvailabilities = $this->groupRecords($availabilities);
|
||||
|
||||
$availabilities = $this->availabilityRepository->getSelectableForTeamer($teamer);
|
||||
$selectableAvailabilities = $this->groupRecords($availabilities);
|
||||
|
||||
return $this->render('teamer/profile/availability/index.html.twig', [
|
||||
'selectedAvailabilities' => $selectedAvailabilities,
|
||||
'selectableAvailabilities' => $selectableAvailabilities,
|
||||
]);
|
||||
}
|
||||
|
||||
private function groupRecords(array $records): array
|
||||
{
|
||||
$selectableAvailabilities = [];
|
||||
|
||||
foreach ($records as $record) {
|
||||
/** @var Availability $record */
|
||||
$dateFrom = $record->getDateFrom();
|
||||
$year = $dateFrom->format('Y');
|
||||
$month = (new Carbon($dateFrom))->locale('de_DE')->monthName;
|
||||
|
||||
if (false === isset($selectableAvailabilities[$year])) {
|
||||
$selectableAvailabilities[$year] = [];
|
||||
}
|
||||
|
||||
if (false === isset($selectableAvailabilities[$year][$month])) {
|
||||
$selectableAvailabilities[$year][$month] = [];
|
||||
}
|
||||
|
||||
$selectableAvailabilities[$year][$month][] = $record;
|
||||
}
|
||||
|
||||
return $selectableAvailabilities;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
#[ORM\Entity(repositoryClass: AvailabilityRepository::class)]
|
||||
class Availability implements BlameableEntityInterface, TimestampableEntityInterface
|
||||
@@ -22,9 +23,12 @@ class Availability implements BlameableEntityInterface, TimestampableEntityInter
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
|
||||
#[Assert\NotNull(message: 'Bitte gib das Datum an')]
|
||||
private ?\DateTimeImmutable $dateFrom = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
|
||||
#[Assert\NotNull(message: 'Bitte gib das Datum an')]
|
||||
#[Assert\GreaterThan(propertyPath: 'dateFrom', message: 'Das Datum muss nach dem Beginndatum liegen')]
|
||||
private ?\DateTimeImmutable $dateTo = null;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'customAvailabilities')]
|
||||
@@ -38,6 +42,11 @@ class Availability implements BlameableEntityInterface, TimestampableEntityInter
|
||||
$this->teamers = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf('%s - %s', $this->getDateFrom()->format('d.m.Y'), $this->getDateTo()->format('d.m.Y'));
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@@ -48,7 +57,7 @@ class Availability implements BlameableEntityInterface, TimestampableEntityInter
|
||||
return $this->dateFrom;
|
||||
}
|
||||
|
||||
public function setDateFrom(\DateTimeImmutable $dateFrom): static
|
||||
public function setDateFrom(?\DateTimeImmutable $dateFrom): static
|
||||
{
|
||||
$this->dateFrom = $dateFrom;
|
||||
|
||||
@@ -60,7 +69,7 @@ class Availability implements BlameableEntityInterface, TimestampableEntityInter
|
||||
return $this->dateTo;
|
||||
}
|
||||
|
||||
public function setDateTo(\DateTimeImmutable $dateTo): static
|
||||
public function setDateTo(?\DateTimeImmutable $dateTo): static
|
||||
{
|
||||
$this->dateTo = $dateTo;
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ class Teamer implements TimestampableEntityInterface
|
||||
private ?string $remarks = null;
|
||||
|
||||
#[ORM\ManyToMany(targetEntity: Availability::class, inversedBy: 'teamers')]
|
||||
#[ORM\OrderBy(['dateFrom' => 'ASC'])]
|
||||
private Collection $availabilities;
|
||||
|
||||
#[ORM\OneToMany(mappedBy: 'owner', targetEntity: Availability::class)]
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Availability;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class AvailabilityType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('dateFrom', DatepickerType::class, [
|
||||
'label' => 'Datum von',
|
||||
'min_date' => new \DateTimeImmutable(),
|
||||
])
|
||||
->add('dateTo', DatepickerType::class, [
|
||||
'label' => 'Datum bis',
|
||||
'min_date' => new \DateTimeImmutable(),
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Availability::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -41,35 +41,17 @@ class AdminMenuBuilder extends AbstractMenuBuilder
|
||||
'title' => 'Einstellungen',
|
||||
'icon' => 'settings',
|
||||
'children' => [
|
||||
[
|
||||
'route' => 'app_admin_system_availability_index',
|
||||
'title' => 'Verfügbarkeiten',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_fee_index',
|
||||
'title' => 'Honorare',
|
||||
'children' => [
|
||||
[
|
||||
'route' => 'app_admin_system_fee_create',
|
||||
'title' => 'Honorar anlegen',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_fee_edit',
|
||||
'routeParameters' => $this->getDefaultRouteParameters(),
|
||||
'title' => 'Honorar bearbeiten',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_training_index',
|
||||
'title' => 'Fortbildungen',
|
||||
'children' => [
|
||||
[
|
||||
'route' => 'app_admin_system_training_create',
|
||||
'title' => 'Fortbildung anlegen',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_training_edit',
|
||||
'routeParameters' => $this->getDefaultRouteParameters(),
|
||||
'title' => 'Fortbildung bearbeiten',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_job_profile_index',
|
||||
@@ -79,6 +61,11 @@ class AdminMenuBuilder extends AbstractMenuBuilder
|
||||
'route' => 'app_admin_system_job_profile_create',
|
||||
'title' => 'Job-Profil anlegen',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_job_profile_edit',
|
||||
'routeParameters' => $this->getDefaultRouteParameters(),
|
||||
'title' => 'Job-Profil bearbeiten',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
|
||||
@@ -28,7 +28,7 @@ class TeamerMenuBuilder extends AbstractMenuBuilder
|
||||
'title' => 'Jobprofile & Skills',
|
||||
],
|
||||
[
|
||||
'route' => 'app_teamer_profile_availabilities',
|
||||
'route' => 'app_teamer_profile_availability_index',
|
||||
'title' => 'Meine Verfügbarkeit',
|
||||
],
|
||||
],
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Repository;
|
||||
use App\Entity\Availability;
|
||||
use App\Entity\Teamer;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
@@ -22,7 +23,22 @@ class AvailabilityRepository extends ServiceEntityRepository
|
||||
parent::__construct($registry, Availability::class);
|
||||
}
|
||||
|
||||
public function getSelectable(Teamer $teamer): array
|
||||
public function getListQuery(): Query
|
||||
{
|
||||
$qb = $this->createQueryBuilder('availability');
|
||||
|
||||
return $qb
|
||||
->where($qb->expr()->andX(
|
||||
$qb->expr()->gt('availability.dateFrom', ':today'),
|
||||
$qb->expr()->isNull('availability.owner')
|
||||
))
|
||||
->orderBy('availability.dateFrom', 'ASC')
|
||||
->setParameter('today', new \DateTimeImmutable())
|
||||
->getQuery()
|
||||
;
|
||||
}
|
||||
|
||||
public function getSelectableForTeamer(Teamer $teamer): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('availability');
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Security\Voter;
|
||||
|
||||
use App\Entity\Availability;
|
||||
use App\Entity\User;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
|
||||
class AvailabilityVoter extends Voter
|
||||
{
|
||||
public const ASSIGN = 'ASSIGN';
|
||||
public const DELETE = 'DELETE';
|
||||
|
||||
public function __construct(private readonly Security $security)
|
||||
{}
|
||||
|
||||
protected function supports(string $attribute, mixed $subject): bool
|
||||
{
|
||||
if (!$subject instanceof Availability) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($attribute, [static::ASSIGN, static::DELETE]);
|
||||
}
|
||||
|
||||
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
|
||||
{
|
||||
/** @var Availability $availability */
|
||||
$availability = $subject;
|
||||
|
||||
if (true === $this->security->isGranted('ROLE_ADMINISTRATIVE')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @var User $user */
|
||||
$user = $this->security->getUser();
|
||||
$teamer = $user->getTeamer();
|
||||
|
||||
return null === $availability->getOwner() || $teamer === $availability->getOwner();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user