Browse code

Update

Benjamin Roth authored on09/08/2023 16:04:53
Showing10 changed files
... ...
@@ -56,6 +56,7 @@ $GLOBALS['TL_DCA']['tl_vr_wa_reservation'] = array
56 56
         'sorten'       => array
57 57
         (
58 58
             'foreignKey'   => 'tl_vr_wa_rebsorte.title',
59
+            'eval'  => array('multiple'=>true, 'csv'=>','),
59 60
             'sql'       => "blob NULL",
60 61
             'relation'   => array('type' => 'hasMany', 'load' => 'lazy')
61 62
         ),
62 63
new file mode 100644
... ...
@@ -0,0 +1,72 @@
1
+{% block content %}
2
+    {% if modal %}<div class="modal-content">{% endif %}
3
+    <div id="wa-slot-{{ id }}">
4
+            <dl>
5
+                <dt>Tag/Uhrzeit</dt>
6
+                <dd>{{ slot.time|date('d.m.Y H:i') }}</dd>
7
+
8
+                <dt>Gebuchte Behälterkapazität</dt>
9
+                <dd>{{ buchung.behaelter }}</dd>
10
+
11
+                <dt>Anliefernde Sorten</dt>
12
+                <dd>{{ buchung.sorten|join(', ') }}</dd>
13
+            </dl>
14
+            <h3>Reservierung ändern</h3>
15
+            <form hx-post="/_ajax/vr_wa/v1/slot?do=updateReservation">
16
+                <input type="hidden" name="id" value="{{ id }}">
17
+                <div class="dflex">
18
+                    <div>
19
+                        <label for="res-behaelter">Liefernde Behältermenge</label>
20
+                        <select id="res-behaelter" name="behaelter" required>
21
+                            <option value="">-</option>
22
+                            {% for option in buchen.behaelter %}
23
+                                <option value="{{ option }}"{{ buchung.behaelter == option ? ' selected' : '' }}>{{ option }}</option>
24
+                            {% endfor %}
25
+                        </select>
26
+                    </div>
27
+                    <fieldset>
28
+                      <legend>Anliefernde Rebsorte(n)</legend>
29
+                        {% for value,label in buchen.sorten %}
30
+                            <label><input type="checkbox" name="sorten[]" value="{{ value }}"{{ value in buchung.sorten|keys ? ' checked' : '' }}> <span class="checkable">{{ label }}</span></label><br>
31
+                        {% endfor %}
32
+                    </fieldset>
33
+                    <div>
34
+                        <button type="submit">Speichern</button>
35
+                    </div>
36
+                </div>
37
+            </form>
38
+        </div>
39
+    {% if modal %}</div>{% endif %}
40
+{% endblock %}
41
+
42
+{% block modal %}
43
+    {% if modal %}
44
+        <script>
45
+            (function ($) {
46
+
47
+                window.modals = window.modals || []
48
+                window.modals.wa_slots = window.modals.wa_slots || []
49
+
50
+                if (window.modals.wa_slots.details{{ id }} === undefined)
51
+                {
52
+                    window.modals.wa_slots.details{{ id }} = new jBox('Modal', {
53
+                    closeButton: 'box',
54
+                    content: $('#wa-slot-{{ id }}'),
55
+                    maxWidth: 650,
56
+                    minWidth: 100,
57
+                    minHeight: 100,
58
+                    width: 650,
59
+                    overlay: true,
60
+                    closeOnClick: false,
61
+                    zIndex: 'auto',
62
+                    addClass: ''
63
+                }).open();
64
+                } else {
65
+                    window.modals.wa_slots.details{{ id }}.content.empty();
66
+                    window.modals.wa_slots.details{{ id }}.setContent($('#wa-slot-{{ id }}')).open();
67
+                }
68
+
69
+            })(jQuery);
70
+        </script>
71
+    {% endif %}
72
+{% endblock %}
... ...
@@ -1,66 +1,96 @@
1
-<div class="modal-content">
2
-    <div id="wa-slot-{{ id }}">
3
-        <dl>
4
-            <dt>Tag/Uhrzeit</dt>
5
-            <dd>{{ slot.time|date('d.m.Y H:i') }}</dd>
1
+{% block content %}
2
+    {% if modal %}<div class="modal-content">{% endif %}
3
+        <div id="wa-slot-{{ id }}" hx-get="/_ajax/vr_wa/v1/slot?do=details&id={{ id }}&modal=false" hx-target="this" hx-swap="outerHTML" hx-trigger="updateWaBooking from:body">
4
+            <dl>
5
+                <dt>Tag/Uhrzeit</dt>
6
+                <dd>{{ slot.time|date('d.m.Y H:i') }}</dd>
6 7
 
