Browse code

Adjust fe booking and make use of new units

Benjamin Roth authored on12/08/2024 15:24:09
Showing3 changed files
... ...
@@ -1,6 +1,6 @@
1 1
 {% block content %}
2 2
     {% if modal %}<div class="modal-content">{% endif %}
3
-    <div id="wa-booking-{{ id }}" hx-target="this" hx-swap="outerHTML" class="frame">
3
+    <div id="wa-booking-{{ id }}" hx-target="this" hx-swap="outerHTML" class="frame" hx-indicator="#wa-booking-{{ id }}">
4 4
         <div class="frame__header">
5 5
             <h3>Reservierung</h3>
6 6
             <div class="grid-md u-gap-2">
... ...
@@ -49,15 +49,30 @@
49 49
             {% endif %}
50 50
             <form hx-post="/_ajax/vr_wa/v1/slot?do=updateReservation" enctype="multipart/form-data">
51 51
                 <input type="hidden" name="id" value="{{ id }}">
52
-                <fieldset>
53
-                    <label for="res-behaelter"><strong>Liefernde Bottichmenge</strong><sup class="text-danger">*</sup></label>
54
-                    <select id="res-behaelter" name="behaelter" required>
55
-                        <option value="">-</option>
56
-                        {% for option in buchen.behaelter %}
57
-                            <option value="{{ option }}"{{ buchung.behaelter == option ? ' selected' : '' }}>{{ option }}</option>
58
-                        {% endfor %}
59
-                    </select>
60
-                </fieldset>
52
+                <div class="grid-md u-gap-2">
53
+                    <div class="grid-c-6 mb-2 mb-0-md">
54
+                        <fieldset>
55
+                            <label for="res-behaeltereinheit"><strong>Liefernde Botticheinheit<sup class="text-danger">*</sup></strong></label>
56
+                            <select id="res-behaeltereinheit" name="unit" hx-get="/_ajax/vr_wa/v1/slot?do=availableBookingUnitAmount&id={{ id }}" hx-target="#wa-booking-{{ id }} #res-behaelter">
57
+                                <option value="">{{ 'tl_vr_wa_units.containers.0'|trans([], 'contao_tl_vr_wa_units') }}</option>
58
+                                {% for value, option in buchen.units %}
59
+                                    <option value="{{ value }}"{{ buchung.unit == value ? ' selected' : '' }}>{{ option }}</option>
60
+                                {% endfor %}
61
+                            </select>
62
+                        </fieldset>
63
+                    </div>
64
+                    <div class="grid-c-6 mb-2 mb-0-md">
65
+                        <fieldset>
66
+                            <label for="res-behaelter"><strong>Menge<sup class="text-danger">*</sup></strong></label>
67
+                            <select id="res-behaelter" name="behaelter" required>
68
+                                <option value="">-</option>
69
+                                {% for option in buchen.behaelter %}
70
+                                    <option value="{{ option }}"{{ buchung.amount == option ? ' selected' : '' }}>{{ option }}</option>
71
+                                {% endfor %}
72
+                            </select>
73
+                        </fieldset>
74
+                    </div>
75
+                </div>
61 76
                 {% if file is defined %}
62 77
                     <fieldset>
63 78
                         <div class="t-label">Aktuelle Datei</div>
... ...
@@ -76,6 +91,8 @@
76 91
                 </fieldset>
77 92
             </form>
78 93
         </div>
94
+
95
+        <div class="loader animated loading"></div>
79 96
     {% if modal %}</div>{% endif %}
80 97
 {% endblock %}
81 98
 
... ...
@@ -1,6 +1,6 @@
1 1
 {% block content %}
2 2
     {% if modal %}<div class="modal-content">{% endif %}
