116 lines
4.6 KiB
Twig
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 %}
|