7
-            <dt>Verfügbare Behälterkapazität</dt>
8
-            <dd>{{ slot.behaelterAvailable }}</dd>
8
+                <dt>Verfügbare Behälterkapazität</dt>
9
+                <dd>{{ slot.behaelterAvailable }}</dd>
9 10
 
10
-            <dt>Verarbeitete Sorten</dt>
11
-            <dd>{{ slot.sorte|join(', ') }}</dd>
12
-        </dl>
13
-        <h3>Reservieren</h3>
14
-        {% if buchen.buchbar %}
15
-            <form hx-post="/_ajax/vr_wa/v1/slot?do=reservate">
16
-                <input type="hidden" name="id" value="{{ id }}">
17
-                <div class="dflex">
18
-                    <div>
19
-                        <label for="res-behaelter">Liefernde Behältermenge</label>
20
-                        <select id="res-behaelter" name="behaelter" required>
21
-                            <option value="">-</option>
22
-                            {% for option in buchen.behaelter %}
23
-                                <option value="{{ option }}">{{ option }}</option>
11
+                <dt>Verarbeitete Sorten</dt>
12
+                <dd>{{ slot.sorte|join(', ') }}</dd>
13
+            </dl>
14
+
15
+            {% if reservations|length %}
16
+                <h4>Ihre Reservierungen</h4>
17
+                <ul class="reservations">
18
+                    {% for reservation in reservations %}
19
+                        <li class="flex align-items-center">
20
+                            <div class="full fifth-500">
21
+                                <div class="icon-behaelter-outline">{{ reservation.behaelter }}</div>
22
+                            </div>
23
+                            <div class="full three-fifth-500">
24
+                                <div class="icon-reben-outline">{{ reservation.sorten|join(', ') }}</div>
25
+                            </div>
26
+                            <div class="full fifth-500">
27
+                                <div><a hx-get="/_ajax/vr_wa/v1/slot?do=booking&id={{ reservation.id }}" hx-target="body" hx-swap="beforeend" href="javascript:;">Bearbeiten</a></div>
28
+                            </div>
29
+                        </li>
30
+                    {% endfor %}
31
+                </ul>
32
+            {% endif %}
33
+
34
+            <h3>Reservieren</h3>
35
+            {% if buchen.buchbar %}
36
+                <form hx-post="/_ajax/vr_wa/v1/slot?do=reservate">
37
+                    <input type="hidden" name="id" value="{{ id }}">
38
+                    <div class="dflex">
39
+                        <div>
40
+                            <label for="res-behaelter">Liefernde Behältermenge</label>
41
+                            <select id="res-behaelter" name="behaelter" required>
42
+                                <option value="">-</option>
43
+                                {% for option in buchen.behaelter %}
44
+                                    <option value="{{ option }}">{{ option }}</option>
45
+                                {% endfor %}
46
+                            </select>
47
+                        </div>
48
+                        <fieldset>
49
+                          <legend>Anliefernde Rebsorte(n)</legend>
50
+                            {% for value,label in buchen.sorten %}
51
+                                <label><input type="checkbox" name="sorten[]" value="{{ value }}"> <span class="checkable">{{ label }}</span></label><br>
24 52
                             {% endfor %}
25
-                        </select>
53
+                        </fieldset>
54
+                        <div>
55
+                            <button type="submit">Reservieren</button>
56
+                        </div>
26 57
                     </div>
