Browse code

Sticky headers in backend reservation view

Benjamin Roth authored on01/09/2025 15:35:59
Showing2 changed files
... ...
@@ -74,186 +74,190 @@
74 74
                 {% if days is defined and days|length %}
75 75
                     <div class="list">
76 76
                         {% for day,standorte in days %}
77
-                            <h3 class="tl_folder_list px-1 text-lg text-primary mt-2">{{ day|date('d.m.Y') }}</h3>
78
-                            {% for standort in standorte %}
79
-                                {% for time,bookings in standort.times %}
80
-                                    <h3 class="tl_folder_list row u-items-center">
81
-                                        <div class="col-2 offset-1">
82
-                                            <div class="t-label">Uhrzeit</div>
83
-                                            {{ time|date('H:i') }}
84
-                                        </div>
85
-                                        <div class="col-2">
86
-                                            <div class="t-label">Standort</div>
87
-                                            {{ standort.standort }}
88
-                                        </div>
89
-                                        <div class="col-2">
90
-                                            <div class="t-label">Verfügbare Behälterkapazität</div>
91
-                                            {{ bookings.behaelterAvailable }}
92
-                                        </div>
93
-                                        <div class="col px-1">
94
-                                            <div class="t-label">Verarbeitete Sorten</div>
95
-                                            {{ bookings.sorten|join(', ') }}
96
-                                        </div>
97
-                                    </h3>
98
-                                    <div class="bookings u-row-striped">
99
-                                        {% for booking in bookings.items %}
100
-                                            {% if booking.approved == '1' %}
101
-                                                {% set status = 'approved' %}
102
-                                            {% elseif booking.approved == '0' %}
103
-                                                {% set status = 'canceled' %}
104
-                                            {% else %}
105
-                                                {% set status = 'pending' %}
106
-                                            {% endif %}
107
-                                            {% if booking.checked_in == '1' %}
108
-                                                {% set checkin_state = 'checked_in' %}
109
-                                            {% else %}
110
-                                                {% set checkin_state = 'pending' %}
111
-                                            {% endif %}
112
-                                            <div class="row u-items-flex-start my-1 status status--{{ status }} checkin--{{ checkin_state }}">
113
-                                                <div class="col-11 m-0">
114
-                                                    <div class="row u-items-flex-start pt-0">
115
-                                                        <div class="col-1">
116
-                                                            <i class="status-icon" title="{{ ('MSC.wa_approval_status.'~status)|trans([], 'contao_default') }}">{{ ('MSC.wa_approval_status.'~status)|trans([], 'contao_default') }}</i>
117
-                                                            <i class="toggle-icon" title="Details ein-/ausblenden"></i>
118
-                                                        </div>
119
-                                                        <div class="col-4 rebsorten icon-reben-outline">
120
-                                                            <div class="t-label">Mitglied</div>
121
-                                                            {% if booking.member is not null %}
122
-                                                                <div>
123
-                                                                    {% if booking.member.memberno is defined %}
124
-                                                                        <span>{{ booking.member.memberno }}</span>{% endif %}
125
-                                                                    <span>{{ booking.member.firstname }} {{ booking.member.lastname }}</span>
126
-                                                                    {% if booking.member.phone is defined %}
127
-                                                                        <span>{{ booking.member.phone }}</span>{% endif %}
128
-                                                                </div>
129
-                                                            {% endif %}
130
-                                                        </div>
131
-                                                        <div class="col-4 behaelter icon-behaelter-outline">
132
-                                                            <div class="t-label">Anliefernde Sorten</div>
133
-                                                            {{ booking.sorte|join(', ') }}
134
-                                                        </div>
135
-                                                        <div class="col-3 behaelter icon-behaelter-outline">
136
-                                                            <div class="t-label">Gebuchte Behälterkapazität</div>
137
-                                                            {{ booking.behaelter }}
138
-                                                        </div>
139
-                                                        <div class="additional-facts col-12 p-0 m-0">
140
-                                                            <div class="row u-items-flex-start pb-0">
77
+                            <div class="day-list">
78
+                                <h3 class="tl_folder_list px-1 text-lg text-primary mt-2 day-sticky">{{ day|date('d.m.Y') }}</h3>
79
+                                {% for standort in standorte %}
80
+                                    {% for time,bookings in standort.times %}
81
+                                        <div class="time-list">
82
+                                            <h3 class="tl_folder_list row u-items-center time-sticky">
83
+                                                <div class="col-2 offset-1">
84
+                                                    <div class="t-label">Uhrzeit</div>
85
+                                                    {{ time|date('H:i') }}
86
+                                                </div>
87
+                                                <div class="col-2">
88
+                                                    <div class="t-label">Standort</div>
89
+                                                    {{ standort.standort }}
90
+                                                </div>
91
+                                                <div class="col-2">
92
+                                                    <div class="t-label">Verfügbare Behälterkapazität</div>
93
+                                                    {{ bookings.behaelterAvailable }}
94
+                                                </div>
95
+                                                <div class="col px-1">
96
+                                                    <div class="t-label">Verarbeitete Sorten</div>
97
+                                                    {{ bookings.sorten|join(', ') }}
98
+                                                </div>
99
+                                            </h3>
100
+                                            <div class="bookings u-row-striped">
101
+                                                {% for booking in bookings.items %}
102
+                                                    {% if booking.approved == '1' %}
103
+                                                        {% set status = 'approved' %}
104
+                                                    {% elseif booking.approved == '0' %}
105
+                                                        {% set status = 'canceled' %}
106
+                                                    {% else %}
107
+                                                        {% set status = 'pending' %}
108
+                                                    {% endif %}
109
+                                                    {% if booking.checked_in == '1' %}
110
+                                                        {% set checkin_state = 'checked_in' %}
111
+                                                    {% else %}
112
+                                                        {% set checkin_state = 'pending' %}
113
+                                                    {% endif %}
114
+                                                    <div class="row u-items-flex-start my-1 status status--{{ status }} checkin--{{ checkin_state }}">
115
+                                                        <div class="col-11 m-0">
116
+                                                            <div class="row u-items-flex-start pt-0">
141 117
                                                                 <div class="col-1">
