Feat: Implement availabilities
This commit is contained in:
@@ -141,9 +141,15 @@
|
||||
<symbol id="icon-folder" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
||||
<path d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</symbol>
|
||||
<symbol id="icon-bus" fill="currentColor" stroke="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<!-- Font Awesome Pro 5.15.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
||||
<path d="M488 128h-8V80c0-44.8-99.2-80-224-80S32 35.2 32 80v48h-8c-13.25 0-24 10.74-24 24v80c0 13.25 10.75 24 24 24h8v160c0 17.67 14.33 32 32 32v32c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32v-32h192v32c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32v-32h6.4c16 0 25.6-12.8 25.6-25.6V256h8c13.25 0 24-10.75 24-24v-80c0-13.26-10.75-24-24-24zM112 400c-17.67 0-32-14.33-32-32s14.33-32 32-32 32 14.33 32 32-14.33 32-32 32zm16-112c-17.67 0-32-14.33-32-32V128c0-17.67 14.33-32 32-32h256c17.67 0 32 14.33 32 32v128c0 17.67-14.33 32-32 32H128zm272 112c-17.67 0-32-14.33-32-32s14.33-32 32-32 32 14.33 32 32-14.33 32-32 32z"/>
|
||||
<symbol id="icon-bus" xmlns="http://www.w3.org/2000/svg" stroke-width="1.5" viewBox="0 0 24 24" stroke="currentColor" fill="none">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M6 17m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
|
||||
<path d="M18 17m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
|
||||
<path d="M4 17h-2v-11a1 1 0 0 1 1 -1h14a5 7 0 0 1 5 7v5h-2m-4 0h-8" />
|
||||
<path d="M16 5l1.5 7l4.5 0" />
|
||||
<path d="M2 10l15 0" />
|
||||
<path d="M7 5l0 5" />
|
||||
<path d="M12 5l0 5" />
|
||||
</symbol>
|
||||
<symbol id="icon-ski" fill="currentColor" stroke="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
|
||||
|
||||
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{{ form_start(form) }}
|
||||
<div class="flex flex-col space-y-4 pb-8">
|
||||
{{ form_row(form.dateFrom) }}
|
||||
{{ form_row(form.dateTo) }}
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
Speichern
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
@@ -0,0 +1,68 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Einstellungen - Verfügbarkeiten/Zeiträume{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Verfügbarkeiten/Zeiträume
|
||||
</h1>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-1/3">
|
||||
{{ knp_pagination_sortable(pagination, 'Datum von', 'availability.dateFrom') }}
|
||||
</th>
|
||||
<th class="w-1/3">
|
||||
{{ knp_pagination_sortable(pagination, 'Datum bis', 'availability.dateTo') }}
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for availability in pagination %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ availability.dateFrom|date('d.m.Y') }}
|
||||
</td>
|
||||
<td>
|
||||
{{ availability.dateTo|date('d.m.Y') }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center space-x-2 justify-end">
|
||||
<button type="button"
|
||||
class="text-red-500"
|
||||
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'confirmation', null, {
|
||||
'title': 'Bist du sicher?',
|
||||
'content': 'Möchtest du den Zeitraum wirklich löschen?',
|
||||
'target-url': path('app_admin_system_availability_delete', { 'id': availability.id })
|
||||
}) }}>
|
||||
{{ icon('delete') }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<div class="text-sm">Keine Daten...</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ knp_pagination_render(pagination) }}
|
||||
</div>
|
||||
</div>
|
||||
<button type="button"
|
||||
class="btn"
|
||||
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'ajax', null, {
|
||||
'title': 'Zeitraum hinzufügen',
|
||||
'url': path('app_admin_system_availability_create')
|
||||
}) }}>
|
||||
Zeitraum hinzufügen
|
||||
</button>
|
||||
{% endblock %}
|
||||
@@ -1,15 +0,0 @@
|
||||
{{ form_start(form) }}
|
||||
<div class="flex flex-col space-y-4 pb-8">
|
||||
{{ form_row(form.name) }}
|
||||
{{ form_row(form.value) }}
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<button type="submit" class="btn">
|
||||
Speichern
|
||||
</button>
|
||||
<a href="{{ path('app_admin_system_fee_index') }}" class="btn btn--secondary">
|
||||
Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
@@ -1,12 +1,10 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Einstellungen - Honorar anlegen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="max-w-screen-sm">
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Honorar anlegen
|
||||
</h1>
|
||||
{% include 'admin/system/fee/_form.html.twig' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{{ form_start(form) }}
|
||||
<div class="flex flex-col space-y-4 pb-8">
|
||||
{{ form_row(form.name) }}
|
||||
{{ form_row(form.value) }}
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
Speichern
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Einstellungen - Honorar bearbeiten{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="max-w-screen-sm">
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Honorar bearbeiten
|
||||
</h1>
|
||||
{% include 'admin/system/fee/_form.html.twig' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -3,62 +3,65 @@
|
||||
{% block title %}Einstellungen - Honorare{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Honorare
|
||||
</h1>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Honorare
|
||||
</h1>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Bezeichnung
|
||||
</th>
|
||||
<th>
|
||||
Wert
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for fee in fees %}
|
||||
<tr>
|
||||
<th>
|
||||
Bezeichnung
|
||||
</th>
|
||||
<th>
|
||||
Wert
|
||||
</th>
|
||||
<th></th>
|
||||
<td>
|
||||
{{ fee.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ fee.value|format_money }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center space-x-2 justify-end">
|
||||
<button type="button"
|
||||
class="text-red-500"
|
||||
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'confirmation', null, {
|
||||
'title': 'Bist du sicher?',
|
||||
'content': 'Möchtest du das Honorar wirklich löschen?',
|
||||
'target-url': path('app_admin_system_fee_delete', { 'id': fee.id })
|
||||
}) }}>
|
||||
{{ icon('delete') }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for fee in fees %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ fee.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ fee.value|format_money }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center space-x-2 justify-end">
|
||||
<button type="button"
|
||||
class="text-red-500"
|
||||
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'confirmation', null, {
|
||||
'title': 'Bist du sicher?',
|
||||
'content': 'Möchtest du das Honorar wirklich löschen?',
|
||||
'target-url': path('app_admin_system_fee_delete', { 'id': fee.id })
|
||||
}) }}>
|
||||
{{ icon('delete') }}
|
||||
</button>
|
||||
<a href="{{ path('app_admin_system_fee_edit', { 'id': fee.id }) }}">
|
||||
{{ icon('edit') }}
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<div class="text-sm">Keine Daten...</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<div class="text-sm">Keine Daten...</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<a href="{{ path('app_admin_system_fee_create') }}" class="btn">
|
||||
Neu
|
||||
</a>
|
||||
</div>
|
||||
<button type="button"
|
||||
class="btn"
|
||||
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'ajax', null, {
|
||||
'title': 'Honorar hinzufügen',
|
||||
'url': path('app_admin_system_fee_create')
|
||||
}) }}>
|
||||
Honorar hinzufügen
|
||||
</button>
|
||||
{% endblock %}
|
||||
@@ -1,14 +0,0 @@
|
||||
{{ form_start(form) }}
|
||||
<div class="flex flex-col space-y-4 pb-8">
|
||||
{{ form_row(form.name) }}
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<button type="submit" class="btn">
|
||||
Speichern
|
||||
</button>
|
||||
<a href="{{ path('app_admin_system_training_index') }}" class="btn btn--secondary">
|
||||
Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
@@ -1,12 +1,9 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Einstellungen - Fortbildung anlegen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="max-w-screen-sm">
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Fortbildung anlegen
|
||||
</h1>
|
||||
{% include 'admin/system/training/_form.html.twig' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{{ form_start(form) }}
|
||||
<div class="flex flex-col space-y-4 pb-8">
|
||||
{{ form_row(form.name) }}
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
Speichern
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Einstellungen - Fortbildung bearbeiten{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="max-w-screen-sm">
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Fortbildung bearbeiten
|
||||
</h1>
|
||||
{% include 'admin/system/training/_form.html.twig' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -3,62 +3,65 @@
|
||||
{% block title %}Einstellungen - Fortbildungen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Fortbildungen
|
||||
</h1>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Fortbildungen
|
||||
</h1>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Bezeichnung
|
||||
</th>
|
||||
<th>
|
||||
Teilnahmen
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for training in trainings %}
|
||||
<tr>
|
||||
<th>
|
||||
Bezeichnung
|
||||
</th>
|
||||
<th>
|
||||
Teilnahmen
|
||||
</th>
|
||||
<th></th>
|
||||
<td>
|
||||
{{ training.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ training.trainingAttendances|length|default('-') }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center space-x-2 justify-end">
|
||||
<button type="button"
|
||||
class="text-red-500"
|
||||
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'confirmation', null, {
|
||||
'title': 'Bist du sicher?',
|
||||
'content': 'Möchtest du die Fortbildung wirklich löschen?',
|
||||
'target-url': path('app_admin_system_training_delete', { 'id': training.id })
|
||||
}) }}>
|
||||
{{ icon('delete') }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for training in trainings %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ training.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ training.trainingAttendances|length|default('-') }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center space-x-2 justify-end">
|
||||
<button type="button"
|
||||
class="text-red-500"
|
||||
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'confirmation', null, {
|
||||
'title': 'Bist du sicher?',
|
||||
'content': 'Möchtest du die Fortbildung wirklich löschen?',
|
||||
'target-url': path('app_admin_system_training_delete', { 'id': training.id })
|
||||
}) }}>
|
||||
{{ icon('delete') }}
|
||||
</button>
|
||||
<a href="{{ path('app_admin_system_training_edit', { 'id': training.id }) }}">
|
||||
{{ icon('edit') }}
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<div class="text-sm">Keine Daten...</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<div class="text-sm">Keine Daten...</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<a href="{{ path('app_admin_system_training_create') }}" class="btn">
|
||||
Neu
|
||||
</a>
|
||||
</div>
|
||||
<button type="button"
|
||||
class="btn"
|
||||
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'ajax', null, {
|
||||
'title': 'Fortbildung hinzufügen',
|
||||
'url': path('app_admin_system_training_create')
|
||||
}) }}>
|
||||
Fortbildung hinzufügen
|
||||
</button>
|
||||
{% endblock %}
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="bg-gray-100 border border-gray-300 border-t-0 px-4 py-3 flex items-center justify-between sm:px-4">
|
||||
<div class="flex-1 flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-sm leading-5 text-gray-700">{{ 'label.paginator.info'|trans({ '{from}': firstItemNumber, '{to}': lastItemNumber, '{total}': totalCount })|raw }}</p>
|
||||
<p class="text-sm leading-5 text-gray-700">{{ 'paginator.info'|trans({ '{from}': firstItemNumber, '{to}': lastItemNumber, '{total}': totalCount })|raw }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<nav class="relative z-0 inline-flex">
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
{% extends 'teamer/layout.html.twig' %}
|
||||
|
||||
{% block title %}Meine Verfügbarkeit{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-4">
|
||||
Meine Vergfügbarkeit
|
||||
</h1>
|
||||
<p class="pb-8">
|
||||
Hier kannst du angeben, wann du allgemein Zeit und Lust hättest, Einsätze zu absolvieren. Wenn wir in diesem
|
||||
Zeitraum einen Einsatz zu vergeben haben, dann nehmen wir telefonisch oder per E-Mail Kontakt zu dir auf.
|
||||
</p>
|
||||
|
||||
<h2 class="text-xl font-bold pb-2">
|
||||
Ich bin verfügbar
|
||||
</h2>
|
||||
<ul class="list-disc pl-4 pb-8">
|
||||
{% for availability in availabilities %}
|
||||
<li>
|
||||
{{ availability.dateFrom|date('d.m.Y') }} - {{ availability.dateTo|date('d.m.Y') }}
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="text-sm">
|
||||
Du hast bisher keine Verfügbarkeiten hinterlegt.
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h2 class="text-xl font-bold pb-2">
|
||||
Weitere Verfügbarkeiten
|
||||
</h2>
|
||||
{{ form_start(form) }}
|
||||
{{ form_row(form.availabilities) }}
|
||||
<button type="submit" class="btn">
|
||||
Aktualisieren
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{{ form_start(form) }}
|
||||
<div class="flex flex-col space-y-4 pb-8">
|
||||
{{ form_row(form.dateFrom) }}
|
||||
{{ form_row(form.dateTo) }}
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
Speichern
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
@@ -0,0 +1,99 @@
|
||||
{% extends 'teamer/layout.html.twig' %}
|
||||
|
||||
{% block title %}Meine Verfügbarkeit{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-4">
|
||||
Meine Vergfügbarkeit
|
||||
</h1>
|
||||
<p class="pb-8">
|
||||
Hier kannst du angeben, wann du allgemein Zeit und Lust hättest, Einsätze zu absolvieren. Wenn wir in diesem
|
||||
Zeitraum einen Einsatz zu vergeben haben, dann nehmen wir telefonisch oder per E-Mail Kontakt zu dir auf.
|
||||
</p>
|
||||
|
||||
<h2 class="text-xl font-bold pb-2">
|
||||
Ich bin verfügbar
|
||||
</h2>
|
||||
<div class="grid md:grid-cols-2 gap-8 pb-8">
|
||||
{% for year, months in selectedAvailabilities %}
|
||||
<div>
|
||||
<h3 class="text-lg font-bold">
|
||||
{{ year }}
|
||||
</h3>
|
||||
<div class="flex flex-col space-y-3">
|
||||
{% for month, availabilities in months %}
|
||||
<div>
|
||||
<h4 class="font-bold">
|
||||
{{ month }}
|
||||
</h4>
|
||||
{% for availability in availabilities %}
|
||||
<div class="flex items-center space-x-2">
|
||||
<span>{{ availability }}</span>
|
||||
{% if is_granted('DELETE', availability) %}
|
||||
<button type="button"
|
||||
title="Zeitraum entfernen/löschen"
|
||||
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'confirmation', null, {
|
||||
'title': 'Bist du sicher?',
|
||||
'content': 'Möchtest du den Zeitraum wirklich löschen?',
|
||||
'target-url': path('app_teamer_profile_availability_delete', { 'id': availability.id })
|
||||
}) }}>
|
||||
{{ icon('delete', 'w-5 h-5') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="md:col-span-2 text-sm">
|
||||
Du hast bisher keine Verfügbarkeiten hinterlegt.
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<h2 class="text-xl font-bold pb-2">
|
||||
Weitere Verfügbarkeiten
|
||||
</h2>
|
||||
<div class="grid md:grid-cols-2 gap-8 pb-8">
|
||||
{% for year, months in selectableAvailabilities %}
|
||||
<div>
|
||||
<h3 class="text-lg font-bold">
|
||||
{{ year }}
|
||||
</h3>
|
||||
<div class="flex flex-col space-y-3">
|
||||
{% for month, availabilities in months %}
|
||||
<div>
|
||||
<h4 class="font-bold">
|
||||
{{ month }}
|
||||
</h4>
|
||||
{% for availability in availabilities %}
|
||||
<div class="flex items-center space-x-2">
|
||||
<span>{{ availability }}</span>
|
||||
<a href="{{ path('app_teamer_profile_availability_add', { 'id': availability.id }) }}"
|
||||
title="Zeitraum hinzufügen">
|
||||
{{ icon('plus', 'w-5 h-5') }}
|
||||
</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="md:col-span-2 text-sm">
|
||||
Es sind keine weiteren Zeiträume verfügbar.
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<button type="button"
|
||||
class="btn"
|
||||
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'ajax', null, {
|
||||
'title': 'Zeitraum hinzufügen',
|
||||
'url': path('app_teamer_profile_availability_create')
|
||||
}) }}>
|
||||
Eigenen Zeitraum hinzufügen
|
||||
</button>
|
||||
{% endblock %}
|
||||
@@ -3,4 +3,8 @@ uploader:
|
||||
click_here: hier klicken
|
||||
file_too_big: Die maximale Dateigröße beträgt %maxFilesize%MB
|
||||
invalid_file_type: Der Dateityp ist nicht erlaubt
|
||||
max_files_exceeded: Die maximale Anzahl von Dateien is %maxFilesExceeded%
|
||||
max_files_exceeded: Die maximale Anzahl von Dateien is %maxFilesExceeded%
|
||||
paginator:
|
||||
previous: vorherige
|
||||
next: nächste
|
||||
info: 'Einträge <span class="font-medium">{from}</span> bis <span class="font-medium">{to}</span> von {total}'
|
||||
|
||||
Reference in New Issue
Block a user