3
-        <div id="wa-slot-{{ id }}" class="frame" hx-get="/_ajax/vr_wa/v1/slot?do=details&id={{ id }}&modal=false" hx-target="this" hx-swap="outerHTML" hx-trigger="updateWaBooking from:body">
3
+        <div id="wa-slot-{{ id }}" class="frame" hx-get="/_ajax/vr_wa/v1/slot?do=details&id={{ id }}&modal=false" hx-target="this" hx-swap="outerHTML" hx-trigger="updateWaBooking from:body" hx-indicator="#wa-slot-{{ id }}">
4 4
             <div class="frame__header">
5 5
                 <h3>Zeitslot</h3>
6 6
                 <div class="grid-md u-gap-2">
... ...
@@ -60,7 +60,8 @@
60 60
                                 <div class="col-7">
61 61
                                     <div class="u-flex u-items-center u-gap-1">
62 62
                                         <i class="icon-behaelter-outline"></i>
63
-                                        {{ reservation.behaelter }}
63
+                                        {{ reservation.amount }} x {{ reservation.unitLabel }}
64
+                                        {% if reservation.unit > 0 %}({{ reservation.behaelter }} {{ 'tl_vr_wa_units.containers.0'|trans([], 'contao_tl_vr_wa_units') }}){% endif %}
64 65
                                     </div>
65 66
                                 </div>
66 67
                                 <div class="col u-text-right">
... ...
@@ -86,7 +87,7 @@
86 87
                             <div class="grid-c-6 mb-2 mb-0-md">
87 88
                                 <fieldset>
88 89
                                     <label for="res-behaeltereinheit"><strong>Liefernde Botticheinheit<sup class="text-danger">*</sup></strong></label>
89
-                                    <select id="res-behaeltereinheit" name="unit" hx-get="/_ajax/vr_wa/v1/slot?do=availableUnitAmount&id={{ id }}" hx-target="#wa-slot-{{ id }} #res-behaelter" hx-indicator="#wa-slot-{{ id }}">
90
+                                    <select id="res-behaeltereinheit" name="unit" hx-get="/_ajax/vr_wa/v1/slot?do=availableUnitAmount&id={{ id }}" hx-target="#wa-slot-{{ id }} #res-behaelter">
90 91
                                         <option value="">{{ 'tl_vr_wa_units.containers.0'|trans([], 'contao_tl_vr_wa_units') }}</option>
91 92
                                         {% for value, option in buchen.units %}
92 93
                                             <option value="{{ value }}">{{ option }}</option>
... ...
@@ -95,6 +95,9 @@ class SlotAjaxController extends AbstractController
95 95
             case 'availableUnitAmount':
96 96
                 return $this->renderAvailableUnitAmount();
97 97
 
98
+            case 'availableBookingUnitAmount':
99
+                return $this->renderAvailableBookingUnitAmount();
100
+
98 101
             case 'delete':
99 102
                 return $this->deleteReservation();
100 103
         }
... ...
@@ -123,7 +126,10 @@ class SlotAjaxController extends AbstractController
123 126
         {
124 127
             foreach ($Reservations as $reservation)
125 128
             {
126
-                $arrReservations[] = $reservation->row();
129
+                $Unit = WeinanlieferungUnitsModel::findByPk($reservation->unit);
130
+                $arrReservations[] = array_merge($reservation->row(),[
131
+                    'unitLabel' => $Unit->title ?? $this->translator->trans('tl_vr_wa_units.containers.0', [], 'contao_tl_vr_wa_units')
132
+                ]);
127 133
             }
128 134
         }
129 135
 
... ...
@@ -290,6 +296,19 @@ class SlotAjaxController extends AbstractController
290 296
         }
291 297
 
292 298
         $intAvailableBehaelter = max(0,$Slot->getAvailableBehaelter());
299
+        $arrUnits = [];
300
+
301
+        if (($Site = $Slot->getRelated('pid')) !== null)
302
+        {
303
+            if (($Units = $Site->getRelated('units')) !== null)
304
+            {
305
+                foreach ($Units as $unit)
306
+                {
307
+                    $arrUnits[$unit->id] = $unit->title . ' (' . $unit->containers . ' '.$this->translator->trans('tl_vr_wa_units.containers.0', [], 'contao_tl_vr_wa_units').')';
308
+                }
309
+            }
310
+
311
+        }
293 312
 