142
-                                                                    <i>{{ ('MSC.wa_checkin_status.'~checkin_state)|trans([], 'contao_default') }}</i>
118
+                                                                    <i class="status-icon" title="{{ ('MSC.wa_approval_status.'~status)|trans([], 'contao_default') }}">{{ ('MSC.wa_approval_status.'~status)|trans([], 'contao_default') }}</i>
119
+                                                                    <i class="toggle-icon" title="Details ein-/ausblenden"></i>
143 120
                                                                 </div>
144 121
                                                                 <div class="col-4 rebsorten icon-reben-outline">
145
-                                                                    {% if booking.member.email is defined %}
122
+                                                                    <div class="t-label">Mitglied</div>
123
+                                                                    {% if booking.member is not null %}
146 124
                                                                         <div>
147
-                                                                        <a href="mailto:{{ booking.member.email }}">{{ booking.member.email }}</a>
125
+                                                                            {% if booking.member.memberno is defined %}
126
+                                                                                <span>{{ booking.member.memberno }}</span>{% endif %}
127
+                                                                            <span>{{ booking.member.firstname }} {{ booking.member.lastname }}</span>
128
+                                                                            {% if booking.member.phone is defined %}
129
+                                                                                <span>{{ booking.member.phone }}</span>{% endif %}
148 130
                                                                         </div>
149 131
                                                                     {% endif %}
150 132
                                                                 </div>
151 133
                                                                 <div class="col-4 behaelter icon-behaelter-outline">
152
-                                                                    <div class="t-label">Lage</div>
153
-                                                                    {{ booking.lage|join(', ') }}
134
+                                                                    <div class="t-label">Anliefernde Sorten</div>
135
+                                                                    {{ booking.sorte|join(', ') }}
154 136
                                                                 </div>