27
-                    <fieldset>
28
-                      <legend>Anliefernde Rebsorte(n)</legend>
29
-                        {% for value,label in buchen.sorten %}
30
-                            <label><input type="checkbox" name="sorten[]" value="{{ value }}"> <span class="checkable">{{ label }}</span></label><br>
31
-                        {% endfor %}
32
-                    </fieldset>
33
-                    <div>
34
-                        <button type="submit">Reservieren</button>
35
-                    </div>
36
-                </div>
37
-            </form>
38
-        {% else %}
39
-          <p class="warning">Dieser Zeit-Slot ist bereits ausgebucht</p>
40
-        {% endif %}
41
-    </div>
42
-</div>
43
-<script>
44
-    (function ($) {
58
+                </form>
59
+            {% else %}
60
+              <p class="warning">Dieser Zeit-Slot ist bereits ausgebucht</p>
61
+            {% endif %}
62
+        </div>
63
+    {% if modal %}</div>{% endif %}
64
+{% endblock %}
65
+
66
+{% block modal %}
67
+    {% if modal %}
68
+        <script>
69
+            (function ($) {
45 70
 
46
-        window.modals = window.modals || []
47
-        window.modals.wa_slots = window.modals.wa_slots || []
71
+                window.modals = window.modals || []
72
+                window.modals.wa_slots = window.modals.wa_slots || []
48 73
 
49
-        if (window.modals.wa_slots.details{{ id }} === undefined)
50
-        {
51
-            window.modals.wa_slots.details{{ id }} = new jBox('Modal', {
52
-            closeButton: 'box',
53
-            content: $('#wa-slot-{{ id }}'),
54
-            maxWidth: 650,
55
-            minWidth: 100,
56
-            minHeight: 100,
57
-            width: 650,
58
-            addClass: ''
59
-        }).open();
60
-        } else {
61
-            window.modals.wa_slots.details{{ id }}.content.empty();
62
-            window.modals.wa_slots.details{{ id }}.setContent($('#wa-slot-{{ id }}')).open();
63
-        }
74
+                if (window.modals.wa_slots.details{{ id }} === undefined)
75
+                {
76
+                    window.modals.wa_slots.details{{ id }} = new jBox('Modal', {
77
+                    closeButton: 'box',
78
+                    content: $('#wa-slot-{{ id }}'),
79
+                    maxWidth: 650,
80
+                    minWidth: 100,
81
+                    minHeight: 100,
82
+                    width: 650,
83
+                    overlay: true,
84
+                    closeOnClick: false,
85
+                    zIndex: 'auto',
86
+                    addClass: ''
87
+                }).open();
88
+                } else {
89
+                    window.modals.wa_slots.details{{ id }}.content.empty();
90
+                    window.modals.wa_slots.details{{ id }}.setContent($('#wa-slot-{{ id }}')).open();
91
+                }
64 92
 
65
-    })(jQuery);
66
-</script>
93
+            })(jQuery);
94
+        </script>
95
+    {% endif %}
96
+{% endblock %}
... ...
@@ -1,4 +1,4 @@
1
-<div hx-get="{{ insert_tag('env::request') }}" hx-headers='{"VR-Ajax": "WabookingsModule"}' hx-trigger="updateWaList from:body" class="{{ class }} content-wrapper block"{{ cssID }}{% if style is defined and style is not empty %} style="{{ style }}"{% endif %}>
1
+<div hx-get="{{ insert_tag('env::request') }}" hx-headers='{"VR-Ajax": "WaBookedModule"}' hx-trigger="updateWaBooking from:body" class="{{ class }} content-wrapper block"{{ cssID }}{% if style is defined and style is not empty %} style="{{ style }}"{% endif %}>
2 2
 
3 3
     {% block content %}
4 4
         {% if days is defined and days|length %}
... ...
@@ -24,6 +24,7 @@
24 24
                                         </div>
25 25
                                         <div class="full third-500 sixth-900 align-right action">
