wip: implement admin crud

This commit is contained in:
Björn Fromme committed 2026-07-16 17:13:15 +02:00
1 parent 13491f346d
commit b075e3ecfc
78 files changed
+2555 -101

No files matched your search

@@ -0,0 +1,121 @@
<?php
declare(strict_types=1);
namespace App\Controller\Admin;
use App\Entity\Groups\Accommodation;
use App\Form\Admin\Groups\AccommodationType;
use App\Htmx\HxRedirectResponse;
use App\Repository\Groups\AccommodationRepository;
use App\Service\CmsDataProvider;
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\Attribute\Route;
class AccommodationController extends AbstractController
{
public function __construct(
private readonly AccommodationRepository $accommodationRepository,
private readonly CmsDataProvider $cmsDataProvider,
private readonly EntityManagerInterface $entityManager,
private readonly LoggerInterface $logger,
) {
}
#[Route('/admin/accommodation', name: 'app_admin_accommodation')]
public function index(): Response
{
$accommodations = $this->accommodationRepository->findAll();
return $this->render('admin/accommodation/index.html.twig', [
'accommodations' => $accommodations,
]);
}
#[Route('/admin/accommodation/create', name: 'app_admin_accommodation_create')]
public function create(Request $request): Response
{
$accommodation = new Accommodation();
$form = $this->createForm(AccommodationType::class, $accommodation);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($accommodation);
$this->entityManager->flush();
$this->addFlash('success', 'Das Gruppenhaus wurde angelegt');
$this->logger->info('Created accommodation', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
]);
return $this->redirectToRoute('app_admin_accommodation');
}
return $this->render('admin/accommodation/create.html.twig', [
'form' => $form,
]);
}
#[Route('/admin/accommodation/{id}/edit', name: 'app_admin_accommodation_edit')]
public function edit(Accommodation $accommodation, Request $request): Response
{
// fetch additional data from cms if available
$cmsData = [];
if (null !== $accommodation->getCode()) {
$cmsData = $this->cmsDataProvider->getHotelDetails($accommodation->getCode());
}
$form = $this->createForm(AccommodationType::class, $accommodation);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->entityManager->persist($accommodation);
$this->entityManager->flush();
$this->addFlash('success', 'Das Gruppenhaus wurde aktualisiert');
$this->logger->info('Updated accommodation', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
]);
return $this->redirectToRoute('app_admin_accommodation_edit', ['id' => $accommodation->getId()]);
}
return $this->render('admin/accommodation/edit.html.twig', [
'accommodation' => $accommodation,
'form' => $form,
'cmsData' => $cmsData,
]);
}
#[Route('/admin/accommodation/{id}/delete', name: 'app_admin_accommodation_delete')]
public function delete(Accommodation $accommodation, Request $request): Response
{
if (true === $request->isMethod(Request::METHOD_POST)) {
$this->entityManager->remove($accommodation);
$this->entityManager->flush();
$this->addFlash('success', 'Das Gruppenhaus wurde gelöscht');
$this->logger->info('Deleted accommodation', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
]);
return new HxRedirectResponse($this->generateUrl('app_admin_accommodation'));
}
return $this->render('admin/accommodation/modal_delete.html.twig', [
'accommodation' => $accommodation,
]);
}
}
@@ -0,0 +1,145 @@
<?php
declare(strict_types=1);
namespace App\Controller\Admin;
use App\Entity\Groups\Accommodation;
use App\Entity\Groups\AccommodationPrice;
use App\Form\Admin\Groups\AccommodationPriceType;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class AccommodationPriceController extends AbstractController
{
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly LoggerInterface $logger,
) {
}
#[Route('/admin/accommodation-price/{id}/create', name: 'app_admin_accommodationprice_create')]
public function create(Accommodation $accommodation, Request $request): Response
{
$accommodationPrice = new AccommodationPrice();
$form = $this->getForm($accommodationPrice, null);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$accommodation->addAccommodationPrice($accommodationPrice);
$this->entityManager->persist($accommodationPrice);
$this->entityManager->flush();
$this->addFlash('success', 'Der Preis wurde angelegt');
$this->logger->info('Created accommodation price', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
'date_range' => [
'from' => $accommodationPrice->getDateFrom()->format('Y-m-d'),
'to' => $accommodationPrice->getDateTo()->format('Y-m-d'),
]
]);
return $this->redirectToRoute('app_admin_accommodation_edit', [
'id' => $accommodation->getId(),
]);
}
return $this->render('admin/accommodation_price/create.html.twig', [
'accommodation' => $accommodation,
'form' => $form,
]);
}
#[Route('/admin/accommodation-price/{id}/edit', name: 'app_admin_accommodationprice_edit', defaults: ['duplicate' => false])]
#[Route('/admin/accommodation-price/{id}/duplicate', name: 'app_admin_accommodationprice_duplicate', defaults: ['duplicate' => true])]
public function edit(AccommodationPrice $accommodationPrice, bool $duplicate, Request $request): Response
{
$accommodation = $accommodationPrice->getAccommodation();
if (true === $duplicate) {
$accommodationPrice = clone $accommodationPrice;
}
$form = $this->getForm($accommodationPrice, $accommodation);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if (true === $duplicate) {
$accommodation->addAccommodationPrice($accommodationPrice);
}
$this->entityManager->persist($accommodationPrice);
$this->entityManager->flush();
$this->addFlash('success', 'Der Preis wurde aktualisiert');
$this->logger->info('Edited accommodation price', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
'date_range' => [
'from' => $accommodationPrice->getDateFrom()->format('Y-m-d'),
'to' => $accommodationPrice->getDateTo()->format('Y-m-d'),
]
]);
return $this->redirectToRoute('app_admin_accommodation_edit', [
'id' => $accommodation->getId(),
]);
}
return $this->render('admin/accommodation_price/edit.html.twig', [
'accommodation' => $accommodation,
'accommodationPrice' => $accommodationPrice,
'form' => $form,
'duplicate' => $duplicate,
]);
}
#[Route('/admin/accommodation-price/{id}/delete', name: 'app_admin_accommodationprice_delete')]
public function delete(AccommodationPrice $accommodationPrice, Request $request): Response
{
$accommodation = $accommodationPrice->getAccommodation();
if (true === $request->isMethod(Request::METHOD_POST)) {
$this->entityManager->remove($accommodationPrice);
$this->entityManager->flush();
$this->addFlash('success', 'Der Preis wurde gelöscht');
$this->logger->info('Deleted accommodation price', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
'date_range' => [
'from' => $accommodationPrice->getDateFrom()->format('Y-m-d'),
'to' => $accommodationPrice->getDateTo()->format('Y-m-d'),
]
]);
$returnUrl = $this->generateUrl('app_admin_accommodation_edit', [
'id' => $accommodation->getId(),
]);
return new HxRedirectResponse($returnUrl);
}
return $this->render('admin/accommodation_price/modal_delete.html.twig', [
'accommodationPrice' => $accommodationPrice,
'accommodation' => $accommodation,
]);
}
private function getForm(AccommodationPrice $accommodationPrice, ?Accommodation $accommodation): FormInterface
{
return $this->createForm(AccommodationPriceType::class, $accommodationPrice, ['currency' => $accommodation->getCurrency()]);
}
}
@@ -0,0 +1,148 @@
<?php
declare(strict_types=1);
namespace App\Controller\Admin;
use App\Entity\Groups\Accommodation;
use App\Entity\Groups\AdditionalService;
use App\Form\Admin\Groups\AdditionalServiceType;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class AdditionalServiceController extends AbstractController
{
use SortingControllerTrait;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly LoggerInterface $logger,
) {
}
#[Route('/admin/additional-service/{id}/create', name: 'app_admin_additionalservice_create')]
public function create(Accommodation $accommodation, Request $request): Response
{
$additionalService = new AdditionalService();
$form = $this->getForm($additionalService, $accommodation);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$accommodation->addAdditionalService($additionalService);
$this->entityManager->persist($additionalService);
$this->entityManager->flush();
$this->addFlash('success', 'Die Zusatzleistung wurde angelegt');
$this->logger->info('Created additional service', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
'label' => $additionalService->getLabel(),
]);
return $this->redirectToRoute('app_admin_accommodation_edit', [
'id' => $accommodation->getId(),
]);
}
return $this->render('admin/additional_service/create.html.twig', [
'accommodation' => $accommodation,
'form' => $form,
]);
}
#[Route('/admin/additional-service/{id}/edit', name: 'app_admin_additionalservice_edit', defaults: ['duplicate' => false])]
#[Route('/admin/additional-service/{id}/duplicate', name: 'app_admin_additionalservice_duplicate', defaults: ['duplicate' => true])]
public function edit(AdditionalService $additionalService, bool $duplicate, Request $request): Response
{
$accommodation = $additionalService->getAccommodation();
if (true === $duplicate) {
$additionalService = clone $additionalService;
}
$form = $this->getForm($additionalService, $accommodation);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if (true === $duplicate) {
$accommodation->addAdditionalService($additionalService);
}
$this->entityManager->persist($additionalService);
$this->entityManager->flush();
$this->addFlash('success', 'Die Zusatzleistung wurde aktualisiert');
$this->logger->info('Edited additional service', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
'label' => $additionalService->getLabel(),
]);
return $this->redirectToRoute('app_admin_accommodation_edit', [
'id' => $accommodation->getId(),
]);
}
return $this->render('admin/additional_service/edit.html.twig', [
'accommodation' => $accommodation,
'additionalService' => $additionalService,
'form' => $form,
'duplicate' => $duplicate,
]);
}
#[Route('/admin/additional-service/{id}/delete', name: 'app_admin_additionalservice_delete')]
public function delete(AdditionalService $additionalService, Request $request): Response
{
$accommodation = $additionalService->getAccommodation();
if (true === $request->isMethod(Request::METHOD_POST)) {
$this->entityManager->remove($additionalService);
$this->entityManager->flush();
$this->addFlash('success', 'Die Zusatzleistung wurde gelöscht');
$this->logger->info('Deleted additional service', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
'label' => $additionalService->getLabel(),
]);
$returnUrl = $this->generateUrl('app_admin_accommodation_edit', [
'id' => $accommodation->getId(),
]);
return new HxRedirectResponse($returnUrl);
}
return $this->render('admin/additional_service/modal_delete.html.twig', [
'additionalService' => $additionalService,
'accommodation' => $accommodation,
]);
}
#[Route('/admin/additional-service/sort/{id}', name: 'app_admin_additionalservice_sort', methods: ['POST'])]
public function sort(Accommodation $accommodation, Request $request): Response
{
$this->applySorting($accommodation->getAdditionalServices(), $request->request->all('sorting'));
$this->entityManager->flush();
return new Response('', Response::HTTP_NO_CONTENT);
}
private function getForm(AdditionalService $additionalService, ?Accommodation $accommodation): FormInterface
{
return $this->createForm(AdditionalServiceType::class, $additionalService, ['currency' => $accommodation->getCurrency()]);
}
}
@@ -0,0 +1,147 @@
<?php
declare(strict_types=1);
namespace App\Controller\Admin;
use App\Entity\Groups\Accommodation;
use App\Entity\Groups\BoardService;
use App\Form\Admin\Groups\BoardServiceType;
use App\Htmx\HxRedirectResponse;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class BoardServiceController extends AbstractController
{
use SortingControllerTrait;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly LoggerInterface $logger,
) {
}
#[Route('/admin/board-service/{id}/create', name: 'app_admin_boardservice_create')]
public function create(Accommodation $accommodation, Request $request): Response
{
$boardService = new BoardService();
$form = $this->getForm($boardService, $accommodation);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$accommodation->addBoardService($boardService);
$this->entityManager->persist($boardService);
$this->entityManager->flush();
$this->addFlash('success', 'Die Verpflegungsleistung wurde angelegt');
$this->logger->info('Created board service', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
'label' => $boardService->getLabel(),
]);
return $this->redirectToRoute('app_admin_accommodation_edit', [
'id' => $accommodation->getId(),
]);
}
return $this->render('admin/board_service/create.html.twig', [
'accommodation' => $accommodation,
'form' => $form,
]);
}
#[Route('/admin/board-service/{id}/edit', name: 'app_admin_boardservice_edit', defaults: ['duplicate' => false])]
#[Route('/admin/board-service/{id}/duplicate', name: 'app_admin_boardservice_duplicate', defaults: ['duplicate' => true])]
public function edit(BoardService $boardService, bool $duplicate, Request $request): Response
{
$accommodation = $boardService->getAccommodation();
if (true === $duplicate) {
$boardService = clone $boardService;
}
$form = $this->getForm($boardService, $accommodation);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if (true === $duplicate) {
$accommodation->addBoardService($boardService);
}
$this->entityManager->persist($boardService);
$this->entityManager->flush();
$this->addFlash('success', 'Die Verpflegungsleistung wurde aktualisiert');
$this->logger->info('Edited board service', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
'label' => $boardService->getLabel(),
]);
return $this->redirectToRoute('app_admin_accommodation_edit', [
'id' => $accommodation->getId(),
]);
}
return $this->render('admin/board_service/edit.html.twig', [
'accommodation' => $accommodation,
'boardService' => $boardService,
'form' => $form,
'duplicate' => $duplicate,
]);
}
#[Route('/admin/board-service/{id}/delete', name: 'app_admin_boardservice_delete')]
public function delete(BoardService $boardService, Request $request): Response
{
$accommodation = $boardService->getAccommodation();
if (true === $request->isMethod(Request::METHOD_POST)) {
$this->entityManager->remove($boardService);
$this->entityManager->flush();
$this->addFlash('success', 'Die Verpflegungsleistung wurde gelöscht');
$this->logger->info('Deleted board service', [
'name' => $accommodation->getName(),
'code' => $accommodation->getCode(),
'label' => $boardService->getLabel(),
]);
$returnUrl = $this->generateUrl('app_admin_accommodation_edit', [
'id' => $accommodation->getId(),
]);
return new HxRedirectResponse($returnUrl);
}
return $this->render('admin/board_service/modal_delete.html.twig', [
'boardService' => $boardService,
'accommodation' => $accommodation,
]);
}
#[Route('/admin/board-service/sort/{id}', name: 'app_admin_boardservice_sort', methods: ['POST'])]
public function sort(Accommodation $accommodation, Request $request): Response
{
$this->applySorting($accommodation->getBoardServices(), $request->request->all('sorting'));
$this->entityManager->flush();
return new Response('', Response::HTTP_NO_CONTENT);
}
private function getForm(BoardService $boardService, ?Accommodation $accommodation): FormInterface
{
return $this->createForm(BoardServiceType::class, $boardService, ['currency' => $accommodation->getCurrency()]);
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Controller\Admin;
use App\Entity\Groups\SortableEntityInterface;
trait SortingControllerTrait
{
private function applySorting(iterable $collection, array $sortingMap): void
{
foreach ($collection as $entity) {
/** @var SortableEntityInterface $entity */
if (isset($sortingMap[$entity->getId()])) {
$entity->setSorting((int) $sortingMap[$entity->getId()]);
}
}
}
}