Files
ephub/templates/admin/resources.html.twig
T

95 lines
4.4 KiB
Twig

{#
Everything bookable, per type and room. Every write opens a modal via htmx and navigates back
here once saved -- the same shape as the sibling apps' admin lists.
Retired resources stay listed, muted, because this is the only place they can be reactivated.
Only an empty room offers "Löschen"; DeleteController refuses the rest regardless. A resource
can always be deleted, taking its bookings with it -- the modal says how many.
#}
{% extends 'layout.html.twig' %}
{% block title %}Ressourcen · E&P Platz{% endblock %}
{% macro opener(url, label, variant = 'neutral') %}
<button type="button" class="button button--small button--{{ variant }}"
hx-get="{{ url }}"
hx-target="body"
hx-swap="beforeend">{{ label }}</button>
{% endmacro %}
{% macro resource_list(resources) %}
{% if resources is empty %}
<p class="py-3 text-sm text-gray-500">Noch nichts angelegt.</p>
{% else %}
<ul class="divide-y divide-gray-200 border-y border-gray-200">
{% for resource in resources %}
<li class="flex items-center justify-between gap-4 py-2" data-resource>
<span class="{{ resource.active ? '' : 'text-gray-400' }}">
{{ resource.label }}
{% if not resource.active %}
<span class="badge bg-gray-100 text-gray-600 ml-1">nicht buchbar</span>
{% endif %}
</span>
<div class="flex gap-2">
{{ _self.opener(path('app_admin_resource_edit', { id: resource.id }), 'Bearbeiten') }}
{{ _self.opener(path('app_admin_resource_delete', { id: resource.id }), 'Löschen') }}
</div>
</li>
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
{% block content %}
<a class="text-sm text-gray-500 hover:text-gray-900" href="{{ path('app_dashboard') }}">← Übersicht</a>
<h1 class="pt-2">Ressourcen</h1>
<p class="subline">Was gebucht werden kann und wo es steht.</p>
{% for section in sections %}
{% set type = section.type %}
<section class="pt-8" data-type="{{ type.value }}">
<div class="flex flex-wrap items-baseline justify-between gap-2">
<h2>{{ type.plural }}</h2>
<div class="flex gap-2">
{{ _self.opener(
path('app_admin_resource_type_notifications', { type: type.value }),
section.recipients > 0 ? 'Benachrichtigungen (' ~ section.recipients ~ ')' : 'Benachrichtigungen'
) }}
{{ _self.opener(path('app_admin_resource_group_new', { type: type.value }), type.groupLabel ~ ' hinzufügen') }}
{{ _self.opener(path('app_admin_resource_new', { type: type.value }), type.label ~ ' hinzufügen', 'primary') }}
</div>
</div>
{% for entry in section.groups %}
<div class="pt-4" data-group>
<div class="flex flex-wrap items-center justify-between gap-2 pb-1">
<h3 class="!mb-0 text-base md:text-base">
{{ entry.group.label }}
</h3>
<div class="flex gap-2">
{{ _self.opener(path('app_admin_resource_group_edit', { id: entry.group.id }), 'Bearbeiten') }}
{% if entry.resources is empty %}
{{ _self.opener(path('app_admin_resource_group_delete', { id: entry.group.id }), 'Löschen') }}
{% endif %}
</div>
</div>
{{ _self.resource_list(entry.resources) }}
</div>
{% endfor %}
{# Only when there is something to show, or when there are no groups at all -- then this
is simply the list, as for the car park. #}
{% if section.ungrouped is not empty or section.groups is empty %}
<div class="pt-4" data-group>
{% if section.groups is not empty %}
<h3 class="!mb-0 pb-1 text-base md:text-base">Ohne {{ type.groupLabel }}</h3>
{% endif %}
{{ _self.resource_list(section.ungrouped) }}
</div>
{% endif %}
</section>
{% endfor %}
{% endblock %}