26 26
                                             <a hx-get="/_ajax/vr_wa/v1/slot?do=delete&id={{ booking.id }}" hx-target="body" hx-swap="beforeend" href="javascript:;" class="button error">Löschen</a>
27
+                                            <a hx-get="/_ajax/vr_wa/v1/slot?do=booking&id={{ booking.id }}" hx-target="body" hx-swap="beforeend" href="javascript:;" class="button">Anzeigen</a>
27 28
                                         </div>
28 29
                                     </div>
29 30
                                 </div>
... ...
@@ -1,4 +1,4 @@
1
-<div hx-get="{{ insert_tag('env::request') }}" hx-headers='{"VR-Ajax": "WaSlotsModule"}' hx-trigger="updateWaList from:body" class="{{ class }} content-wrapper block"{{ cssID }}{% if style is defined and style is not empty %} style="{{ style }}"{% endif %}>
1
+<div hx-get="{{ insert_tag('env::request') }}" hx-headers='{"VR-Ajax": "WaSlotsModule"}' hx-trigger="updateWaList from:body, updateWaBooking from:body" class="{{ class }} content-wrapper block"{{ cssID }}{% if style is defined and style is not empty %} style="{{ style }}"{% endif %}>
2 2
 
3 3
     {% block filter %}
4 4
         <form hx-get="{{ insert_tag('env::request') }}" hx-headers='{"VR-Ajax": "WaSlotsModule"}' hx-trigger="change, submit" hx-target="closest .content-wrapper" class="filter">