155 137
                                                                 <div class="col-3 behaelter icon-behaelter-outline">
156
-                                                                    <div class="t-label">Ernteart</div>
157
-                                                                    {{ booking.ernteart|join(', ') }}
138
+                                                                    <div class="t-label">Gebuchte Behälterkapazität</div>
139
+                                                                    {{ booking.behaelter }}
158 140
                                                                 </div>
159
-                                                                {% if booking.checked_in %}
160
-                                                                    <div class="col-1"> </div>
161
-                                                                    <div class="col-10 behaelter_nummern">
162
-                                                                        <div class="t-label">Eingecheckte Behälternummern</div>
163
-                                                                        {% for behaelter in booking.behaelter_numbers %}
164
-                                                                            {% if loop.index != 1 %}, {% endif %}{{ behaelter.behaelter }} [M:{{ behaelter.member }}]
165
-                                                                        {% endfor %}
141
+                                                                <div class="additional-facts col-12 p-0 m-0">
142
+                                                                    <div class="row u-items-flex-start pb-0">
143
+                                                                        <div class="col-1">
144
+                                                                            <i>{{ ('MSC.wa_checkin_status.'~checkin_state)|trans([], 'contao_default') }}</i>
145
+                                                                        </div>
146
+                                                                        <div class="col-4 rebsorten icon-reben-outline">
147
+                                                                            {% if booking.member.email is defined %}
148
+                                                                                <div>
149
+                                                                                <a href="mailto:{{ booking.member.email }}">{{ booking.member.email }}</a>
150
+                                                                                </div>
151
+                                                                            {% endif %}
152
+                                                                        </div>
153
+                                                                        <div class="col-4 behaelter icon-behaelter-outline">
154
+                                                                            <div class="t-label">Lage</div>
155
+                                                                            {{ booking.lage|join(', ') }}
156
+                                                                        </div>
157
+                                                                        <div class="col-3 behaelter icon-behaelter-outline">
158
+                                                                            <div class="t-label">Ernteart</div>
159
+                                                                            {{ booking.ernteart|join(', ') }}
160
+                                                                        </div>
161
+                                                                        {% if booking.checked_in %}
162
+                                                                            <div class="col-1"> </div>
163
+                                                                            <div class="col-10 behaelter_nummern">
164
+                                                                                <div class="t-label">Eingecheckte Behälternummern</div>
165
+                                                                                {% for behaelter in booking.behaelter_numbers %}
166
+                                                                                    {% if loop.index != 1 %}, {% endif %}{{ behaelter.behaelter }} [M:{{ behaelter.member }}]
167
+                                                                                {% endfor %}
168
+                                                                            </div>
169
+                                                                        {% endif %}
166 170
                                                                     </div>
167
-                                                                {% endif %}
168
-                                                            </div>
169
-                                                            {% if booking.upload_file %}
170
-                                                            <div class="row u-items-flex-start pt-0">
171
-                                                                <div class="col-1"></div>
172
-                                                                <div class="col-11 icon-file-outline">
173
-                                                                    <div class="t-label">Datei</div>
174
-                                                                    <a href="{{ booking.upload_file.popup_href }}" onclick="Backend.openModalIframe({'title':'{{ booking.upload_file.popup_title|e('js') }}','url':this.href});return false">{{ booking.upload_file.name }}</a>
171
+                                                                    {% if booking.upload_file %}
172
+                                                                    <div class="row u-items-flex-start pt-0">
173
+                                                                        <div class="col-1"></div>
174
+                                                                        <div class="col-11 icon-file-outline">
175
+                                                                            <div class="t-label">Datei</div>
176
+                                                                            <a href="{{ booking.upload_file.popup_href }}" onclick="Backend.openModalIframe({'title':'{{ booking.upload_file.popup_title|e('js') }}','url':this.href});return false">{{ booking.upload_file.name }}</a>
177
+                                                                        </div>
178
+                                                                    </div>
179
+                                                                    {% endif %}
175 180
                                                                 </div>
