feat: let managers edit the staffing matrix

This commit is contained in:
fromme committed 2026-11-05 17:18:26 +01:00
1 parent f9d2ff084d
commit 4ff963d1e2
15 files changed
+84 -52

No files matched your search

@@ -1,16 +0,0 @@
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
<div class="flex flex-col space-y-4 pb-8">
{{ form_row(form.productCode) }}
{{ form_row(form.guides) }}
{{ form_row(form.skiBeginner) }}
{{ form_row(form.splitBeginner) }}
{{ form_row(form.skiAdvanced) }}
{{ form_row(form.splitAdvanced) }}
{{ form_row(form.guiding) }}
{{ form_row(form.enabled) }}
</div>
<button type="submit" class="btn">
Speichern
</button>
{{ form_rest(form) }}
{{ form_end(form) }}
@@ -1,90 +0,0 @@
{% extends 'admin/layout.html.twig' %}
{% block title %}Einstellungen - Besetzungsmatrix{% endblock %}
{% macro yes_no(value) %}{{ value ? 'ja' : '-' }}{% endmacro %}
{% block content %}
<div class="flex items-center justify-between pb-8">
<h1 class="text-2xl font-bold">
Besetzungsmatrix
</h1>
<a href="{{ path('app_admin_system_staffing_rule_preview') }}" class="btn">
Vorschau
</a>
</div>
<p class="pb-4">
Für jeden künftigen Termin eines aktiven Produkts legt der Einsatz-Generator die Einsätze als
Entwurf an. Termine, die schon einmal Einsätze hatten, bleiben unberührt. Die Busbegleitung
ergibt sich aus den Zustiegen des Termins: Hat er welche, ist der erste vorausgewählt.
</p>
<div class="data-table-wrapper">
<div class="data-table-wrapper__inner">
<table class="data-table">
<thead>
<tr>
<th>Produkt</th>
<th>Reiseleitungen</th>
<th>Ski Anfänger:innen</th>
<th>Ski Fortgeschrittene</th>
<th>Split</th>
<th>Guiding</th>
<th>aktiv</th>
<th></th>
</tr>
</thead>
<tbody>
{% for rule in rules %}
<tr>
<td>{{ rule.productCode }}</td>
<td>{{ rule.guides }}</td>
<td>{{ _self.yes_no(rule.skiBeginner) }}</td>
<td>{{ _self.yes_no(rule.skiAdvanced) }}</td>
<td>
{%- set split = [] -%}
{%- if rule.splitBeginner %}{% set split = split|merge(['Anfänger:innen']) %}{% endif -%}
{%- if rule.splitAdvanced %}{% set split = split|merge(['Fortgeschrittene']) %}{% endif -%}
{{- split is empty ? _self.yes_no(false) : split|join(', ') -}}
</td>
<td>{{ _self.yes_no(rule.guiding) }}</td>
<td>{{ _self.yes_no(rule.enabled) }}</td>
<td>
<div class="flex items-center space-x-2 justify-end">
<button type="button"
class="text-red-500"
title="Zeile löschen"
hx-get="{{ path('app_admin_system_staffing_rule_delete', { 'uuid': rule.uuid }) }}"
hx-target="body"
hx-swap="beforeend">
{{ icon('delete') }}
</button>
<button type="button"
title="Zeile bearbeiten"
hx-get="{{ path('app_admin_system_staffing_rule_edit', { 'uuid': rule.uuid }) }}"
hx-target="body"
hx-swap="beforeend">
{{ icon('edit') }}
</button>
</div>
</td>
</tr>
{% else %}
<tr>
<td colspan="8">
Keine Daten...
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<button type="button"
class="btn"
title="Zeile hinzufügen"
hx-get="{{ path('app_admin_system_staffing_rule_create') }}"
hx-target="body"
hx-swap="beforeend">
Zeile hinzufügen
</button>
{% endblock %}
@@ -1,7 +0,0 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Zeile hinzufügen{% endblock %}
{% block content %}
{% include 'admin/system/staffing_rule/_form.html.twig' %}
{% endblock %}
@@ -1,8 +0,0 @@
{% extends 'htmx_confirmation_modal.html.twig' %}
{% block content %}
<div>
Möchtest du die Zeile <em>{{ rule.productCode }}</em> wirklich aus der Besetzungsmatrix löschen?
Bereits angelegte Einsätze bleiben erhalten.
</div>
{% endblock %}
@@ -1,7 +0,0 @@
{% extends 'htmx_modal.html.twig' %}
{% block title %}Zeile bearbeiten{% endblock %}
{% block content %}
{% include 'admin/system/staffing_rule/_form.html.twig' %}
{% endblock %}
@@ -1,78 +0,0 @@
{% extends 'admin/layout.html.twig' %}
{% block title %}Einstellungen - Besetzungsmatrix - Vorschau{% endblock %}
{% block content %}
<div class="flex items-center justify-between pb-8">
<h1 class="text-2xl font-bold">
Besetzungsmatrix – Vorschau
</h1>
<div class="flex items-center space-x-2">
<a href="{{ path('app_admin_system_staffing_rule_index') }}" class="btn">
Zurück zur Matrix
</a>
<a href="{{ path('app_admin_system_staffing_rule_export') }}" class="btn">
Excel-Export
</a>
</div>
</div>
<p class="pb-4">
Alle künftigen Termine der Produkte in der Matrix, auch inaktive Zeilen. Angelegt wird nur,
was hier als „wird angelegt" steht.
</p>
<div class="data-table-wrapper">
<div class="data-table-wrapper__inner">
<table class="data-table">
<thead>
<tr>
<th>Produkt</th>
<th>Termin</th>
<th>Reisedatum</th>
<th>Status</th>
<th>Einsätze</th>
</tr>
</thead>
<tbody>
{% for row in pagination %}
<tr>
<td>{{ row.productCode }}</td>
<td>
{{ row.code }}
<br>
<span class="text-sm text-gray-500">{{ row.product }}</span>
</td>
<td class="whitespace-nowrap">
{{ row.dateFrom|date('d.m.Y') }} – {{ row.dateTo|date('d.m.Y') }}
</td>
<td class="whitespace-nowrap">{{ row.status }}</td>
<td>
<ul>
{% for assignment in row.assignments %}
<li>
{{ assignment.places }}× {{ assignment.jobProfile }}
{% if assignment.pickup %}
<span class="text-sm text-gray-500">– Busbegleitung ab {{ assignment.pickup }}</span>
{% endif %}
{% if assignment.fees %}
<span class="text-sm text-gray-500">– {{ assignment.fees }}</span>
{% endif %}
</li>
{% else %}
<li>-</li>
{% endfor %}
</ul>
</td>
</tr>
{% else %}
<tr>
<td colspan="5">
Keine Termine – die Matrix ist leer, oder keiner ihrer Produktcodes hat künftige Termine.
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ knp_pagination_render(pagination) }}
</div>
</div>
{% endblock %}