5 5
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 413 413" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="412.5" height="412.5" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g id="Behaelter"><path d="M412.5,119.063c-0,12.418 -10.082,22.5 -22.5,22.5l-367.5,-0c-12.418,-0 -22.5,-10.082 -22.5,-22.5c0,-12.419 10.082,-22.5 22.5,-22.5l367.5,-0c12.418,-0 22.5,10.081 22.5,22.5Zm-15,-0c-0,-4.14 -3.361,-7.5 -7.5,-7.5l-367.5,-0c-4.139,-0 -7.5,3.36 -7.5,7.5c0,4.139 3.361,7.5 7.5,7.5l367.5,-0c4.139,-0 7.5,-3.361 7.5,-7.5Z"/><path d="M379.41,141.563l-32.166,168.283c-0.676,3.535 -3.768,6.091 -7.367,6.091l-267.254,0c-3.599,0 -6.691,-2.556 -7.367,-6.091l-32.166,-168.283l15.271,-0c6.778,35.459 30.464,159.374 30.464,159.374l254.85,0.001l30.464,-159.375l15.271,-0Z"/></g></g></svg>
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 413 413" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="412.5" height="412.5" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g><path d="M74.684,98.842c18.526,2.813 31.283,20.137 28.47,38.662c-2.812,18.526 -20.136,31.284 -38.662,28.471c-18.526,-2.812 -31.283,-20.136 -28.471,-38.662c2.813,-18.526 20.137,-31.283 38.663,-28.471Zm-2.252,14.83c-10.341,-1.57 -20.011,5.551 -21.581,15.892c-1.569,10.341 5.552,20.011 15.892,21.581c10.341,1.57 20.011,-5.551 21.581,-15.892c1.57,-10.341 -5.551,-20.011 -15.892,-21.581Z"/><path d="M109.897,166.703c25.725,3.905 43.44,27.961 39.534,53.686c-3.905,25.725 -27.961,43.44 -53.686,39.535c-25.725,-3.906 -43.44,-27.962 -39.534,-53.687c3.905,-25.725 27.961,-43.44 53.686,-39.534Zm-2.251,14.83c-17.54,-2.663 -33.942,9.415 -36.605,26.955c-2.663,17.541 9.415,33.943 26.955,36.605c17.54,2.663 33.943,-9.415 36.605,-26.955c2.663,-17.54 -9.415,-33.942 -26.955,-36.605Z"/><path d="M148.372,262.486c17.513,2.659 29.573,19.036 26.914,36.549c-2.659,17.513 -19.036,29.573 -36.549,26.915c-17.513,-2.659 -29.573,-19.036 -26.915,-36.55c2.659,-17.513 19.036,-29.573 36.55,-26.914Zm-2.252,14.83c-9.328,-1.416 -18.051,5.008 -19.468,14.336c-1.416,9.328 5.008,18.051 14.336,19.468c9.329,1.416 18.052,-5.008 19.468,-14.336c1.416,-9.329 -5.007,-18.052 -14.336,-19.468Z"/><path d="M236.218,298.467c13.389,2.032 22.609,14.553 20.576,27.942c-2.032,13.39 -14.553,22.61 -27.942,20.577c-13.39,-2.033 -22.61,-14.553 -20.577,-27.943c2.033,-13.389 14.553,-22.609 27.943,-20.576Zm-2.252,14.83c-5.204,-0.791 -10.071,2.793 -10.861,7.998c-0.79,5.204 2.794,10.071 7.998,10.861c5.205,0.79 10.071,-2.794 10.861,-7.998c0.79,-5.205 -2.793,-10.071 -7.998,-10.861Z"/><path d="M174.691,339.53c19.644,2.982 33.171,21.352 30.189,40.996c-2.983,19.644 -21.352,33.171 -40.996,30.189c-19.644,-2.983 -33.171,-21.352 -30.189,-40.996c2.982,-19.644 21.352,-33.171 40.996,-30.189Zm-2.252,14.83c-11.459,-1.739 -22.174,6.152 -23.914,17.61c-1.739,11.459 6.151,22.175 17.61,23.915c11.459,1.739 22.175,-6.152 23.914,-17.611c1.74,-11.459 -6.151,-22.174 -17.61,-23.914Z"/><path d="M163.421,106.453c17.641,2.678 29.789,19.175 27.111,36.817c-2.678,17.641 -19.175,29.789 -36.816,27.111c-17.642,-2.678 -29.79,-19.175 -27.111,-36.817c2.678,-17.641 19.175,-29.789 36.816,-27.111Zm-2.251,14.83c-9.457,-1.435 -18.3,5.077 -19.735,14.533c-1.436,9.456 5.076,18.299 14.532,19.735c9.457,1.435 18.3,-5.076 19.735,-14.533c1.436,-9.456 -5.076,-18.299 -14.532,-19.735Z"/><path d="M204.597,191.939c19.252,2.923 32.51,20.926 29.587,40.178c-2.923,19.252 -20.926,32.51 -40.178,29.587c-19.252,-2.923 -32.51,-20.926 -29.587,-40.178c2.923,-19.252 20.926,-32.509 40.178,-29.587Zm-2.251,14.83c-11.067,-1.68 -21.417,5.941 -23.097,17.008c-1.68,11.068 5.941,21.417 17.008,23.097c11.067,1.68 21.417,-5.941 23.097,-17.008c1.68,-11.067 -5.941,-21.416 -17.008,-23.097Z"/><path d="M277.889,217.486c16.747,2.542 28.28,18.203 25.738,34.951c-2.543,16.748 -18.204,28.28 -34.952,25.738c-16.747,-2.543 -28.28,-18.204 -25.738,-34.952c2.543,-16.747 18.204,-28.28 34.952,-25.737Zm-2.252,14.83c-8.562,-1.3 -16.57,4.596 -17.87,13.159c-1.3,8.563 4.597,16.57 13.16,17.87c8.562,1.3 16.57,-4.597 17.87,-13.16c1.299,-8.562 -4.597,-16.569 -13.16,-17.869Z"/><path d="M251.327,134.541c13.734,2.085 23.191,14.928 21.106,28.662c-2.085,13.734 -14.928,23.192 -28.662,21.107c-13.734,-2.085 -23.191,-14.928 -21.106,-28.662c2.085,-13.734 14.928,-23.192 28.662,-21.107Zm-2.252,14.83c-5.549,-0.842 -10.738,2.979 -11.58,8.528c-0.843,5.549 2.978,10.738 8.527,11.581c5.55,0.842 10.739,-2.979 11.581,-8.528c0.842,-5.549 -2.979,-10.738 -8.528,-11.581Z"/><path d="M342.583,133.058c22.008,3.341 37.164,23.921 33.823,45.93c-3.342,22.008 -23.922,37.164 -45.931,33.822c-22.008,-3.341 -37.163,-23.921 -33.822,-45.93c3.341,-22.008 23.922,-37.163 45.93,-33.822Zm-2.251,14.83c-13.824,-2.099 -26.75,7.42 -28.849,21.244c-2.099,13.823 7.421,26.75 21.244,28.848c13.823,2.099 26.75,-7.42 28.849,-21.244c2.098,-13.823 -7.421,-26.75 -21.244,-28.848Z"/></g><path d="M196.6,105.642c0,0 9.626,-42.688 26.774,-73.146c8.068,-14.329 17.988,-25.882 28.928,-30.526c1.279,-0.543 2.683,-0.72 4.057,-0.512l29.66,4.503c3.243,0.493 5.79,3.036 6.287,6.278c0.498,3.243 -1.17,6.432 -4.117,7.874c0,0 -27.67,14.345 -63.035,92.453c-1.386,3.06 -4.637,4.826 -7.958,4.322l-14.404,-2.187c-2.057,-0.312 -3.892,-1.465 -5.066,-3.183c-1.174,-1.717 -1.582,-3.845 -1.126,-5.876Zm16.584,-4.535l0.677,0.103c21.549,-46.341 40.728,-70.665 53.129,-82.966c0,0 -10.619,-1.612 -10.619,-1.612c-10.723,5.681 -19.275,20.43 -26.324,35.912c-8.315,18.265 -14.065,37.964 -16.863,48.563Z"/></g></g></svg>
0 2
\ No newline at end of file
... ...
@@ -57,24 +57,36 @@ class SlotAjaxController extends AbstractController
57 57
             return new Response('Required parameter missing',412);