294 313
         $arrData = array_merge($arrData,[
295 314
             'modal' => $blnModal,
... ...
@@ -303,6 +322,7 @@ class SlotAjaxController extends AbstractController
303 322
             'buchen' => [
304 323
                 'buchbar' => (boolean) $intAvailableBehaelter,
305 324
                 'behaelter' => range(min($intAvailableBehaelter,1),$intAvailableBehaelter+$Booking->behaelter),
325
+                'units' => $arrUnits,
306 326
             ]
307 327
         ]);
308 328
 
... ...
@@ -319,6 +339,11 @@ class SlotAjaxController extends AbstractController
319 339
         Controller::loadDataContainer('tl_vr_wa_reservation');
320 340
         $arrData = [];
321 341
 
342
+        if (($Slot = WeinanlieferungSlotsModel::findByPk($_REQUEST['id'])) === null)
343
+        {
344
+            return $this->renderDetails(false,'<div class="toast toast--danger mx-0">Fehler: der Zeitslot ist nicht verfügbar.</div>');
345
+        }
346
+
322 347
         if (($rootPage = Frontend::getRootPageFromUrl()) !== null && !empty($rootPage->vr_wa_uploadFolderSRC))
323 348
         {
324 349
             $File = new FormFileUpload(\Contao\Widget::getAttributesFromDca($GLOBALS['TL_DCA']['tl_vr_wa_reservation']['fields']['upload'], 'upload'));
... ...
@@ -346,13 +371,13 @@ class SlotAjaxController extends AbstractController
346 371
         }
347 372
 
348 373
         // Form validation
349
-        if (($Slot = WeinanlieferungSlotsModel::findByPk($_REQUEST['id'])) !== null)
374
+        $intBehaelter = Input::post('behaelter');
375
+
376
+        if (Input::post('behaelter') > $Slot->getAvailableBehaelter())
350 377
         {
351
-            if (Input::post('behaelter') > $Slot->getAvailableBehaelter())
352
-            {
353
-                return $this->renderDetails(false,sprintf('<div class="toast toast--danger mx-0">Fehler: Es sind mittlerweile nur noch %s Bottiche verfügbar.</div>',$Slot->getAvailableBehaelter()));
354
-            }
378
+            return $this->renderDetails(false,sprintf('<div class="toast toast--danger mx-0">Fehler: Es sind mittlerweile nur noch %s Bottiche verfügbar.</div>',$Slot->getAvailableBehaelter()));
355 379
         }
380
+
356 381
         $arrError = [];
357 382
         foreach (['behaelter'] as $field)
358 383
         {
... ...
@@ -362,6 +387,29 @@ class SlotAjaxController extends AbstractController
362 387
             }
363 388
         }
364 389
 
390
+        // Get allowed units
391
+        if (Input::post('unit'))
392
+        {
393
+            if (($SelectedUnit = WeinanlieferungUnitsModel::findByPk(intval(Input::post('unit')))) === null)
394
+            {
395
+                return $this->renderDetails(false, '<div class="toast toast--danger mx-0">Die gewünschte Botticheinheit steht nicht zur Verfügung. Bitte versuchen Sie es noch einmal.</div>');
396
+            }
397
+
398
+            if (($Site = $Slot->getRelated('pid')) !== null)
399
+            {
400
+                $unitIds = StringUtil::deserialize($Site->units, true);
401
+                $Units = WeinanlieferungUnitsModel::findMultipleByIds($unitIds);
402
+
403
+                if (!\in_array(intval(Input::post('unit')), $Units->fetchEach('id')))
404
+                {
405
+                    return $this->renderDetails(false, '<div class="toast toast--danger mx-0">Die gewünschte Botticheinheit steht nicht mehr zur Verfügung. Bitte versuchen Sie es noch einmal.</div>');
406
+                }
407
+            }
408
+
409
+            $intBehaelter = intval($intBehaelter) * intval($SelectedUnit->containers);
410
+        }
411
+
412
+
365 413
         if (count($arrError))
