M3: Reorder + Inspiration – Schritt 2 (UI): Planungsliste mit SortableJS, Tagesansicht /mahlzeiten/tage, Inspiration /inspiration mit 'Weitere 5' + 1-Klick-Adopt, Feature-Tests

This commit is contained in:
2026-09-19 17:09:15 +02:00
parent 52a34225fa
commit fa5894426d
9 changed files with 488 additions and 25 deletions
+38 -10
View File
@@ -7,25 +7,53 @@
<div class="row-between">
<div>
<h1 style="margin: 0;">Mahlzeiten</h1>
<div class="muted" style="margin-top: 0.2rem;">Tagesansicht nach Wochentag</div>
<div class="muted" style="margin-top: 0.2rem;">Planungsliste – per Drag &amp; Drop sortieren</div>
</div>
<div class="actions">
<a class="btn" href="{{ path('mahlzeiten_neu') }}">+ Neue Mahlzeit</a>
<a class="btn btn-link" href="{{ path('mahlzeiten_inspiration') }}">Inspiration</a>
<a class="btn btn-link" href="{{ path('mahlzeiten_tage') }}">Tagesansicht</a>
<a class="btn btn-link" href="{{ path('mahlzeiten_archiv') }}">Archiv</a>
</div>
</div>
{% if total == 0 %}
<p class="muted" style="margin-top: 1rem;">Noch keine Mahlzeiten angelegt.</p>
<p class="muted" style="margin-top: 1rem;">Noch keine Mahlzeiten in der Planung.</p>
{% else %}
{% for tag, mahlzeiten in tage %}
<h2 style="margin: 1.25rem 0 0;">{{ tag }}</h2>
<ul class="list">
{% for m in mahlzeiten %}
{{ include('mahlzeiten/_mahlzeit.html.twig', { m: m }) }}
{% endfor %}
</ul>
{% endfor %}
<ul class="list sortierbar">
{% for m in mahlzeiten %}
{{ include('mahlzeiten/_mahlzeit.html.twig', { m: m, sortierbar: true }) }}
{% endfor %}
</ul>
{% endif %}
</div>
{% endblock %}
{% block javascripts %}
<script src="{{ asset('js/sortable.min.js') }}"></script>
<script>
(function () {
const liste = document.querySelector('ul.sortierbar');
if (!liste || typeof Sortable === 'undefined') { return; }
const url = '{{ path("mahlzeiten_reorder") }}';
Sortable.create(liste, {
handle: '.drag-handle',
animation: 150,
ghostClass: 'item-drag',
onEnd: function () {
const ids = Array.prototype.map.call(
liste.querySelectorAll('li[data-id]'),
function (li) { return Number(li.getAttribute('data-id')); }
);
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ids: ids }),
}).then(function (antwort) {
if (!antwort.ok) { window.location.reload(); }
}).catch(function () { window.location.reload(); });
},
});
})();
</script>
{% endblock %}