58 58
         }
59 59
 
60
+        $blnModal = true;
61
+
62
+        if (!empty($_REQUEST['modal']))
63
+        {
64
+            $blnModal = !(strtolower($_REQUEST['modal']) == 'false');
65
+        }
66
+
60 67
         switch ($_REQUEST['do'])
61 68
         {
62 69
             case 'details':
63
-                return $this->renderDetails();
64
-                break;
70
+                return $this->renderDetails($blnModal);
71
+
72
+            case 'booking':
73
+                return $this->renderBooking($blnModal);
65 74
 
66 75
             case 'reservate':
67 76
                 return $this->reservate();
68 77
 
78
+            case 'updateReservation':
79
+                return $this->updateReservation();
80
+
69 81
             case 'delete':
70
-                return $this->deleteBooking();
82
+                return $this->deleteReservation();
71 83
         }
72 84
 
73 85
         return new Response('',500);
74 86
         return new Response(null,203);
75 87
     }
76 88
 
77
-    protected function renderDetails()
89
+    protected function renderDetails(bool $blnModal=true)
78 90
     {
79 91
         if (empty($_REQUEST['id']))
80 92
         {
... ...
@@ -86,6 +98,25 @@ class SlotAjaxController extends AbstractController
86 98
             return new Response('Could not load slot data',500);
87 99
         }
88 100
 
101
+        // Get slot reservations from user
102
+        $arrReservations = [];
103
+
104
+        if (($Reservations = WeinanlieferungReservationModel::findBy(["uid = ?","pid = ?"],[FrontendUser::getInstance()->id,$Slot->id])) !== null)
105
+        {
106
+            foreach ($Reservations as $reservation)
107
+            {
108
+                $arrSortenBooked = [];
109
+                if (($Sorten = $reservation->getRelated('sorten')) !== null)
110
+                {
111
+                    $arrSortenBooked = $Sorten->fetchEach('title');
112
+                }
113
+                $arrReservations[] = array_merge($reservation->row(),[
114
+                    'sorten' => $arrSortenBooked
115
+                ]);
116
+            }
117
+        }
118
+
119
+        // Build data
89 120
         $arrSorten = [];
90 121
         if (($Sorten = $Slot->getRelated('sorte')) !== null)
91 122
         {
... ...
@@ -95,6 +126,7 @@ class SlotAjaxController extends AbstractController
95 126
         $intAvailableBehaelter = $Slot->getAvailableBehaelter();
96 127
 
97 128
         $arrData = [
129
+            'modal' => $blnModal,
98 130
             'id'       => $Slot->id,
99 131
             'slot'     => array_merge($Slot->row(),[
100 132
                 'sorte' => $arrSorten,
... ...
@@ -105,17 +137,65 @@ class SlotAjaxController extends AbstractController
105 137
                 'buchbar' => (boolean) $intAvailableBehaelter,
106 138
                 'behaelter' => range(min($intAvailableBehaelter,1),$intAvailableBehaelter),
107 139
                 'sorten' => $arrSorten
108
-            ]
140
+            ],
141
+            'reservations' => $arrReservations
109 142
         ];
110 143
 
111 144
         return $this->render('@Contao/modal_slot_details.html.twig',$arrData);
112 145
     }
113 146
 
147
+    protected function renderBooking(bool $blnModal=true)
148
+    {
149
+        if (empty($_REQUEST['id']))
150
+        {
151
+            return new Response('Required parameter missing',412);
152
+        }
153
+
154
+        /** @var WeinanlieferungSlotsModel $Slot */
155
+        if (($Booking = WeinanlieferungReservationModel::findById($_REQUEST['id'])) === null || ($Slot = $Booking->getRelated('pid')) === null)
156
+        {
157
+            return new Response('Could not load booking data',500);
158
+        }
159
+
160
+        $arrSortenAvailable = [];
161
+        if (($Sorten = $Slot->getRelated('sorte')) !== null)
162
+        {
163
+            $arrSortenAvailable = array_combine($Sorten->fetchEach('id'),$Sorten->fetchEach('title'));
164
+        }
165
+        $arrSortenBooked = [];
166
+        if (($Sorten = $Booking->getRelated('sorten')) !== null)
167
+        {
168
+            $arrSortenBooked = array_combine($Sorten->fetchEach('id'),$Sorten->fetchEach('title'));
169
+        }
170
+
171
+        $intAvailableBehaelter = $Slot->getAvailableBehaelter();
172
+
173
+        $arrData = [
174
+            'modal' => $blnModal,
175
+            'id'       => $Booking->id,
176
+            'slot'     => array_merge($Slot->row(),[
177
+                'sorte' => $arrSortenAvailable,
178
+                'behaelterAvailable' => $intAvailableBehaelter
179
+            ]),
180
+            'buchung' => array_merge($Booking->row(),[
181
+                'sorten' => $arrSortenBooked
182
+            ]),
183
+            'standort' => $Slot->getRelated('pid'),
184
+            'buchen' => [
185
+                'buchbar' => (boolean) $intAvailableBehaelter,
186
+                'behaelter' => range(min($intAvailableBehaelter,1),$intAvailableBehaelter+$Booking->behaelter),
187
+                'sorten' => $arrSortenAvailable
188
+            ]
189
+        ];
190
+
191
+        return $this->render('@Contao/modal_booking_details.html.twig',$arrData);
192
+    }
193
+
114 194
     protected function reservate()
115 195
     {
116 196
         if (empty($_REQUEST['id']) || empty(Input::post('behaelter')) || empty(Input::post('sorten')))
117 197
         {
118
-            return new Response('Missing parameter',500);
198
+            return new Response('Missing parameter',412);
119 199
         }
120 200
 
121 201
         $arrSorten = [];
... ...
@@ -139,14 +219,43 @@ class SlotAjaxController extends AbstractController
139 219
 
140 220
         $Reservation->save();
141 221
 
142
-        return new Response('<p>Reservierung erfolgreich</p>');
222
+        return new Response('<p>Reservierung erfolgreich</p>',200,['HX-Trigger'=> 'updateWaList']);
223
+    }
224
+
225
+    protected function updateReservation()
226
+    {
227
+        if (empty($_REQUEST['id']) || empty(Input::post('behaelter')) || empty(Input::post('sorten')))
228
+        {
229
+            return new Response('Missing parameter',412);
230
+        }
231
+
232
+        if (($Reservation = WeinanlieferungReservationModel::findById($_REQUEST['id'])) === null)
233
+        {
234
+            return new Response('Could not load booking data',500);
235
+        }
236
+
237
+        $arrSorten = [];
238
+        if (!is_array(Input::post('sorten')))
239
+        {
240
+            $arrSorten[] = Input::post('sorten');
241
+        } else {
242
+            $arrSorten = implode(',', Input::post('sorten'));
243
+        }
244
+
245
+        $Reservation->tstamp = time();
246
+        $Reservation->behaelter = Input::post('behaelter');
247
+        $Reservation->sorten = $arrSorten;
248
+
249
+        $Reservation->save();
250
+
251
+        return new Response('<p>Reservierung erfolgreich geändert</p>',200,['HX-Trigger'=> 'updateWaBooking']);
143 252
     }
144 253
 
145
-    protected function deleteBooking()
254
+    protected function deleteReservation()
146 255
     {
147 256
         if (empty($_REQUEST['id']))
148 257
         {
149
-            return new Response('Missing parameter',500);
258
+            return new Response('Missing parameter',412);
150 259
         }
151 260
 
152 261
         /** @var Connection $db */
... ...
@@ -159,7 +268,7 @@ class SlotAjaxController extends AbstractController
159 268
 
160 269
         if ($db->delete('tl_vr_wa_reservation',$arrCriteria))
161 270
         {
162
-            return new Response(null,203);
271
+            return new Response(null,203,['HX-Trigger'=> 'updateWaBooking']);
163 272
         }
164 273
 
165 274
         return new Response('Could not delete',500);
... ...
@@ -48,14 +48,14 @@ class WeinanlieferungBookedListModuleController extends AbstractFrontendModuleCo
48 48
         $arrData = $template->getData();
49 49
 
50 50
         // Get bookings
51
-        if (($bookings = WeinanlieferungReservationModel::findBy("uid",FrontendUser::getInstance()->id)) !== null)
51
+        if (($bookings = WeinanlieferungReservationModel::findBy("uid",FrontendUser::getInstance()->id,['order' => "(SELECT tl_vr_wa_slot.time FROM tl_vr_wa_slot WHERE tl_vr_wa_slot.id=tl_vr_wa_reservation.pid) ASC"])) !== null)
52 52
         {
53 53
             /** @var WeinanlieferungReservationModel $booking */
54 54
             foreach ($bookings as $booking)
55 55
             {
56 56
                 if (($Slot = $booking->getRelated('pid')) !== null)
57 57
                 {
58
-                    $day = new Date($booking->date);
58
+                    $day = new Date($Slot->date);
59 59
                     $arrSorten = [];
60 60
 
61 61
                     if (($Sorten = $booking->getRelated('sorten')) !== null)
... ...
@@ -97,7 +97,7 @@ class WeinanlieferungSlotsModel extends Model
97 97
         return static::findBy($arrColumns,null,$arrOptions);
98 98
     }
99 99
 
100
-    public function getAvailableBehaelter()
100
+    public function getAvailableBehaelter(?int $intOffset=null)
101 101
     {
102 102
         /** @var Connection $db */
103 103
         $db = Controller::getContainer()->get('database_connection');
... ...
@@ -112,6 +112,11 @@ class WeinanlieferungSlotsModel extends Model
112 112
             $intReserved = 0;
113 113
         }
114 114
 
115
+        if ($intOffset > 0)
116
+        {
117
+            $intReserved += $intOffset;
118
+        }
119
+
115 120
         return (int) $this->behaelter - $intReserved;
116 121
     }
117 122
 }