366 414
         {
367 415
             return $this->renderDetails(false,'<div class="toast toast--danger mx-0">Bitte geben Sie alle Pflichtangaben (mit * markierte Felder) an</div>');
... ...
@@ -372,7 +420,8 @@ class SlotAjaxController extends AbstractController
372 420
             'pid' => $_REQUEST['id'],
373 421
             'tstamp' => time(),
374 422
             'uid' => FrontendUser::getInstance()->id,
375
-            'behaelter' => Input::post('behaelter'),
423
+            'unit' => intval(Input::post('unit')),
424
+            'behaelter' => $intBehaelter,
376 425
             'amount' => Input::post('behaelter'),
377 426
         ]);
378 427
         $Reservation->setRow($arrData);
... ...
@@ -392,7 +441,12 @@ class SlotAjaxController extends AbstractController
392 441
 
393 442
         if (($Reservation = WeinanlieferungReservationModel::findById($_REQUEST['id'])) === null)
394 443
         {
395
-            return new Response('Could not load booking data',500);
444
+            return $this->renderBooking(false,'<div class="toast toast--danger mx-0">Fehler: Buchung kann nicht geladen werden.</div>');
445
+        }
446
+
447
+        if (($Slot = $Reservation->getRelated('pid')) === null)
448
+        {
449
+            return $this->renderBooking(false,'<div class="toast toast--danger mx-0">Fehler: der Zeitslot ist nicht verfügbar.</div>');
396 450
         }
397 451
 
398 452
         if (($rootPage = Frontend::getRootPageFromUrl()) !== null && !empty($rootPage->vr_wa_uploadFolderSRC))
... ...
@@ -417,15 +471,15 @@ class SlotAjaxController extends AbstractController
417 471
         }
418 472
 
419 473
         // Form validation
420
-        if (($Slot = $Reservation->getRelated('pid')) !== null)
474
+        $intBehaelter = Input::post('behaelter');
475
+
476
+        if (Input::post('behaelter') > $Slot->getAvailableBehaelter()+$Reservation->behaelter)
421 477
         {
422
-            if (Input::post('behaelter') > $Slot->getAvailableBehaelter()+$Reservation->behaelter)
423
-            {
424
-                return $this->renderBooking(false,sprintf('<div class="toast toast--danger mx-0">Fehler: Es sind mittlerweile nur noch %s Bottiche verfügbar.</div>',$Slot->getAvailableBehaelter()+$Reservation->behaelter));
425
-            }
478
+            return $this->renderBooking(false,sprintf('<div class="toast toast--danger mx-0">Fehler: Es sind mittlerweile nur noch %s Bottiche verfügbar.</div>',$Slot->getAvailableBehaelter()+$Reservation->behaelter));
426 479
         }
480
+
427 481
         $arrError = [];
428
-        foreach (['behaelter','sorten','ernteart','lage'] as $field)
482
+        foreach (['behaelter'] as $field)
429 483
         {
430 484
             if (empty(Input::post($field)))
431 485
             {
... ...
@@ -433,41 +487,37 @@ class SlotAjaxController extends AbstractController
433 487
             }
434 488
         }
435 489
 
436
-        if (count($arrError))
490
+        // Get allowed units
491
+        if (Input::post('unit'))
437 492
         {
438
-            return $this->renderBooking(false,'<div class="toast toast--danger mx-0">Bitte geben Sie alle Pflichtangaben (mit * markierte Felder) an</div>');
439
-        }
493
+            if (($SelectedUnit = WeinanlieferungUnitsModel::findByPk(intval(Input::post('unit')))) === null)
494
+            {
495
+                return $this->renderDetails(false, '<div class="toast toast--danger mx-0">Die gewünschte Botticheinheit steht nicht zur Verfügung. Bitte versuchen Sie es noch einmal.</div>');
496
+            }
440 497
 