176 181
                                                             </div>
177
-                                                            {% endif %}
182
+                                                        </div>
183
+                                                        <div class="col u-text-right action">
184
+                                                            <a
185
+                                                                href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=edit&id={{ booking.id }}&rt={{ request_token }}&ref={{ ref }}"
186
+                                                                {#                        onclick="Backend.openModalIframe({'title':'Quellelement ID {{ booking.id }} bearbeiten','url':this.href});return false" #}
187
+                                                                title="Element ID {{ booking.id }} bearbeiten"
188
+                                                            ><img src="/system/themes/flexible/icons/edit.svg" width="16" height="16" alt="Element ID {{ booking.id }} bearbeiten"></a>
189
+                                                            <a
190
+                                                                href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=delete&id={{ booking.id }}&rt={{ request_token }}"
191
+                                                                onclick="if(!confirm('Soll das Element ID {{ booking.id }} wirklich gelöscht werden?'))return false;Backend.getScrollOffset()"
192
+                                                                title="Element ID {{ booking.id }} löschen"
193
+                                                            ><img src="/system/themes/flexible/icons/delete.svg" width="16" height="16" alt="Element ID {{ booking.id }} löschen"></a>
178 194
                                                         </div>
179 195
                                                     </div>
180
-                                                </div>
181
-                                                <div class="col u-text-right action">
182
-                                                    <a
183
-                                                        href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=edit&id={{ booking.id }}&rt={{ request_token }}&ref={{ ref }}"
184
-                                                        {#                        onclick="Backend.openModalIframe({'title':'Quellelement ID {{ booking.id }} bearbeiten','url':this.href});return false" #}
185
-                                                        title="Element ID {{ booking.id }} bearbeiten"
186
-                                                    ><img src="/system/themes/flexible/icons/edit.svg" width="16" height="16" alt="Element ID {{ booking.id }} bearbeiten"></a>
187
-                                                    <a
188
-                                                        href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=delete&id={{ booking.id }}&rt={{ request_token }}"
189
-                                                        onclick="if(!confirm('Soll das Element ID {{ booking.id }} wirklich gelöscht werden?'))return false;Backend.getScrollOffset()"
190
-                                                        title="Element ID {{ booking.id }} löschen"
191
-                                                    ><img src="/system/themes/flexible/icons/delete.svg" width="16" height="16" alt="Element ID {{ booking.id }} löschen"></a>
192
-                                                </div>
196
+                                                    {#<div class="row u-items-flex-start my-1 status status--{{ status }}">
197
+                                                        <div class="col-1">
198
+                                                            <i class="status-icon" title="{{ ('MSC.wa_approval_status.'~status)|trans([], 'contao_default') }}">{{ ('MSC.wa_approval_status.'~status)|trans([], 'contao_default') }}</i>
199
+                                                        </div>
200
+                                                        <div class="col-2 time icon-uhr-outline">
201
+                                                            <div class="t-label">Uhrzeit</div>
202
+                                                            {{ booking.slot.time|date('H:i') }}
203
+                                                            <div class="t-label">Standort</div>
204
+                                                            {{ booking.standort }}
205
+                                                        </div>
206
+                                                        <div class="col-2 behaelter icon-behaelter-outline">
207
+                                                            <div class="t-label">Gebuchte Behälterkapazität</div>
208
+                                                            {{ booking.behaelter }}
209
+                                                            <div class="t-label">Ernteart</div>
210
+                                                            {{ booking.ernteart|join(', ') }}
211
+                                                        </div>
212
+                                                        <div class="col-2 behaelter icon-behaelter-outline">
213
+                                                            <div class="t-label">Anliefernde Sorten</div>
214
+                                                            {{ booking.sorte|join(', ') }}
215
+                                                            <div class="t-label">Lage</div>
216
+                                                            {{ booking.lage|join(', ') }}
217
+                                                        </div>
218
+                                                        <div class="col-3 rebsorten icon-reben-outline">
219
+                                                            <div class="t-label">Mitglied</div>
220
+                                                            {% if booking.member is not null %}
221
+                                                                {% if booking.member.memberno is defined %}
222
+                                                                    <div>{{ booking.member.memberno }}</div>{% endif %}
223
+                                                                <div>{{ booking.member.firstname }} {{ booking.member.lastname }}</div>
224
+                                                                {% if booking.member.phone is defined %}
225
+                                                                    <div>{{ booking.member.phone }}</div>{% endif %}
226
+                                                                {% if booking.member.email is defined %}
227
+                                                                    <div>
228
+                                                                    <a href="mailto:{{ booking.member.email }}">{{ booking.member.email }}</a>
229
+                                                                    </div>{% endif %}
230
+                                                            {% endif %}
231
+                                                        </div>
232
+                                                        {% if booking.checked_in %}
233
+                                                            <div class="col-1">
234
+                                                            </div>
235
+                                                            <div class="col-10 behaelter_nummern">
236
+                                                                <div class="t-label">Eingecheckte Behälternummern</div>
237
+                                                                {% for behaelter in booking.behaelter_numbers %}
238
+                                                                    {% if loop.index != 1 %}, {% endif %}{{ behaelter.behaelter }} [M:{{ behaelter.member }}]
239
+                                                                {% endfor %}
240
+                                                            </div>
241
+                                                        {% endif %}
242
+                                                        <div class="col px-1 u-text-right action">
243
+                                                            <a
244
+                                                                href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=edit&id={{ booking.id }}&rt={{ request_token }}&ref={{ ref }}"
245
+                                                                #}{#                        onclick="Backend.openModalIframe({'title':'Quellelement ID {{ booking.id }} bearbeiten','url':this.href});return false" #}{#
246
+                                                                title="Element ID {{ booking.id }} bearbeiten"
247
+                                                            ><img src="/system/themes/flexible/icons/edit.svg" width="16" height="16" alt="Element ID {{ booking.id }} bearbeiten"></a>
248
+                                                            <a
249
+                                                                href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=delete&id={{ booking.id }}&rt={{ request_token }}"
250
+                                                                onclick="if(!confirm('Soll das Element ID {{ booking.id }} wirklich gelöscht werden?'))return false;Backend.getScrollOffset()"
251
+                                                                title="Element ID {{ booking.id }} löschen"
252
+                                                            ><img src="/system/themes/flexible/icons/delete.svg" width="16" height="16" alt="Element ID {{ booking.id }} löschen"></a>
253
+                                                        </div>
254
+                                                    </div>#}
255
+                                                {% endfor %}
193 256
                                             </div>
194
-                                            {#<div class="row u-items-flex-start my-1 status status--{{ status }}">
195
-                                                <div class="col-1">
196
-                                                    <i class="status-icon" title="{{ ('MSC.wa_approval_status.'~status)|trans([], 'contao_default') }}">{{ ('MSC.wa_approval_status.'~status)|trans([], 'contao_default') }}</i>
197
-                                                </div>
198
-                                                <div class="col-2 time icon-uhr-outline">
199
-                                                    <div class="t-label">Uhrzeit</div>
200
-                                                    {{ booking.slot.time|date('H:i') }}
201
-                                                    <div class="t-label">Standort</div>
202
-                                                    {{ booking.standort }}
203
-                                                </div>
204
-                                                <div class="col-2 behaelter icon-behaelter-outline">
205
-                                                    <div class="t-label">Gebuchte Behälterkapazität</div>
206
-                                                    {{ booking.behaelter }}
207
-                                                    <div class="t-label">Ernteart</div>
208
-                                                    {{ booking.ernteart|join(', ') }}
209
-                                                </div>
210
-                                                <div class="col-2 behaelter icon-behaelter-outline">
211
-                                                    <div class="t-label">Anliefernde Sorten</div>
212
-                                                    {{ booking.sorte|join(', ') }}
213
-                                                    <div class="t-label">Lage</div>
214
-                                                    {{ booking.lage|join(', ') }}
215
-                                                </div>
216
-                                                <div class="col-3 rebsorten icon-reben-outline">
217
-                                                    <div class="t-label">Mitglied</div>
218
-                                                    {% if booking.member is not null %}
219
-                                                        {% if booking.member.memberno is defined %}
220
-                                                            <div>{{ booking.member.memberno }}</div>{% endif %}
221
-                                                        <div>{{ booking.member.firstname }} {{ booking.member.lastname }}</div>
222
-                                                        {% if booking.member.phone is defined %}
223
-                                                            <div>{{ booking.member.phone }}</div>{% endif %}
224
-                                                        {% if booking.member.email is defined %}
225
-                                                            <div>
226
-                                                            <a href="mailto:{{ booking.member.email }}">{{ booking.member.email }}</a>
227
-                                                            </div>{% endif %}
228
-                                                    {% endif %}
229
-                                                </div>
230
-                                                {% if booking.checked_in %}
231
-                                                    <div class="col-1">
232
-                                                    </div>
233
-                                                    <div class="col-10 behaelter_nummern">
234
-                                                        <div class="t-label">Eingecheckte Behälternummern</div>
235
-                                                        {% for behaelter in booking.behaelter_numbers %}
236
-                                                            {% if loop.index != 1 %}, {% endif %}{{ behaelter.behaelter }} [M:{{ behaelter.member }}]
237
-                                                        {% endfor %}
238
-                                                    </div>
239
-                                                {% endif %}
240
-                                                <div class="col px-1 u-text-right action">
241
-                                                    <a
242
-                                                        href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=edit&id={{ booking.id }}&rt={{ request_token }}&ref={{ ref }}"
243
-                                                        #}{#                        onclick="Backend.openModalIframe({'title':'Quellelement ID {{ booking.id }} bearbeiten','url':this.href});return false" #}{#
244
-                                                        title="Element ID {{ booking.id }} bearbeiten"
245
-                                                    ><img src="/system/themes/flexible/icons/edit.svg" width="16" height="16" alt="Element ID {{ booking.id }} bearbeiten"></a>
246
-                                                    <a
247
-                                                        href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=delete&id={{ booking.id }}&rt={{ request_token }}"
248
-                                                        onclick="if(!confirm('Soll das Element ID {{ booking.id }} wirklich gelöscht werden?'))return false;Backend.getScrollOffset()"
249
-                                                        title="Element ID {{ booking.id }} löschen"
250
-                                                    ><img src="/system/themes/flexible/icons/delete.svg" width="16" height="16" alt="Element ID {{ booking.id }} löschen"></a>
251
-                                                </div>
252
-                                            </div>#}
253
-                                        {% endfor %}
254
-                                    </div>
257
+                                        </div>
258
+                                    {% endfor %}
255 259
                                 {% endfor %}
256
-                            {% endfor %}
260
+                            </div>
257 261
                         {% endfor %}
258 262
                     </div>
259 263
                 {% else %}
... ...
@@ -6398,3 +6398,9 @@
6398 6398
 .additional-facts.show {
6399 6399
   display: block;
6400 6400
 }
6401
+
6402
+.day-list{position:relative}
6403
+.day-list>.day-sticky{position:sticky;top:0;z-index:5;box-shadow:0 1px 0 rgba(0,0,0,.05)}
6404
+/* Nested sticky header for time blocks */
6405
+.time-list{position:relative}
6406
+.time-list>.time-sticky{position:sticky;top:2.25rem; /* sits below day header */ z-index:4;box-shadow:0 1px 0 rgba(0,0,0,.04)}