Files
myep-team/templates/admin/teamer/mailing.html.twig
T

116 lines
4.6 KiB
Twig

{% extends 'administrative/layout.html.twig' %}
{% block title %}Mailing{% endblock %}
{% block content %}
<div class="flex items-start justify-between pb-4">
<h1 class="text-2xl font-bold">
Mailing an das Team
</h1>
<a href="{{ returnUrl }}" class="btn btn--small btn--secondary shrink-0">
Zurück zur Teamübersicht
</a>
</div>
<div class="pb-6">
{{ include('admin/teamer/_mailing_filter_summary.html.twig', { 'filterDto': filterDto }) }}
</div>
<div class="pb-6">
<div class="text-xl font-bold">
{{ recipients.eligibleCount }} Empfänger:innen
</div>
{% if recipients.hasSkipped %}
<div class="text-sm text-gray-500">
{{ include('admin/teamer/_mailing_skipped.html.twig', { 'recipients': recipients }) }}
</div>
{% endif %}
</div>
{# One request per keystroke parks the draft - so that a trip to the filter and back
keeps it - and answers with the preview, which is why the response is swapped into
the pane instead of being thrown away. hx-trigger replaces htmx' default submit
trigger, the "Vorschau an mich senden" button still posts natively.
Deliberately without htmx' "changed" modifier: it compares the listening element's
.value between events, and a <form> has none, so every event compares undefined to
undefined and the request is never sent. The 500ms delay is what keeps the typing
from flooding the route. #}
{{ form_start(form, { 'attr': {
'id': 'mailing-form',
'hx-post': path('app_admin_teamer_mailing_draft'),
'hx-trigger': 'input delay:500ms',
'hx-target': '#mailing-preview',
'hx-swap': 'innerHTML',
'hx-indicator': '#mailing-preview-indicator',
} }) }}
<div class="grid lg:grid-cols-2 gap-8 items-start">
<div>
<div class="flex flex-col space-y-4 pb-4">
{{ form_row(form.subject) }}
{{ form_row(form.message) }}
</div>
<div class="pb-6">
{{ include('_partials/_markdown_hint.html.twig') }}
</div>
<div class="pb-8 text-sm text-gray-500">
<div class="pb-2">
Platzhalter für Betreff und Nachricht, sie werden beim Senden pro Person ersetzt:
</div>
<div class="flex flex-wrap gap-2">
{% for placeholder, label in placeholders %}
<span class="inline-flex items-center space-x-1 py-1 px-2 bg-gray-50 border border-gray-200 rounded">
<code>{{ placeholder }}</code>
<span>{{ label }}</span>
</span>
{% endfor %}
</div>
</div>
</div>
<div class="lg:sticky lg:top-4">
<div class="font-bold pb-2">
Vorschau
</div>
<div class="relative">
<div id="mailing-preview">
{{ include('admin/teamer/_mailing_preview.html.twig', preview) }}
</div>
{# Deliberately a sibling of the swap target, not a child: hx-swap replaces
the target's contents, which would carry the indicator away with them. #}
<div class="htmx-indicator absolute inset-0 bg-white/75 flex items-center justify-center"
id="mailing-preview-indicator">
{{ include('_partials/_spinner.html.twig', { 'class': 'w-8 h-8' }) }}
</div>
</div>
</div>
</div>
<div class="flex items-center space-x-2">
{# nobody to write to means there is nothing to confirm, only the preview stays useful #}
{% if recipients.eligibleCount > 0 %}
<button type="button"
class="btn"
hx-post="{{ path('app_admin_teamer_mailing_confirm') }}"
hx-include="closest form"
hx-target="body"
hx-swap="beforeend">
{{ icon('mail', 'w-4 h-4 shrink-0') }}
<span>Senden</span>
</button>
{% endif %}
<button type="submit" class="btn btn--secondary">
Vorschau an mich senden
</button>
{% if hasDraft %}
<a href="{{ path('app_admin_teamer_mailing_discard') }}" class="btn btn--secondary">
Entwurf verwerfen
</a>
{% endif %}
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
{% endblock %}