441
-        $arrSorten = [];
442
-        if (!is_array(Input::post('sorten')))
443
-        {
444
-            $arrSorten[] = Input::post('sorten');
445
-        } else {
446
-            $arrSorten = implode(';', Input::post('sorten'));
447
-        }
498
+            if (($Site = $Slot->getRelated('pid')) !== null)
499
+            {
500
+                $unitIds = StringUtil::deserialize($Site->units, true);
501
+                $Units = WeinanlieferungUnitsModel::findMultipleByIds($unitIds);
448 502
 
449
-        $arrErnteart = [];
450
-        if (!is_array(Input::post('ernteart')))
451
-        {
452
-            $arrErnteart[] = Input::post('ernteart');
453
-        } else {
454
-            $arrErnteart = implode(',', Input::post('ernteart'));
503
+                if (!\in_array(intval(Input::post('unit')), $Units->fetchEach('id')))
504
+                {
505
+                    return $this->renderDetails(false, '<div class="toast toast--danger mx-0">Die gewünschte Botticheinheit steht nicht mehr zur Verfügung. Bitte versuchen Sie es noch einmal.</div>');
506
+                }
507
+            }
508
+
509
+            $intBehaelter = intval($intBehaelter) * intval($SelectedUnit->containers);
455 510
         }
456 511
 
457
-        $arrLage = [];
458
-        if (!is_array(Input::post('lage')))
512
+        if (count($arrError))
459 513
         {
460
-            $arrLage[] = Input::post('lage');
461
-        } else {
462
-            $arrLage = implode(',', Input::post('lage'));
514
+            return $this->renderBooking(false,'<div class="toast toast--danger mx-0">Bitte geben Sie alle Pflichtangaben (mit * markierte Felder) an</div>');
463 515
         }
464 516
 
465 517
         $Reservation->tstamp = time();
466
-        $Reservation->behaelter = Input::post('behaelter');
518
+        $Reservation->unit = intval(Input::post('unit'));
519
+        $Reservation->behaelter = $intBehaelter;
467 520
         $Reservation->amount = Input::post('behaelter');
468
-        $Reservation->sorten = $arrSorten;
469
-        $Reservation->ernteart = $arrErnteart;
470
-        $Reservation->lage = $arrLage;
471 521
 
472 522
         $Reservation->save();
473 523
 
... ...
@@ -538,4 +588,40 @@ class SlotAjaxController extends AbstractController
538 588
         return new Response($strOutput);
539 589
     }
540 590
 
591
+    protected function renderAvailableBookingUnitAmount(): Response
592
+    {
593
+        if (empty($_REQUEST['id']))
594
+        {
595
+            return new Response('Required parameter missing',412);
596
+        }
597
+
598
+        if (($Reservation = WeinanlieferungReservationModel::findByPk($_REQUEST['id'])) === null || ($Slot = $Reservation->getRelated('pid')) === null)
599
+        {
600
+            return new Response('Could not load slot data',500);
601
+        }
602
+
603
+        $intAvailableBehaelter = max(0,$Slot->getAvailableBehaelter())+$Reservation->behaelter;
604
+        $intAmount = $intAvailableBehaelter;
605
+
606
+        if (!empty($_REQUEST['unit']) && intval($_REQUEST['unit']) > 0)
607
+        {
608
+            if (($Site = $Slot->getRelated('pid')) === null || ($Unit = WeinanlieferungUnitsModel::findByPk($_REQUEST['unit'])) === null)
609
+            {
610
+                return new Response('Could not load unit data', 500);
611
+            }
612
+
613
+            $intAmount = floor($intAvailableBehaelter / max(1, $Unit->containers));
614
+        }
615
+
616
+        $strOutput = "<select id=\"res-behaelter\" name=\"behaelter\" required>
617
+<option value=\"\">-</option>\n";
618
+        for ($i = 1; $i <= $intAmount; $i++)
619
+        {
620
+            $strOutput .= "<option value=\"$i\">$i</option>\n";
621
+        }
622
+        $strOutput .= "</select>\n";
623
+
624
+        return new Response($strOutput);
625
+    }
626
+
541 627
 }