diff --git a/src/Controller/FoodOrderController.php b/src/Controller/FoodOrderController.php index e0d94ac..f74661d 100644 --- a/src/Controller/FoodOrderController.php +++ b/src/Controller/FoodOrderController.php @@ -3,9 +3,12 @@ namespace App\Controller; use App\Entity\FoodOrder; +use App\Entity\ItemExtra; use App\Entity\MenuItem; +use App\Entity\MenuItemAlias; use App\Entity\OrderItem; -use App\Form\MenuItemExtraType; +use App\Form\ItemExtraType; +use App\Form\MenuItemType; use App\Form\OrderItemType; use App\Repository\ItemExtraRepository; use Doctrine\ORM\EntityManagerInterface; @@ -23,15 +26,50 @@ class FoodOrderController extends AbstractController final public const APP_FOODORDER_CLOSE = 'app_foodorder_close'; - #[Route('/{id}', name: self::APP_FOOD_ORDER_SHOW, methods: ['GET'])] - public function show(FoodOrder $foodOrder): Response - { + final public const APP_FOODORDER_COPY_ITEM = 'app_foodorder_item_copy'; + + final public const APP_FOODORDER_REMOVE_ITEM = 'app_foodorder_item_remove'; + + #[Route( + '/{id}', + name: self::APP_FOOD_ORDER_SHOW, + methods: [Request::METHOD_GET, Request::METHOD_POST], + )] + public function show( + FoodOrder $foodOrder, + Request $request, + EntityManagerInterface $entityManager, + ): Response { + $newItem = new MenuItem; + $newItem->setVendor($foodOrder->getVendor()); + $newItem->setPrice(0); + $newItemForm = $this->createForm(MenuItemType::class, $newItem); + $newItemForm->handleRequest($request); + + if ($newItemForm->isSubmitted() && $newItemForm->isValid()) { + $name = (string) $newItemForm->get('name') + ->getData(); + $alias = new MenuItemAlias; + $alias->setName($name); + $alias->setMenuItem($newItem); + $entityManager->persist($newItem); + $entityManager->persist($alias); + $entityManager->flush(); + return $this->redirectToRoute( + self::APP_FOOD_ORDER_SHOW, + [ + 'id' => $foodOrder->getId(), + ], + ); + } + return $this->render( 'food_order/show.html.twig', [ 'food_order' => $foodOrder, 'menu_items' => $foodOrder->getVendor() ->getMenuItems(), + 'form' => $newItemForm, ], ); } @@ -89,38 +127,88 @@ class FoodOrderController extends AbstractController ); } - $formExtra = $this->createForm( - MenuItemExtraType::class, - + $newExtra = new ItemExtra; + $newExtra->setMenuItem($menuItem); + $extraForm = $this->createForm( + ItemExtraType::class, + $newExtra, + [ + 'menuItem' => $menuItem, + ], ); + $extraForm->handleRequest($request); + + if ($extraForm->isSubmitted() && $extraForm->isValid()) { + $entityManager->persist($newExtra); + $entityManager->flush(); + return $this->redirectToRoute( + self::APP_FOODORDER_ADD_ITEM, + [ + 'foodOrder' => $foodOrder->getId(), + 'menuItem' => $menuItem->getId(), + ], + Response::HTTP_SEE_OTHER, + ); + } return $this->render( 'food_order/orderitem.html.twig', [ 'form' => $form, + 'extraForm' => $extraForm, 'extras' => $extraRepository->getUniqueNames(), ], ); } #[Route( - '/{foodOrder}/remove_item/{orderItem}', - name: 'app_foodorder_remove_item', + '/item/remove/{orderItem}', + name: self::APP_FOODORDER_REMOVE_ITEM, methods: [Request::METHOD_GET], )] public function remove( - FoodOrder $foodOrder, OrderItem $orderItem, EntityManagerInterface $entityManager, ): Response { + $orderId = $orderItem->getFoodOrder() + ->getId(); $entityManager->remove($orderItem); $entityManager->flush(); return $this->redirectToRoute( self::APP_FOOD_ORDER_SHOW, [ - 'id' => $foodOrder->getId(), + 'id' => $orderId, ], Response::HTTP_SEE_OTHER, ); } + + #[Route( + '/item/copy/{orderItem}', + name: self::APP_FOODORDER_COPY_ITEM, + methods: [Request::METHOD_GET], + )] + public function copyItem( + OrderItem $orderItem, + EntityManagerInterface $entityManager, + ): Response { + $newItem = new OrderItem; + $newItem->setFoodOrder($orderItem->getFoodOrder()); + $newItem->setMenuItem($orderItem->getMenuItem()); + + foreach ($orderItem->getExtras() as $extra) { + $newItem->getExtras() + ->add($extra); + } + + $entityManager->persist($newItem); + $entityManager->flush(); + return $this->redirectToRoute( + self::APP_FOOD_ORDER_SHOW, + [ + 'id' => $orderItem->getFoodOrder() + ->getId(), + ], + ); + } } diff --git a/src/Entity/FoodOrder.php b/src/Entity/FoodOrder.php index 670c416..5afbc96 100644 --- a/src/Entity/FoodOrder.php +++ b/src/Entity/FoodOrder.php @@ -11,6 +11,8 @@ use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator; use Symfony\Bridge\Doctrine\Types\UlidType; use Symfony\Component\Uid\Ulid; +use function iterator_to_array; + #[ORM\Entity(repositoryClass: FoodOrderRepository::class)] class FoodOrder { @@ -130,6 +132,12 @@ class FoodOrder public function groupedOrderItems(): Collection { - return $this->getOrderItems(); + $iterator = $this->orderItems->getIterator(); + $orderFunction = static fn(OrderItem $a, OrderItem $b): int + => $a->getMenuItem() + ->getId() + ->compare($b->getMenuItem()->getId()); + $iterator->uasort($orderFunction); + return new ArrayCollection(iterator_to_array($iterator)); } } diff --git a/src/Entity/ItemExtra.php b/src/Entity/ItemExtra.php index 2c770fd..60ae4ee 100644 --- a/src/Entity/ItemExtra.php +++ b/src/Entity/ItemExtra.php @@ -11,23 +11,18 @@ use Symfony\Component\Uid\Ulid; #[ORM\Entity(repositoryClass: ItemExtraRepository::class)] class ItemExtra { - #[ORM\Id] - #[ORM\GeneratedValue(strategy: 'CUSTOM')] - #[ORM\Column(type: UlidType::NAME, unique: true)] - #[ORM\CustomIdGenerator(class: UlidGenerator::class)] - private Ulid $id; - - #[ORM\Column(length: 50)] - private string|null $name = null; - - #[ORM\ManyToOne(inversedBy: 'itemExtras')] - #[ORM\JoinColumn(nullable: false)] - private MenuItem|null $menuItem = null; - - public function __construct() - { - $this->id = new Ulid; - } + public function __construct( + #[ORM\Column(length: 50)] + private string|null $name = null, + #[ORM\ManyToOne(inversedBy: 'itemExtras')] + #[ORM\JoinColumn(nullable: false)] + private MenuItem|null $menuItem = null, + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'CUSTOM')] + #[ORM\Column(type: UlidType::NAME, unique: true)] + #[ORM\CustomIdGenerator(class: UlidGenerator::class)] + private Ulid $id = new Ulid, + ) {} public function getId(): Ulid { diff --git a/src/Form/ItemExtraType.php b/src/Form/ItemExtraType.php new file mode 100644 index 0000000..b71bce6 --- /dev/null +++ b/src/Form/ItemExtraType.php @@ -0,0 +1,31 @@ +add(child: 'name', options: [ + 'label' => 'custom extra', + ]); + } + + #[Override] + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => ItemExtra::class, + ]); + $resolver->setRequired('menuItem'); + $resolver->setAllowedTypes('menuItem', MenuItem::class); + } +} diff --git a/src/Form/MenuItemExtraType.php b/src/Form/MenuItemExtraType.php index 28ae522..f90e299 100644 --- a/src/Form/MenuItemExtraType.php +++ b/src/Form/MenuItemExtraType.php @@ -1,5 +1,4 @@ -setDefaults([ diff --git a/src/Form/MenuItemType.php b/src/Form/MenuItemType.php new file mode 100644 index 0000000..93be546 --- /dev/null +++ b/src/Form/MenuItemType.php @@ -0,0 +1,43 @@ +add(child: 'name', type: TextType::class, options: [ + 'mapped' => false, + ]) + ->add( + child: 'price', + options: [ + 'label' => 'Price in cents', + 'constraints' => [ + new GreaterThanOrEqual([ + 'value' => 0, + 'message' => 'The price must be a positive number or zero.', + ]), + ], + ], + ); + } + + #[Override] + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => MenuItem::class, + ]); + } +} diff --git a/symfony.lock b/symfony.lock index 7d8f3b0..84532e6 100644 --- a/symfony.lock +++ b/symfony.lock @@ -5,7 +5,7 @@ "repo": "github.com/symfony/recipes", "branch": "main", "version": "2.10", - "ref": "310a02a22033e35640468f48ff6bf31a25891537" + "ref": "c170ded8fc587d6bd670550c43dafcf093762245" }, "files": [ "config/packages/doctrine.yaml", diff --git a/templates/food_order/orderitem.html.twig b/templates/food_order/orderitem.html.twig index 8c26a22..6bf2e30 100644 --- a/templates/food_order/orderitem.html.twig +++ b/templates/food_order/orderitem.html.twig @@ -1,7 +1,8 @@ {% extends 'base.html.twig' %} {% block body %} - {{ include('_form.html.twig') }} + {% include('_form.html.twig') %} + {% include('_form.html.twig') with {'form': extraForm, 'button_label': 'add extra'} only %} {% for item in extras %} diff --git a/templates/food_order/show.html.twig b/templates/food_order/show.html.twig index 371ee01..29f4cb5 100644 --- a/templates/food_order/show.html.twig +++ b/templates/food_order/show.html.twig @@ -53,6 +53,22 @@ {{ orderItem.menuItem.price|cents_to_eur }} + +1 | + del | {% endfor %} @@ -90,4 +106,6 @@ {% endfor %} + + {% include('_form.html.twig') %} {% endblock %}