diff --git a/assets/controllers/form_partial_controller.js b/assets/controllers/form_partial_controller.js new file mode 100644 index 0000000..77170ce --- /dev/null +++ b/assets/controllers/form_partial_controller.js @@ -0,0 +1,35 @@ +import { Controller } from '@hotwired/stimulus' +import { useFetch } from '../mixins/use_fetch' + +export default class extends Controller { + + static targets = [ 'form', 'container', 'spinner' ] + static values = { url: String, loading: Boolean } + + connect() { + useFetch(this) + } + + update() { + this.loadingValue = true + const formData = new FormData(this.formTarget) + fetch(this.urlValue, { method: 'POST', body: formData }) + .then(this.checkStatus) + .then(this.parseHTML) + .then(response => { + this.containerTarget.innerHTML = response + }) + .catch(error => { + }) + .finally(() => { + this.loadingValue = false + }) + + } + + loadingValueChanged(loading) { + if (this.hasSpinnerTarget) { + this.spinnerTarget.classList.toggle('hidden', false === loading) + } + } +} \ No newline at end of file diff --git a/src/BusProNet/Model/Pickup.php b/src/BusProNet/Model/Pickup.php index cd88b05..8e84b89 100644 --- a/src/BusProNet/Model/Pickup.php +++ b/src/BusProNet/Model/Pickup.php @@ -7,8 +7,23 @@ class Pickup private ?int $id = null; private ?int $busProId = null; private ?string $code = null; - private ?string $city; - private ?string $street; + private ?string $city = null; + private ?string $street = null; + private ?string $time = null; + + public static function fromArray(array $data): static + { + $instance = new static(); + $instance + ->setId($data['busProId']) + ->setCode($data['code'] ?? null) + ->setCity($data['city']) + ->setStreet($data['street']) + ->setTime($data['time']) + ; + + return $instance; + } public function getId(): ?int { @@ -69,4 +84,16 @@ class Pickup return $this; } + + public function getTime(): ?string + { + return $this->time; + } + + public function setTime(?string $time): static + { + $this->time = $time; + + return $this; + } } \ No newline at end of file diff --git a/src/Controller/Admin/Assignment/PickupFormController.php b/src/Controller/Admin/Assignment/PickupFormController.php new file mode 100644 index 0000000..f34af0a --- /dev/null +++ b/src/Controller/Admin/Assignment/PickupFormController.php @@ -0,0 +1,28 @@ +createForm(AssignmentType::class, $assignment); + $form->handleRequest($request); + + return $this->render('admin/assignment/_form_pickup.html.twig', [ + 'form' => $form->createView(), + ]); + } +} \ No newline at end of file diff --git a/src/Entity/Destination.php b/src/Entity/Destination.php index 1ad08e5..3666145 100644 --- a/src/Entity/Destination.php +++ b/src/Entity/Destination.php @@ -2,6 +2,7 @@ namespace App\Entity; +use App\BusProNet\Model\Pickup; use App\Entity\Traits\SoftDeletableEntity; use App\Entity\Traits\TimestampableEntity; use App\Repository\DestinationRepository; @@ -171,6 +172,17 @@ class Destination implements TimestampableEntityInterface, SoftDeletableEntityIn return $this; } + public function getPickup(int $id): ?Pickup + { + foreach ($this->getPickups() as $pickup) { + if ($id === $pickup['busProId']) { + return Pickup::fromArray($pickup); + } + } + + return null; + } + public function hasBusTransfer(): bool { return 0 < count($this->getPickups()); diff --git a/src/Entity/Disposition.php b/src/Entity/Disposition.php index 040ffcd..5f9af72 100644 --- a/src/Entity/Disposition.php +++ b/src/Entity/Disposition.php @@ -43,7 +43,7 @@ class Disposition implements BlameableEntityInterface, TimestampableEntityInterf private ?Teamer $teamer; #[ORM\Column(nullable: true)] - private ?int $pickup = null; + private ?int $pickup; #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $remarks; diff --git a/src/Form/AssignmentType.php b/src/Form/AssignmentType.php index 557d5b9..8f1b84b 100644 --- a/src/Form/AssignmentType.php +++ b/src/Form/AssignmentType.php @@ -8,18 +8,27 @@ use App\Entity\Fee; use App\Entity\JobProfile; use App\Entity\Upload; use App\Entity\User; +use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\IntegerType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormEvents; +use Symfony\Component\Form\FormInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class AssignmentType extends AbstractType { + public function __construct(private readonly EntityManagerInterface $entityManager) + { + } + public function buildForm(FormBuilderInterface $builder, array $options): void { $builder @@ -37,6 +46,7 @@ class AssignmentType extends AbstractType 'label_property' => 'product', 'label_function' => fn(Destination $destination) => (string) $destination, 'endpoint_route' => 'app_admin_autocomplete_destination', + 'controller_action' => 'select->form-partial#update', ]) ->add('jobProfile', EntityType::class, [ 'label' => 'Jobprofil', @@ -60,11 +70,6 @@ class AssignmentType extends AbstractType 'label' => 'abweichender Zustieg bei Busbegleitung', 'required' => false, ]) - ->add('pickup', BpnPickupType::class, [ - 'label' => 'Busbegleitung ab', - 'required' => false, - 'placeholder' => 'Keine Busbegleitung', - ]) ->add('benefits', TextareaType::class, [ 'label' => 'Benefits', 'required' => false, @@ -133,9 +138,62 @@ class AssignmentType extends AbstractType 'rows' => 3, ], ]) + ->add('pickup', ChoiceType::class, [ + 'label' => 'Busbegleitung ab', + 'required' => false, + 'placeholder' => 'Keine Busbegleitung', + ]) + ->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { + $form = $event->getForm(); + $data = $event->getData(); + $destination = $data->getDestination(); + + if (null === $destination) { + return; + } + + $this->addPickupField($destination, $form); + }) + ->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { + $form = $event->getForm(); + $data = $event->getData(); + $destinationId = $data['destination'] ?? null; + + if (null === $destinationId) { + return; + } + + $destination = $this + ->entityManager + ->getRepository(Destination::class) + ->find($destinationId) + ; + + $this->addPickupField($destination, $form); + }) ; } + private function addPickupField(Destination $destination, FormInterface $form): void + { + $choices = []; + + foreach ($destination->getPickups() as $pickup) { + $label = sprintf('%s, %s Uhr', trim($pickup['city']), trim($pickup['time'])); + $choices[$label] = $pickup['busProId']; + } + + // Remove placeholder field first + $form->remove('pickup'); + + $form->add('pickup', ChoiceType::class, [ + 'label' => 'Busbegleitung ab', + 'required' => false, + 'placeholder' => 'Keine Busbegleitung', + 'choices' => $choices, + ]); + } + public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ diff --git a/src/Twig/AppRuntime.php b/src/Twig/AppRuntime.php index eb44806..80cb8e5 100644 --- a/src/Twig/AppRuntime.php +++ b/src/Twig/AppRuntime.php @@ -50,7 +50,7 @@ class AppRuntime implements RuntimeExtensionInterface return 'nationality' === $property ? $country->getNationality() : $country->getName(); } - public function bpnPickupLabel(?int $id): string + public function bpnPickupLabel(?int $id): ?string { if (null === $id) { return 'keine Busbegleitung'; @@ -59,7 +59,7 @@ class AppRuntime implements RuntimeExtensionInterface $pickup = $this->pickups->get($id); if (null === $pickup) { - return 'unbekannt'; + return null; } return 'ab '.$pickup->getCity(); diff --git a/templates/_partials/_assignment_info.html.twig b/templates/_partials/_assignment_info.html.twig index dd1ff89..26f3215 100644 --- a/templates/_partials/_assignment_info.html.twig +++ b/templates/_partials/_assignment_info.html.twig @@ -24,29 +24,28 @@ {% if assignment.pickup %} + {% set pickup = assignment.destination.pickup(assignment.pickup) %}
Busbegleitung
- {{ assignment.pickup|bpn_pickup_label }} + ab {{ pickup.city }}, {{ pickup.street }}
- {% if assignment.pickupDate %} -
-
- Busabfahrt -
-
- {{ assignment.pickupDate|date('d.m.Y') }} -
-
- {% endif %} - {% endif %} - {% if application is defined and application.pickup is not null %}
- Gwählter Zustieg + Busabfahrt +
+
+ {{ pickup.time }} Uhr +
+
+ {% endif %} + {% if application is defined and application is not null and application.pickup is not null %} +
+
+ Gewählter Zustieg
{{ application.pickup|bpn_pickup_label }} diff --git a/templates/_partials/_assignment_info_compact.html.twig b/templates/_partials/_assignment_info_compact.html.twig index 4cb6cf8..fa330eb 100644 --- a/templates/_partials/_assignment_info_compact.html.twig +++ b/templates/_partials/_assignment_info_compact.html.twig @@ -27,24 +27,23 @@
{% if assignment.pickup %} + {% set pickup = assignment.destination.pickup(assignment.pickup) %}
Busbegleitung
- {{ assignment.pickup|bpn_pickup_label }} + {{ pickup.city }} +
+
+
+
+ Busabfahrt +
+
+ {{ pickup.time }} Uhr
- {% if assignment.pickupDate %} -
-
- Busabfahrt -
-
- {{ assignment.pickupDate|date('d.m.Y') }} -
-
- {% endif %} {% endif %}
diff --git a/templates/_partials/_assignment_requirements_info.html.twig b/templates/_partials/_assignment_requirements_info.html.twig index 4b6faad..634b267 100644 --- a/templates/_partials/_assignment_requirements_info.html.twig +++ b/templates/_partials/_assignment_requirements_info.html.twig @@ -2,7 +2,7 @@ {% if assignment.pickup %}
  • - Busbegleitung {{ assignment.pickup|bpn_pickup_label }} am {{ assignment.effectivePickupDate|date('d.m.Y') }} + Busbegleitung ab {{ assignment.destination.pickup(assignment.pickup).city }} {% if teamer.hasPickup(assignment.pickup) %} {{ icon('check', 'w-5 h-5 text-green-500 shrink-0') }} {% else %} diff --git a/templates/admin/application/index.html.twig b/templates/admin/application/index.html.twig index 628b531..0fab2c7 100644 --- a/templates/admin/application/index.html.twig +++ b/templates/admin/application/index.html.twig @@ -56,11 +56,16 @@ - - {{ assignment.pickup ? assignment.pickup|bpn_pickup_label : '-' }} -
    - {{ assignment.effectivePickupDate ? assignment.effectivePickupDate|date('d.m.Y') : '' }} -
    + {% if assignment.pickup %} + {% set pickup = assignment.destination.pickup(assignment.pickup) %} + + ab {{ pickup.city }} +
    + {{ pickup.time }} Uhr +
    + {% else %} + - + {% endif %} diff --git a/templates/admin/assignment/_form.html.twig b/templates/admin/assignment/_form.html.twig index f00c274..19ad412 100644 --- a/templates/admin/assignment/_form.html.twig +++ b/templates/admin/assignment/_form.html.twig @@ -10,63 +10,69 @@
    {% endmacro %} -{{ form_start(form) }} -
    -
    -
    - {{ form_row(form.destination) }} -
    - {{ form_row(form.availableDispositions) }} -
    -

    - {{ form_label(form.showAvailableDispositions) }} -

    - {{ form_widget(form.showAvailableDispositions) }} -
    -
    -
    - {{ form_row(form.dateFrom) }} - {{ form_row(form.dateTo) }} -
    -
    - {{ form_row(form.jobProfile) }} - {{ form_row(form.contact) }} -
    -
    - {{ form_row(form.pickup) }} - {{ form_row(form.pickupDate) }} -
    -
    - {{ form_row(form.benefits) }} - {{ form_row(form.fees) }} -
    -
    - {{ form_row(form.remarks) }} -
    -

    - Dokumente -

    -
    - {% do form.documents.setRendered %} - {%- for document in form.documents -%}{{- _self.collectionRow(document) -}}{%- endfor -%} +
    + {{ form_start(form, { 'attr': { 'data-form-partial-target': 'form' } }) }} +
    +
    +
    + {{ form_row(form.destination) }}
    -
    - + {{ form_row(form.availableDispositions) }} +
    +

    + {{ form_label(form.showAvailableDispositions) }} +

    + {{ form_widget(form.showAvailableDispositions) }} +
    +
    +
    + {{ form_row(form.dateFrom) }} + {{ form_row(form.dateTo) }} +
    +
    + {{ form_row(form.jobProfile) }} + {{ form_row(form.contact) }} +
    +
    +
    + {% include 'admin/assignment/_form_pickup.html.twig' %} +
    +
    + {% include '_partials/_spinner.html.twig' with { 'class': 'w-8 h-8'} %} +
    +
    +
    + {{ form_row(form.benefits) }} + {{ form_row(form.fees) }} +
    +
    + {{ form_row(form.remarks) }} +
    +

    + Dokumente +

    +
    + {% do form.documents.setRendered %} + {%- for document in form.documents -%}{{- _self.collectionRow(document) -}}{%- endfor -%} +
    +
    + +
    -
    -
    -{{ form_rest(form) }} -{{ form_end(form) }} +
    + + + Abbrechen + +
    + {{ form_rest(form) }} + {{ form_end(form) }} +
    \ No newline at end of file diff --git a/templates/admin/assignment/_form_pickup.html.twig b/templates/admin/assignment/_form_pickup.html.twig new file mode 100644 index 0000000..a0767c9 --- /dev/null +++ b/templates/admin/assignment/_form_pickup.html.twig @@ -0,0 +1,2 @@ +{{ form_row(form.pickup) }} +{{ form_row(form.pickupDate) }} diff --git a/templates/admin/assignment/index.html.twig b/templates/admin/assignment/index.html.twig index 984d889..cb26ffd 100644 --- a/templates/admin/assignment/index.html.twig +++ b/templates/admin/assignment/index.html.twig @@ -82,11 +82,16 @@ - - {{ assignment.pickup ? assignment.pickup|bpn_pickup_label : '-' }} -
    - {{ assignment.effectivePickupDate ? assignment.effectivePickupDate|date('d.m.Y') : '' }} -
    + {% if assignment.pickup %} + {% set pickup = assignment.destination.pickup(assignment.pickup) %} + + ab {{ pickup.city }} +
    + {{ pickup.time }} Uhr +
    + {% else %} + - + {% endif %} diff --git a/templates/teamer/application/index.html.twig b/templates/teamer/application/index.html.twig index f5da450..0ad5865 100644 --- a/templates/teamer/application/index.html.twig +++ b/templates/teamer/application/index.html.twig @@ -28,9 +28,10 @@ {{ assignment.destination.hotel }}
    {% if assignment.pickup %} + {% set pickup = assignment.destination.pickup(assignment.pickup) %}
    {{ icon('bus', 'w-5 h-5 shrink-0') }} - {{ assignment.pickup|bpn_pickup_label|default('-') }} {{ assignment.effectivePickupDate ? assignment.effectivePickupDate|date('d.m.Y') : '' }} + {{ pickup.city }}, {{ pickup.time }} Uhr
    {% endif %}
    diff --git a/templates/teamer/assignment/index.html.twig b/templates/teamer/assignment/index.html.twig index 85c9c28..d745ae6 100644 --- a/templates/teamer/assignment/index.html.twig +++ b/templates/teamer/assignment/index.html.twig @@ -54,9 +54,10 @@ {{ assignment.destination.hotel }}
    {% if assignment.pickup %} + {% set pickup = assignment.destination.pickup(assignment.pickup) %}
    {{ icon('bus', 'w-5 h-5 shrink-0') }} - {{ assignment.pickup|bpn_pickup_label|default('-') }} {{ assignment.effectivePickupDate ? assignment.effectivePickupDate|date('d.m.Y') : '' }} + {{ pickup.city }}, {{ pickup.time }} Uhr
    {% endif %}
    diff --git a/templates/teamer/bookmark/index.html.twig b/templates/teamer/bookmark/index.html.twig index f59d191..d2851c2 100644 --- a/templates/teamer/bookmark/index.html.twig +++ b/templates/teamer/bookmark/index.html.twig @@ -27,9 +27,10 @@ {{ assignment.destination.hotel }}
  • {% if assignment.pickup %} + {% set pickup = assignment.destination.pickup(assignment.pickup) %}
    {{ icon('bus', 'w-5 h-5 shrink-0') }} - {{ assignment.pickup|bpn_pickup_label|default('-') }} {{ assignment.effectivePickupDate ? assignment.effectivePickupDate|date('d.m.Y') : '' }} + {{ pickup.city }}, {{ pickup.time }} Uhr
    {% endif %}
    diff --git a/templates/teamer/disposition/_list.html.twig b/templates/teamer/disposition/_list.html.twig index 2a64d3a..4f9b2aa 100644 --- a/templates/teamer/disposition/_list.html.twig +++ b/templates/teamer/disposition/_list.html.twig @@ -20,9 +20,10 @@ {{ assignment.destination.hotel }} {% if assignment.pickup %} + {% set pickup = assignment.destination.pickup(assignment.pickup) %}
    {{ icon('bus', 'w-5 h-5 shrink-0') }} - {{ assignment.pickup|bpn_pickup_label|default('-') }} {{ assignment.effectivePickupDate ? assignment.effectivePickupDate|date('d.m.Y') : '' }} + {{ pickup.city }}, {{ pickup.time }} Uhr
    {% endif %}