src/StartPlatz/Bundle/EventBundle/Resources/views/Default/_registration.batch.tailwind.html.twig line 1

Open in your IDE?
  1. {# Registration Section - Tailwind Version #}
  2. {# Defaults definiert in event-single.tailwind.html.twig (styles block) #}
  3. <section id="{% if lang == 'en' or isEnglish %}registration{% else %}anmeldung{% endif %}" class="bg-registration registration-accent py-12">
  4.     <div class="max-w-4xl mx-auto px-4">
  5.         {# Batch ist Source of Truth fuer Preis und Steuerverhalten (event.priceInEuroCent ist Legacy). #}
  6.         {% set displayPrice = null %}
  7.         {% set isTaxIncluded = false %}
  8.         {% set isFreeForKiCampus = false %}
  9.         {% set isFreeForCommunity = false %}
  10.         {% if batch and batch.priceInEuroCent %}
  11.             {% set displayPrice = batch.priceInEuroCent %}
  12.             {% set isTaxIncluded = batch.taxBehavior == 'inclusive' %}
  13.             {% set isFreeForKiCampus = batch.isFreeForKiCampus %}
  14.             {% set isFreeForCommunity = batch.isFreeForCommunity %}
  15.         {% elseif event is defined and event and event.priceInEuroCent %}
  16.             {% set displayPrice = event.priceInEuroCent %}
  17.             {% set isTaxIncluded = event.isTaxIncluded %}
  18.             {% set isFreeForKiCampus = event.isFreeForKiCampus %}
  19.             {% set isFreeForCommunity = event.isFreeForCommunity %}
  20.         {% endif %}
  21.         {# --- Registrierungs-Header --- #}
  22.         {% if event is defined %}
  23.         {% if batch.registrationHeadline %}
  24.             {# Custom Header: ersetzt Standard-Details-Box und Free-Access-Boxen #}
  25.             <div class="text-center mb-8">
  26.                 <h2 class="text-white text-3xl lg:text-4xl font-bold mb-3">{{ batch.registrationHeadline }}</h2>
  27.                 {% if batch.registrationSubtitle %}
  28.                     <p class="text-white/80 text-lg">{{ batch.registrationSubtitle|raw }}</p>
  29.                 {% endif %}
  30.             </div>
  31.         {% else %}
  32.             {# Event Details Box #}
  33.             <div class="bg-white/10 backdrop-blur rounded-xl p-4 mb-6">
  34.                 <div class="flex flex-wrap justify-between gap-4 text-white">
  35.                     {# When #}
  36.                     <div class="flex items-center gap-2">
  37.                         <span class="text-xl">&#128197;</span>
  38.                         <div>
  39.                             <strong>{% if isEnglish %}When:{% else %}Wann:{% endif %}</strong>
  40.                             {% if isMultiBatchEvent and batch and batch.startDate %}
  41.                                 {{ batch.startDate|date('d.m.Y H:i') }}{% if batch.endDate %} - {{ batch.endDate|date('H:i') }} Uhr{% endif %}
  42.                             {% elseif event.startDate %}
  43.                                 {{ event.startDate|date('d.m.Y H:i') }}{% if event.endDate %} - {{ event.endDate|date('H:i') }} Uhr{% endif %}
  44.                             {% endif %}
  45.                         </div>
  46.                     </div>
  47.                     {# Where #}
  48.                     <div class="flex items-center gap-2">
  49.                         <span class="text-xl">&#128205;</span>
  50.                         <div>
  51.                             <strong>{% if isEnglish %}Where:{% else %}Wo:{% endif %}</strong>
  52.                             {% if event.location %}{{ event.location }}{% elseif event.isOnline %}Online{% else %}STARTPLATZ{% endif %}
  53.                         </div>
  54.                     </div>
  55.                     {# Fee #}
  56.                     {% if displayPrice is not null %}
  57.                         <div class="flex items-center gap-2">
  58.                             <span class="text-xl">&#128176;</span>
  59.                             <div>
  60.                                 <strong>{% if isEnglish %}Fee:{% else %}Gebuehr:{% endif %}</strong>
  61.                                 {% if displayPrice == 0 %}
  62.                                     {% if isEnglish %}free{% else %}kostenlos{% endif %}
  63.                                 {% else %}
  64.                                     {{ (displayPrice/100)|number_format(2, ',', '.') }} EUR
  65.                                     {% if isTaxIncluded %}{% if isEnglish %}incl. VAT{% else %}inkl. MwSt.{% endif %}{% else %}{% if isEnglish %}excl. VAT{% else %}zzgl. MwSt.{% endif %}{% endif %}
  66.                                 {% endif %}
  67.                             </div>
  68.                         </div>
  69.                     {% endif %}
  70.                 </div>
  71.             </div>
  72.             {# KI Campus Free Access Box #}
  73.             {% if displayPrice and isFreeForKiCampus %}
  74.                 <div class="bg-green-50 border border-green-200 rounded-xl p-4 mb-4">
  75.                     <div class="flex items-start gap-3">
  76.                         <span class="text-green-500 text-xl">&#10003;</span>
  77.                         <div>
  78.                             <strong class="text-green-700">
  79.                                 {% if isEnglish %}Free for KI Campus members{% else %}Kostenlos fuer KI Campus Mitglieder{% endif %}
  80.                             </strong>
  81.                             <p class="text-sm text-gray-600 mt-1">
  82.                                 {% if isEnglish %}
  83.                                     Join now for just EUR49/month and get access to this and many other free AI courses and events!
  84.                                 {% else %}
  85.                                     Werde Mitglied fuer nur 49EUR/Monat und erhalte Zugang zu diesem und vielen weiteren kostenlosen KI-Kursen und Events!
  86.                                 {% endif %}
  87.                             </p>
  88.                             <a target="_blank" href="https://ki-campus.onepage.me/" class="inline-block mt-2 px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors text-sm font-semibold">
  89.                                 {% if isEnglish %}Become a KI Campus member now{% else %}Jetzt KI Campus Mitglied werden{% endif %}
  90.                             </a>
  91.                         </div>
  92.                     </div>
  93.                 </div>
  94.             {% endif %}
  95.             {# Community Free Access Box #}
  96.             {% if displayPrice and isFreeForCommunity %}
  97.                 <div class="bg-green-50 border border-green-200 rounded-xl p-4 mb-4">
  98.                     <div class="flex items-start gap-3">
  99.                         <span class="text-green-500 text-xl">&#10003;</span>
  100.                         <div>
  101.                             <strong class="text-green-700">
  102.                                 {% if isEnglish %}Free for Community members{% else %}Kostenlos fuer Community Mitglieder{% endif %}
  103.                             </strong>
  104.                             <p class="text-sm text-gray-600 mt-1">
  105.                                 {% if isEnglish %}
  106.                                     As a Community member, you get free access to this event!
  107.                                 {% else %}
  108.                                     Als Community Mitglied erhaeltst Du kostenlosen Zugang zu diesem Event!
  109.                                 {% endif %}
  110.                             </p>
  111.                         </div>
  112.                     </div>
  113.                 </div>
  114.             {% endif %}
  115.         {% endif %}{# end registrationHeadline if/else #}
  116.             {# Payment pending: started + paid event → show hint and re-show form below #}
  117.             {% set isPaidAndStarted = application.applicationStatus is defined and application.applicationStatus == 'started' and batch.priceInEuroCent > 0 %}
  118.             {# Application Status #}
  119.             {% if application.applicationStatus is defined and application.applicationStatus is not empty %}
  120.                 {% if batch.registrationMode == 'lead-capture' and batch.registrationRedirectUrl and application.applicationStatus == 'applied' %}
  121.                     {# Lead-Capture: show redirect link instead of generic status #}
  122.                     <div class="bg-white rounded-2xl p-6 shadow-xl text-center">
  123.                         <p class="text-gray-700 mb-4">
  124.                             {% if isEnglish %}
  125.                                 Thank you for your inquiry! Book your consultation now:
  126.                             {% else %}
  127.                                 Danke fuer Deine Anfrage! Buche jetzt Dein Gespraech:
  128.                             {% endif %}
  129.                         </p>
  130.                         <a href="{{ batch.registrationRedirectUrl }}" target="_blank"
  131.                            class="inline-block px-8 py-4 bg-gray-900 text-white font-bold text-lg rounded-xl hover:bg-gray-800 transition-colors no-underline">
  132.                             {{ batch.registrationButtonText ?? (isEnglish ? 'Book now' : 'Jetzt buchen') }}
  133.                         </a>
  134.                     </div>
  135.                 {% elseif isPaidAndStarted %}
  136.                     <div class="bg-amber-50 border border-amber-200 rounded-xl p-4 mb-4">
  137.                         <strong class="text-amber-700">
  138.                             {% if isEnglish %}Payment pending{% else %}Zahlung ausstehend{% endif %}
  139.                         </strong>
  140.                         <p class="text-amber-600 mt-1">
  141.                             {% if isEnglish %}
  142.                                 Your registration has been started. Please complete the payment to confirm your spot.
  143.                             {% else %}
  144.                                 Deine Anmeldung wurde gestartet. Bitte schliesse die Zahlung ab, um Deinen Platz zu sichern.
  145.                             {% endif %}
  146.                         </p>
  147.                     </div>
  148.                 {% else %}
  149.                     <div class="bg-blue-50 border border-blue-200 rounded-xl p-4 mb-4">
  150.                         <strong class="text-blue-700">{{ phrases.event_phrase_application_status|default('Anmeldestatus:') }}</strong>
  151.                         <p class="text-blue-600 mt-1">
  152.                             {% if application.applicationStatus == 'started' %}
  153.                                 {{ phrases.event_phrase_status_started|default('Du bist vorgemerkt. Sobald Du Deine E-Mail Adresse bestaetigt hast, wird die Anmeldung gueltig.') }}
  154.                             {% elseif application.applicationStatus == 'applied' %}
  155.                                 {% if event is defined and event and event.isFormalLanguage %}
  156.                                     {{ phrases.event_phrase_status_applied_formal|default('Sie sind angemeldet. Wir freuen uns auf Sie!') }}
  157.                                 {% else %}
  158.                                     {{ phrases.event_phrase_status_applied|default('Du bist angemeldet. Wir freuen uns auf Dich!') }}
  159.                                 {% endif %}
  160.                             {% else %}
  161.                                 {{ phrases.event_phrase_status_other|default('Du bist angemeldet mit dem Status ==') }} {{ application.applicationStatus }}
  162.                             {% endif %}
  163.                         </p>
  164.                     </div>
  165.                 {% endif %}
  166.             {% endif %}
  167.         {% endif %}
  168.         {# Ticket Availability Counter #}
  169.         {% if settings.showParticipantCounter|default(false) %}
  170.             {% set maxParticipants = batch.capacity|default(0) %}
  171.             {% set countedStatuses = settings.countStatus|default(['applied', 'approved']) %}
  172.             {% set registered = 0 %}
  173.             {% if 'started' in countedStatuses and batch.startedCount is not null %}
  174.                 {% set registered = registered + batch.startedCount %}
  175.             {% endif %}
  176.             {% if 'applied' in countedStatuses and batch.appliedCount is not null %}
  177.                 {% set registered = registered + batch.appliedCount %}
  178.             {% endif %}
  179.             {% if 'approved' in countedStatuses and batch.approvedCount is not null %}
  180.                 {% set registered = registered + batch.approvedCount %}
  181.             {% endif %}
  182.             {% if 'rejected' in countedStatuses and batch.rejectedCount is not null %}
  183.                 {% set registered = registered + batch.rejectedCount %}
  184.             {% endif %}
  185.             {% set available = maxParticipants - registered %}
  186.             <div class="bg-white/10 backdrop-blur rounded-xl p-3 mb-6 text-center text-white">
  187.                 {% if isEnglish %}
  188.                     <strong>{{ registered }} of {{ maxParticipants }} seats taken</strong> |
  189.                     <strong class="text-yellow-300">{{ available }} left</strong> - don't miss your spot
  190.                 {% else %}
  191.                     <strong>{{ registered }} von {{ maxParticipants }} Plaetzen belegt</strong> |
  192.                     <strong class="text-yellow-300">{{ available }} uebrig</strong> - sichere dir deinen Platz
  193.                 {% endif %}
  194.             </div>
  195.         {% endif %}
  196.         {# Registration Form — also shown when payment is pending (started + paid) #}
  197.         {% if application.applicationStatus is defined and (application.applicationStatus is empty or isPaidAndStarted) %}
  198.             {# Waiting List or Full Notice #}
  199.             {% set effectiveCapacity = batch.capacity|default(0) %}
  200.             {% if effectiveCapacity > 0 and batch.appliedCount >= effectiveCapacity %}
  201.                 {% if settings.hasWaitingList %}
  202.                     <h2 class="text-2xl font-bold text-white text-center mb-6">
  203.                         {{ phrases.event_phrase_all_seats_booked_waiting_list|default('Alle Plaetze sind gebucht - Bitte registriere Dich fuer die Warteliste') }}
  204.                     </h2>
  205.                 {% else %}
  206.                     <h2 class="text-2xl font-bold text-white text-center mb-6">
  207.                         {{ phrases.event_phrase_all_seats_booked_no_registration|default('Alle Plaetze sind gebucht - Eine Anmeldung ist leider nicht moeglich') }}
  208.                     </h2>
  209.                 {% endif %}
  210.             {% endif %}
  211.             {# Show form if not full OR has waiting list #}
  212.             {% if (effectiveCapacity == 0 or batch.appliedCount < effectiveCapacity) or (effectiveCapacity > 0 and batch.appliedCount >= effectiveCapacity and settings.hasWaitingList) %}
  213.                 {# Form Container #}
  214.                 <div class="bg-white rounded-2xl p-6 shadow-xl">
  215.                     {{ form_start(form) }}
  216.                     {{ form_errors(form) }}
  217.                     {# Name Fields (Side by Side) #}
  218.                     <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
  219.                         <div>
  220.                             {{ form_widget(form.firstName, {'attr': {
  221.                                 'class': 'w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[color:var(--registration-accent,#9632FF)] focus:border-transparent outline-none transition-all',
  222.                                 'placeholder': phrases.phrase_form_firstName_placeholder ~ ' (*)'
  223.                             }}) }}
  224.                         </div>
  225.                         <div>
  226.                             {{ form_widget(form.lastName, {'attr': {
  227.                                 'class': 'w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[color:var(--registration-accent,#9632FF)] focus:border-transparent outline-none transition-all',
  228.                                 'placeholder': phrases.phrase_form_lastName_placeholder ~ ' (*)'
  229.                             }}) }}
  230.                         </div>
  231.                     </div>
  232.                     {# Startup Name (Optional) #}
  233.                     {% if batch.askForTeam %}
  234.                         <div class="mb-4">
  235.                             {{ form_widget(form.startupName, {'attr': {
  236.                                 'class': 'w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[color:var(--registration-accent,#9632FF)] focus:border-transparent outline-none transition-all',
  237.                                 'placeholder': 'Firma'
  238.                             }, 'required': false}) }}
  239.                         </div>
  240.                     {% endif %}
  241.                     {# Email #}
  242.                     <div class="mb-4">
  243.                         {{ form_widget(form.email, {'attr': {
  244.                             'class': 'w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[color:var(--registration-accent,#9632FF)] focus:border-transparent outline-none transition-all',
  245.                             'placeholder': 'E-mail (*)'
  246.                         }}) }}
  247.                     </div>
  248.                     {# Phone #}
  249.                     {% if batch.hasIncludePhone %}
  250.                         <div class="mb-4">
  251.                             {{ form_widget(form.phone, {'attr': {
  252.                                 'class': 'w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[color:var(--registration-accent,#9632FF)] focus:border-transparent outline-none transition-all',
  253.                                 'placeholder': 'Phone Number'
  254.                             }, 'required': false}) }}
  255.                             <p class="text-sm text-gray-500 mt-1">
  256.                                 {{ phrases.request_phone_number_for_updates|default('Bitte gib Deine Telefonnummer an, damit wir Dich im Fall von Aenderungen erreichen koennen.') }}
  257.                             </p>
  258.                         </div>
  259.                     {% endif %}
  260.                     {# LinkedIn #}
  261.                     {% if batch.hasIncludeLinkedIn %}
  262.                         <div class="mb-4">
  263.                             {{ form_widget(form.linkedin, {'attr': {
  264.                                 'class': 'w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[color:var(--registration-accent,#9632FF)] focus:border-transparent outline-none transition-all'
  265.                             }, 'required': false}) }}
  266.                         </div>
  267.                     {% endif %}
  268.                     {# Extra Fields (Dynamic) #}
  269.                     {% if attribute(settings, 'extraFields') is defined %}
  270.                         {% set extraFields = attribute(settings, 'extraFields') %}
  271.                         {% for extraField in extraFields %}
  272.                             {% set formField = attribute(form, extraField.field) %}
  273.                             {% if extraField.type == 'checkbox' %}
  274.                                 <div class="mb-4">
  275.                                     <label class="flex items-start gap-3 cursor-pointer">
  276.                                         {{ form_widget(formField, {'attr': {
  277.                                             'class': 'mt-1 w-5 h-5 accent-[color:var(--registration-accent,#9632FF)] border-gray-300 rounded'
  278.                                         }, 'required': extraField.required}) }}
  279.                                         <span class="text-gray-600 text-sm">{{ extraField.label }}</span>
  280.                                     </label>
  281.                                 </div>
  282.                             {% else %}
  283.                                 <div class="mb-4">
  284.                                     {{ form_widget(formField, {'attr': {
  285.                                         'class': 'w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[color:var(--registration-accent,#9632FF)] focus:border-transparent outline-none transition-all'
  286.                                     }, 'required': extraField.required}) }}
  287.                                 </div>
  288.                             {% endif %}
  289.                         {% endfor %}
  290.                     {% endif %}
  291.                     {# Applicant Types #}
  292.                     {% if settings.applicantTypes is defined and settings.applicantTypes %}
  293.                         <div class="mb-4">
  294.                             {{ form_widget(form.applicantType, {'attr': {
  295.                                 'class': 'w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[color:var(--registration-accent,#9632FF)] focus:border-transparent outline-none transition-all'
  296.                             }, 'required': false}) }}
  297.                         </div>
  298.                     {% endif %}
  299.                     {# Newsletter Permission #}
  300.                     {% if batch.hasIncludeNewsletterPermission %}
  301.                         <div class="mb-4">
  302.                             <label class="flex items-start gap-3 cursor-pointer">
  303.                                 {{ form_widget(form.hasNewsletterPermissionGiven, {'attr': {
  304.                                     'class': 'mt-1 w-5 h-5 accent-[color:var(--registration-accent,#9632FF)] border-gray-300 rounded'
  305.                                 }, 'required': false}) }}
  306.                                 <span class="text-gray-600 text-sm">
  307.                                     {% if application.lang == 'DE' %}
  308.                                         Ja, ich moechte gerne ueber weitere Veranstaltungen informiert werden.
  309.                                     {% else %}
  310.                                         Yes, I would like to be informed about further events.
  311.                                     {% endif %}
  312.                                 </span>
  313.                             </label>
  314.                         </div>
  315.                     {% endif %}
  316.                     {# Volunteer Consent #}
  317.                     {% if settings.hasIncludeVolunteerConsent is defined and settings.hasIncludeVolunteerConsent %}
  318.                         <div class="mb-4">
  319.                             <label class="flex items-start gap-3 cursor-pointer">
  320.                                 {{ form_widget(form.hasVolunteerAgreed, {'attr': {
  321.                                     'class': 'mt-1 w-5 h-5 accent-[color:var(--registration-accent,#9632FF)] border-gray-300 rounded'
  322.                                 }, 'required': false}) }}
  323.                                 <span class="text-gray-600 text-sm">
  324.                                     {% if application.lang == 'DE' %}
  325.                                         Ja, ich wuerde mich gerne als Volunteer, Mentor oder Unterstuetzer einbringen
  326.                                     {% else %}
  327.                                         Yes, I would like to contribute as a volunteer, mentor, or supporter
  328.                                     {% endif %}
  329.                                 </span>
  330.                             </label>
  331.                         </div>
  332.                     {% endif %}
  333.                     {# Terms Consent #}
  334.                     {% if batch.hasIncludeTermsConsent %}
  335.                         <div class="mb-4 p-3 bg-gray-50 rounded-lg">
  336.                             <p class="text-sm text-gray-500">
  337.                                 {% if application.lang == 'DE' %}
  338.                                     Bei unseren Veranstaltungen koennen Aufnahmen fuer Social Media gemacht werden.
  339.                                     <br>Mit Deiner Anmeldung stimmst Du zu, dass Bildaufnahmen fuer Social Media verwendet werden duerfen.
  340.                                 {% else %}
  341.                                     At our events, recordings for social media can be made.
  342.                                     <br>By registering, you agree that image recordings may be used for social media.
  343.                                 {% endif %}
  344.                             </p>
  345.                         </div>
  346.                     {% endif %}
  347.                     {# AI Hub Trial Membership Note #}
  348.                     {% if batch.productId > 322 and batch.productId < 330 %}
  349.                         <div class="mb-4 p-3 bg-gray-50 rounded-lg">
  350.                             <p class="text-sm text-gray-500">
  351.                                 (*) die Probemitgliedschaft im AI Hub verlaengert sich nicht automatisch und wird 30 Tage nach Ende der ausgewaehlten AI-Summer-School-Ausgabe automatisch und ohne zusaetzliche Kosten gekuendigt.
  352.                             </p>
  353.                         </div>
  354.                     {% endif %}
  355.                     {# Price Information #}
  356.                     {% if batch.priceInEuroCent %}
  357.                         <div class="mb-4 p-3 bg-gray-50 rounded-lg">
  358.                             {% if application.lang == 'DE' %}
  359.                                 <strong>Der Standardpreis betraegt {{ application.priceInEuroCent / 100|number_format(0, ',', '.') }}EUR</strong> (zzgl. MwSt.)
  360.                                 {% if application.discountPercent %}
  361.                                     <br>
  362.                                     Du erhaelst einen Discount wegen <i>{{ application.discountReason }}</i> in Hoehe von {{ application.discountPercent }}%
  363.                                     und daher betraegt der Preis fuer Dich {{ application.realPriceinEuroCent / 100|number_format(0, ',', '.') }}EUR (zzgl. MwSt.)
  364.                                 {% endif %}
  365.                                 <br>
  366.                                 {% if application.realPriceinEuroCent %}
  367.                                     <small class="text-gray-500">Mit Klick auf "Jetzt anmelden" wirst Du angemeldet und der Zahlungsvorgang wird gestartet</small>
  368.                                 {% endif %}
  369.                             {% else %}
  370.                                 <strong>The standard price is {{ application.priceInEuroCent / 100|number_format(0, ',', '.') }}EUR</strong>
  371.                                 {% if application.discountPercent %}
  372.                                     <br>
  373.                                     You will receive a discount due to <i>{{ application.discountReason }}</i> in the amount of {{ application.discountPercent }}%
  374.                                     and therefore the price for you is {{ application.realPriceinEuroCent / 100|number_format(0, ',', '.') }}EUR
  375.                                 {% endif %}
  376.                                 <br>
  377.                                 {% if application.realPriceinEuroCent %}
  378.                                     <small class="text-gray-500">By clicking "Register Now" you will be registered and the payment process will be started</small>
  379.                                 {% endif %}
  380.                             {% endif %}
  381.                         </div>
  382.                     {% endif %}
  383.                     {# Submit Button #}
  384.                     {% set label = batch.registrationButtonText ?? phrases.phrase_form_button_call_to_act %}
  385.                     <div class="text-center mt-6">
  386.                         {{ form_widget(form.finish, {'attr': {
  387.                             'class': 'px-8 py-4 bg-gray-900 text-white font-bold text-lg rounded-xl hover:bg-gray-800 transition-colors cursor-pointer'
  388.                         }, 'label': label}) }}
  389.                     </div>
  390.                     {# CSRF Token #}
  391.                     {% if not embed|default(false) %}
  392.                         {{ form_row(form._token) }}
  393.                     {% endif %}
  394.                     {# B-128: Meta CAPI dedup event ID #}
  395.                     <input type="hidden" name="_meta_event_id" id="metaEventId" value="">
  396.                     {{ form_end(form, {'render_rest': false}) }}
  397.                     {# Meta Pixel CompleteRegistration Event - fires on lead-capture form submit (B-128: with CAPI dedup eventID) #}
  398.                     <script>
  399.                         (function() {
  400.                             var form = document.querySelector('form[name="{{ form.vars.name }}"]');
  401.                             if (!form) return;
  402.                             var isSubmitting = false;
  403.                             form.addEventListener('submit', function(e) {
  404.                                 if (isSubmitting) return true;
  405.                                 if (typeof fbq !== 'undefined') {
  406.                                     e.preventDefault();
  407.                                     e.stopPropagation();
  408.                                     var submitted = false;
  409.                                     function submitForm() {
  410.                                         if (submitted) return;
  411.                                         submitted = true;
  412.                                         isSubmitting = true;
  413.                                         form.submit();
  414.                                     }
  415.                                     var metaEventId = (crypto && crypto.randomUUID) ? crypto.randomUUID() : 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
  416.                                         var r = Math.random() * 16 | 0; return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
  417.                                     });
  418.                                     var eventIdField = document.getElementById('metaEventId');
  419.                                     if (eventIdField) eventIdField.value = metaEventId;
  420.                                     fbq('track', 'CompleteRegistration', {
  421.                                         content_name: '{{ event.title|e('js') }}'
  422.                                     }, { eventID: metaEventId });
  423.                                     setTimeout(function() {
  424.                                         submitForm();
  425.                                     }, 1000);
  426.                                 }
  427.                             });
  428.                         })();
  429.                     </script>
  430.                     {# Reduced Tickets Info #}
  431.                     {% if batch.priceInEuroCent and attribute(phrases, 'phrase_reduced_tickets') is defined %}
  432.                         <div class="mt-4">
  433.                             <p class="text-sm text-gray-500">{{ phrases.phrase_reduced_tickets }}</p>
  434.                         </div>
  435.                     {% endif %}
  436.                 </div>
  437.             {% endif %}
  438.         {% endif %}
  439.     </div>
  440.     {# Multi-Batch: Other Dates Section #}
  441.     {% if isMultiBatchEvent and futureBatches|length > 1 %}
  442.         <div class="max-w-4xl mx-auto px-4 mt-12" id="{{ isEnglish ? 'OtherDates' : 'WeitereTermine' }}">
  443.             <h3 class="text-2xl font-bold text-white text-center mb-6">
  444.                 {{ phrases.event_phrase_other_dates|default('Weitere Termine') }}
  445.             </h3>
  446.             <div class="space-y-3">
  447.                 {% for futureBatch in futureBatches %}
  448.                     {% if futureBatch.id != batch.id %}
  449.                         <a href="{{ path('event_show_single_by_date', {'slug': event.slug, 'date': futureBatch.startDate|date('Y-m-d')}) }}"
  450.                            class="block bg-white rounded-xl p-4 hover:shadow-lg transition-shadow">
  451.                             <div class="flex flex-wrap items-center justify-between gap-4">
  452.                                 <div>
  453.                                     <h5 class="text-lg font-semibold text-gray-900">
  454.                                         {% if lang == 'DE' %}
  455.                                             {{ futureBatch.startDate|date('d. F Y', 'Europe/Berlin')|replace({
  456.                                                 'January': 'Januar', 'February': 'Februar', 'March': 'Maerz',
  457.                                                 'April': 'April', 'May': 'Mai', 'June': 'Juni',
  458.                                                 'July': 'Juli', 'August': 'August', 'September': 'September',
  459.                                                 'October': 'Oktober', 'November': 'November', 'December': 'Dezember'
  460.                                             }) }}
  461.                                         {% else %}
  462.                                             {{ futureBatch.startDate|date('F d, Y') }}
  463.                                         {% endif %}
  464.                                     </h5>
  465.                                     <p class="text-gray-600">
  466.                                         {{ futureBatch.startDate|date('H:i') }} -
  467.                                         {% if futureBatch.endDate %}
  468.                                             {{ futureBatch.endDate|date('H:i') }} Uhr
  469.                                         {% else %}
  470.                                             {{ futureBatch.startDate|date_modify('+2 hours')|date('H:i') }} Uhr
  471.                                         {% endif %}
  472.                                     </p>
  473.                                     {% if futureBatch.name and futureBatch.name != batch.name %}
  474.                                         <p class="text-sm text-gray-400">{{ futureBatch.name }}</p>
  475.                                     {% endif %}
  476.                                 </div>
  477.                                 <div class="flex items-center gap-2">
  478.                                     {% set isBatchOpen = futureBatch.start and futureBatch.end and date(futureBatch.start) <= date() and date(futureBatch.end) >= date() %}
  479.                                     {% set futureBatchCapacity = futureBatch.capacity|default(0) %}
  480.                                     {% if futureBatchCapacity > 0 and futureBatch.appliedCount >= futureBatchCapacity %}
  481.                                         <span class="px-3 py-1 bg-red-100 text-red-700 rounded-full text-sm font-medium">Ausgebucht</span>
  482.                                     {% elseif not isBatchOpen %}
  483.                                         <span class="px-3 py-1 bg-gray-100 text-gray-600 rounded-full text-sm font-medium">Anmeldung geschlossen</span>
  484.                                     {% else %}
  485.                                         <span class="px-3 py-1 bg-green-100 text-green-700 rounded-full text-sm font-medium">
  486.                                             {% if futureBatchCapacity > 0 %}
  487.                                                 {{ futureBatchCapacity - futureBatch.appliedCount }} Plaetze frei
  488.                                             {% else %}
  489.                                                 Plaetze verfuegbar
  490.                                             {% endif %}
  491.                                         </span>
  492.                                         <span class="text-[color:var(--registration-accent,#9632FF)] font-medium">Zu diesem Termin &#8594;</span>
  493.                                     {% endif %}
  494.                                 </div>
  495.                             </div>
  496.                         </a>
  497.                     {% endif %}
  498.                 {% endfor %}
  499.             </div>
  500.             {% if selectedDate %}
  501.                 <div class="mt-4 text-center">
  502.                     <a href="{{ path('event_show_single', {'slug': event.slug}) }}" class="text-white hover:text-gray-200 underline">
  503.                         &#8592; Alle Termine anzeigen
  504.                     </a>
  505.                 </div>
  506.             {% endif %}
  507.         </div>
  508.     {% endif %}
  509. </section>