templates/module/FormTermin/__form-termin.html.twig line 1

Open in your IDE?
  1. {% block content %}
  2. {% if editmode %}
  3.     {{ include('includes/backend-kopf.html.twig') }}
  4.     {% set tabContentArray = {1: 'Data'} %}
  5.     {% set tab = 1 %}
  6.     <style>
  7.         section.tabContent {
  8.             display: block;
  9.         }
  10.     </style>
  11.     <div id="content">
  12.         <section class="tabContent">
  13.             <p class="hl">Email Betreff:</p>
  14.             <span class="parentbox">
  15.             {{ pimcore_textarea("subject", {
  16.                 "nl2br": true,
  17.                 "width": 735,
  18.             }) }}
  19.             </span>
  20.         </section>
  21.         <section class="tabContent">
  22.             <p class="hl">Titel:</p>
  23.             <span class="parentbox">
  24.             {{ pimcore_textarea("title", {
  25.                 "nl2br": true,
  26.                 "width": 735,
  27.             }) }}
  28.             </span>
  29.         </section>
  30.         <section class="tabContent">
  31.             <p class="hl">Beschreibung:</p>
  32.             <span class="parentbox">
  33.             {{ pimcore_textarea("description", {
  34.                 "nl2br": true,
  35.                 "width": 735,
  36.             }) }}
  37.             </span>
  38.         </section>
  39.         {# <section class="tabContent">
  40.             <p class="hl">Bild:</p>
  41.             <span class="parentbox">
  42.             {{ pimcore_image("image", {
  43.                 "width": 200,
  44.                 "height": 130,
  45.                 "thumbnail": "img-default-edm"
  46.             }) }}
  47.             </span>
  48.         </section> #}
  49.         <section class="tabContent">
  50.             <p class="hl">Saisonsende:</p>
  51.             <span class="parentbox">
  52.             {{ pimcore_date("maxDate", {
  53.                 "format": "d.m.Y",
  54.                 "outputIsoFormat": "DD.MM.YYYY"
  55.             }) }}
  56.             </span>
  57.         </section>
  58.         <section class="tabContent">
  59.             <p class="hl">Erster Termin (Uhrzeit):</p>
  60.             <span class="parentbox">
  61.             {{ pimcore_textarea("minHours", {
  62.                 "nl2br": true,
  63.                 "width": 735,
  64.                 "placeholder": "09:00"
  65.             }) }}
  66.             </span>
  67.         </section>
  68.         <section class="tabContent">
  69.             <p class="hl">Letzter Termin (Uhrzeit): </p>
  70.             <span class="parentbox">
  71.             {{ pimcore_textarea("maxHours", {
  72.                 "nl2br": true,
  73.                 "width": 735,
  74.                 "placeholder": "18:00"
  75.             }) }}
  76.             </span>
  77.         </section>
  78.         <section class="tabContent">
  79.             <p class="hl">Zeitintervall:</p>
  80.             <span class="parentbox">
  81.             {{ pimcore_select("timeIntervals", {
  82.                 "store": [
  83.                     ["15", "15min"],
  84.                     ["30", "30min"],
  85.                     ["60", "60min"]
  86.                 ],
  87.             }) }}
  88.             </span>
  89.         </section>
  90.         <section class="tabContent">
  91.             <p class="hl">Service wählen (Zwischen den Services muss ein ; stehen):</p>
  92.             <span class="parentbox">
  93.             {{ pimcore_textarea("services", {
  94.                 "nl2br": true,
  95.                 "width": 735,
  96.                 "placeholder": "Skischuhfitting ; Shopping Beratung"
  97.             }) }}
  98.             </span>
  99.         </section>
  100.         <section class="tabContent">
  101.             <p class="hl">Filiale (Zwischen den Standorten muss ein ; stehen):</p>
  102.             <span class="parentbox">
  103.             {{ pimcore_textarea("locations", {
  104.                 "nl2br": true,
  105.                 "width": 735,
  106.                 "placeholder": "Zentrum ; Giggijochbahn"
  107.             }) }}
  108.             </span>
  109.         </section>
  110.     </div>
  111.     {{ include('includes/backend-fuss.html.twig') }}
  112. {% else %}
  113.     <style>
  114.         .ski-boot-fitting {
  115.             padding-bottom: 2rem;
  116.             padding-top: 2rem;
  117.         }
  118.         .ski-boot-fitting {
  119.             background-color: #164194;
  120.         }
  121.         [data-theme="shops"] .ski-boot-fitting {
  122.             background-color: #e3e3e0;
  123.         }
  124.         [data-theme="rent"] .ski-boot-fitting {
  125.             background-color: #164194;
  126.         }
  127.         [data-theme="homes"] .ski-boot-fitting {
  128.             background-color: #bc9f60;
  129.         }
  130.         .form-termin-heading,
  131.         .form-termin-description {
  132.             color: #fff;
  133.         }
  134.         [data-theme="shops"] .form-termin-heading,
  135.         [data-theme="shops"] .form-termin-description {
  136.             color: #e50000;
  137.         }
  138.         [data-theme="rent"] .form-termin-heading,
  139.         [data-theme="rent"] .form-termin-description {
  140.             color: #fff;
  141.         }
  142.         [data-theme="homes"] .form-termin-heading,
  143.         [data-theme="homes"] .form-termin-description {
  144.             color: #000;
  145.         }
  146.         .form-termin-heading {
  147.             margin: 0;
  148.         }
  149.         .form-termin-form-container {
  150.             display: flex;
  151.             flex-wrap: wrap;
  152.             column-gap: 10px;
  153.             justify-content: space-between;
  154.             gap: 10px;
  155.         }
  156.         .form-termin-input-container {
  157.             width: 100%;
  158.         }
  159.         .form-termin-input-container input,
  160.         .form-termin-input-container select,
  161.         .form-termin-input-container button {
  162.             width: 100%;
  163.         }
  164.         .form-termin-input-container input,
  165.         .form-termin-input-container select,
  166.         .form-termin-input-container button {
  167.             background-color: rgba(255, 255, 255, 0.1);
  168.             color: #ffffff;
  169.             border: none;
  170.             box-shadow: none;
  171.             padding: 0.375rem 0.75rem;
  172.             font-size: 1rem;
  173.             line-height: 1.5;
  174.             border-radius: 5px;
  175.         }
  176.         [data-theme="rent"] .form-termin-input-container input,
  177.         [data-theme="rent"] .form-termin-input-container select,
  178.         [data-theme="rent"] .form-termin-input-container button {
  179.             background-color: rgba(255, 255, 255, 0.1);
  180.             color: #ffffff;
  181.         }
  182.         .form-termin-input-container input,
  183.         .form-termin-input-container select {
  184.             color: #000;
  185.             background-color: #fff;
  186.         }
  187.         /* Change placeholder color for all browsers */
  188.         .form-termin-input-container input::placeholder {
  189.             color: #000; /* Replace with your desired color */
  190.             opacity: 1; /* Ensures the color is fully opaque */
  191.         }
  192.         /* For specific browsers */
  193.         .form-termin-input-container input::-webkit-input-placeholder {
  194.             color: #000; /* Chrome, Safari, and Opera */
  195.         }
  196.         .form-termin-input-container input:-ms-input-placeholder {
  197.             color: #000; /* Internet Explorer */
  198.         }
  199.         .form-termin-input-container input::-ms-input-placeholder {
  200.             color: #000; /* Microsoft Edge */
  201.         }
  202.         .form-termin-input-container button {
  203.             cursor: pointer;
  204.         }
  205.         [data-theme="shops"] .form-termin-input-container input,
  206.         [data-theme="shops"] .form-termin-input-container select {
  207.             color: #fff;
  208.             background-color: #e50000;
  209.         }
  210.         /* Change placeholder color for all browsers */
  211.         [data-theme="shops"] .form-termin-input-container input::placeholder {
  212.             color: #fff; /* Replace with your desired color */
  213.             opacity: 1; /* Ensures the color is fully opaque */
  214.         }
  215.         /* For specific browsers */
  216.         [data-theme="shops"] .form-termin-input-container input::-webkit-input-placeholder {
  217.             color: #fff; /* Chrome, Safari, and Opera */
  218.         }
  219.         [data-theme="shops"] .form-termin-input-container input:-ms-input-placeholder {
  220.             color: #fff; /* Internet Explorer */
  221.         }
  222.         [data-theme="shops"] .form-termin-input-container input::-ms-input-placeholder {
  223.             color: #fff; /* Microsoft Edge */
  224.         }
  225.         [data-theme="shops"] .form-termin-input-container button {
  226.             cursor: pointer;
  227.         }
  228.         /* Change placeholder color for all browsers */
  229.         [data-theme="rent"] .form-termin-input-container input::placeholder {
  230.             color: #fff; /* Replace with your desired color */
  231.             opacity: 1; /* Ensures the color is fully opaque */
  232.         }
  233.         /* For specific browsers */
  234.         [data-theme="rent"] .form-termin-input-container input::-webkit-input-placeholder {
  235.             color: #fff; /* Chrome, Safari, and Opera */
  236.         }
  237.         [data-theme="rent"] .form-termin-input-container input:-ms-input-placeholder {
  238.             color: #fff; /* Internet Explorer */
  239.         }
  240.         [data-theme="rent"] .form-termin-input-container input::-ms-input-placeholder {
  241.             color: #fff; /* Microsoft Edge */
  242.         }
  243.         [data-theme="rent"] .form-termin-input-container button {
  244.             cursor: pointer;
  245.         }
  246.         [data-theme="homes"] .form-termin-input-container input,
  247.         [data-theme="homes"] .form-termin-input-container select {
  248.             color: #000;
  249.         }
  250.         
  251.         /* Change placeholder color for all browsers */
  252.         [data-theme="homes"] .form-termin-input-container input::placeholder {
  253.             color: #fff; /* Replace with your desired color */
  254.             opacity: 1; /* Ensures the color is fully opaque */
  255.         }
  256.         /* For specific browsers */
  257.         [data-theme="homes"] .form-termin-input-container input::-webkit-input-placeholder {
  258.             color: #000; /* Chrome, Safari, and Opera */
  259.         }
  260.         [data-theme="homes"] .form-termin-input-container input:-ms-input-placeholder {
  261.             color: #000; /* Internet Explorer */
  262.         }
  263.         [data-theme="homes"] .form-termin-input-container input::-ms-input-placeholder {
  264.             color: #000; /* Microsoft Edge */
  265.         }
  266.         [data-theme="homes"] .form-termin-input-container button {
  267.             cursor: pointer;
  268.         }
  269.         .form-termin-input-container button {
  270.             background-color: #fff;
  271.             color: #000;
  272.         }
  273.         [data-theme="shops"] .form-termin-input-container button {
  274.             background-color: #e50000;
  275.             color: #fff;
  276.         }
  277.         [data-theme="rent"] .form-termin-input-container button {
  278.             background-color: rgba(255, 255, 255, 1);
  279.             color: #164194;
  280.         }
  281.         [data-theme="homes"] .form-termin-input-container button {
  282.             background-color: #000;
  283.             color: #fff;
  284.         }
  285.         @media only screen and (min-width: 740px) {
  286.             .form-termin-input-container {
  287.                 width: 49%;
  288.             }
  289.         }
  290.         @media only screen and (min-width: 940px) {
  291.             .form-termin-input-container {
  292.                 width: 32%;
  293.             }
  294.         }
  295.         .form-termin-input-container:has(button) {
  296.             width: 100%;
  297.         }
  298.         .form-termin-input-container .invalid-feedback,
  299.         .form-termin-input-container .form-termin-feedback  {
  300.             margin-top: 4px;
  301.             color: #fff;
  302.         }
  303.         .form-termin-input-container .form-termin-feedback {
  304.             margin-top: 10px;
  305.             text-align: center;
  306.             font-weight: bold;
  307.             font-size: 20px;
  308.         }
  309.         [data-theme="shops"] .form-termin-input-container .invalid-feedback,
  310.         [data-theme="shops"] .form-termin-input-container .form-termin-feedback {
  311.             color: #e50000;
  312.         }
  313.         [data-theme="rent"] .form-termin-input-container .invalid-feedback,
  314.         [data-theme="rent"] .form-termin-input-container .form-termin-feedback {
  315.             color: #fff;
  316.         }
  317.         [data-theme="homes"] .form-termin-input-container .invalid-feedback,
  318.         [data-theme="homes"] .form-termin-input-container .form-termin-feedback {
  319.             color: #000;
  320.         }
  321.     </style>
  322.     <link rel="stylesheet" type="text/css" href="/bundles/app/static/frontend/css/pikaday.css" />
  323.     {% set lang = document.getProperty('language') %}
  324.     <div class="ski-boot-fitting">
  325.         <div class="constrainer-maxsize edgepadding">
  326.             <div class="row">
  327.                 {# {% set image_src = pimcore_image("icon_teaser_1").getSrc() %}
  328.                 {% if image_src %}
  329.                 <div class="image-col col-12"><img alt="Sporthaus St.Anton, Dorfstrasse 1" src="{{ image_src }}"></div>
  330.                 {% endif %} #}
  331.                 <div class="text-col col-12">
  332.                     <h2 class="form-termin-heading">{{ pimcore_textarea('title') }}</h2>
  333.                     <p class="form-termin-description">{{ pimcore_textarea('description') }}</p>
  334.                     <form id="form-{{ document.id }}" action="{{ path('handle_form_submission') }}" method="POST">
  335.                         <input type="hidden" name="subject" id="id_subject" value="{{ pimcore_textarea("subject") }}" />
  336.                         <div class="form-termin-form-container">
  337.                             <div class="form-termin-input-container">
  338.                                 <input class="form-control" id="id_name-{{ document.id }}" name="name" placeholder="Name" required="true" type="text">
  339.                                 <div class="invalid-feedback"></div>
  340.                             </div>
  341.                             <div class="form-termin-input-container">
  342.                                 <input class="form-control" id="id_email-{{ document.id }}" name="email" placeholder="{% if lang == 'de' %}E-Mail{% else %}Email{% endif %}" required="true" type="email">
  343.                                 <div class="invalid-feedback"></div>
  344.                             </div>
  345.                             <div class="form-termin-input-container">
  346.                                 <select class="form-control" id="id_service-{{ document.id }}" name="service" required="true">
  347.                                     <option selected="true" disabled="disabled" value="">{% if lang == 'de' %}Service wählen{% else %}Choose service{% endif %}</option>
  348.                                     {% set servicesList = pimcore_textarea('services') | split(';') %}
  349.                                     {% for service in servicesList %}
  350.                                         <option value="{{ service | trim }}">{{ service | trim }}</option>
  351.                                     {% endfor %}
  352.                                 </select>
  353.                                 <div class="invalid-feedback"></div>
  354.                             </div>
  355.                             <div class="form-termin-input-container">
  356.                                 <select class="form-control" id="id_location-{{ document.id }}" name="location" required="true">
  357.                                     <option selected="true" disabled="disabled" value="">{% if lang == 'de' %}Filiale{% else %}Location{% endif %}</option>
  358.                                     {% set locationList = pimcore_textarea('locations') | split(';') %}
  359.                                     {% for location in locationList %}
  360.                                         <option value="{{ location | trim }}">{{ location | trim }}</option>
  361.                                     {% endfor %}
  362.                                 </select>
  363.                                 <div class="invalid-feedback"></div>
  364.                             </div>
  365.                             <div class="form-termin-input-container">
  366.                                 <input class="form-control flatpickr-input" id="id_date-{{ document.id }}" name="date" placeholder="{% if lang == 'de' %}Datum{% else %}Date{% endif %}" required="true" type="text" readonly="readonly">
  367.                                 <div class="invalid-feedback"></div>
  368.                             </div>
  369.                             <div class="form-termin-input-container">
  370.                                 <select class="form-control" id="id_time-{{ document.id }}" name="time" required="true">
  371.                                     <option selected="true" disabled="disabled" value="">{% if lang == 'de' %}Zeit{% else %}Time{% endif %}</option>
  372.                                     {% set minHours = pimcore_textarea("minHours") %}
  373.                                     {% set maxHours = pimcore_textarea("maxHours") %}
  374.                                     {% set selectedInterval = pimcore_select("timeIntervals").getData() %}
  375.                                     {% set minTimeParts = minHours|split(':') %}
  376.                                     {% set maxTimeParts = maxHours|split(':') %}
  377.                                     {% set interval = selectedInterval|number_format %}
  378.                                     {% set startHour = minTimeParts[0]|number_format %}
  379.                                     {% set startMinute = minTimeParts[1]|number_format %}
  380.                                     {% set endHour = maxTimeParts[0]|number_format %}
  381.                                     {% set endMinute = maxTimeParts[1]|number_format %}
  382.                                     {% set currentHour = startHour %}
  383.                                     {% set currentMinute = startMinute %}
  384.                                     {% set totalMinutes = ((endHour * 60) + endMinute) - ((startHour * 60) + startMinute) %}
  385.                                     {% set steps = totalMinutes // interval %}
  386.                                     {% set currentMinute = startMinute %}
  387.                                     {% for i in 0..steps %}
  388.                                         {% set currentTimeInMinutes = (startHour * 60) + startMinute + (i * interval) %}
  389.                                         {% set currentHour = currentTimeInMinutes // 60 %}
  390.                                         {% set currentMinute = currentTimeInMinutes % 60 %}
  391.                                         {% set formattedTime = (currentHour < 10 ? '0' ~ currentHour : currentHour) ~ ':' ~ (currentMinute < 10 ? '0' ~ currentMinute : currentMinute) %}
  392.                                         <option value="{{ formattedTime }}">{{ formattedTime }}</option>
  393.                                     {% endfor %}
  394.                                 </select>
  395.                                 <div class="invalid-feedback"></div>
  396.                             </div>
  397.                             <div class="form-termin-input-container">
  398.                                 <button id="form-termin-button-{{ document.id }}" type="submit">{% if lang == 'de' %}Termin Buchen{% else %}Book{% endif %}</button>
  399.                                 <div class="form-termin-feedback" id="form-termin-feedback-{{ document.id }}"></div>
  400.                             </div>
  401.                         </div>
  402.                     </form>
  403.                 </div>
  404.             </div>
  405.         </div>
  406.     </div>
  407.     <script src="/bundles/app/static/frontend/js/pikaday.js"></script>
  408.     <script>
  409.         var picker{{ document.id }} = new Pikaday({
  410.             field: document.getElementById('id_date-{{ document.id }}'),
  411.             minDate: new Date(),
  412.             maxDate: new Date('{{ pimcore_date("maxDate") }}'),
  413.             theme: "form-termin",
  414.                 toString: function(date) {
  415.                 var parts = [('0'+date.getDate()).slice(-2), ('0'+(date.getMonth()+1)).slice(-2), date.getFullYear()];
  416.                 return parts.join(".");
  417.             },
  418.             {% if lang == 'de' %}
  419.             i18n: {
  420.                 previousMonth : 'Vorheriger Monat',
  421.                 nextMonth     : 'Nächster Monat',
  422.                 months        : ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
  423.                 weekdays      : ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
  424.                 weekdaysShort : ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']
  425.             }
  426.             {% endif %}
  427.         });
  428.         document.getElementById('form-{{ document.id }}').addEventListener('submit', async function (e) {
  429.             e.preventDefault();
  430.             const form = this;
  431.             const formBtn = document.getElementById('form-termin-button-{{ document.id }}');
  432.             const nameField = document.getElementById('id_name-{{ document.id }}');
  433.             const emailField = document.getElementById('id_email-{{ document.id }}');
  434.             const serviceField = document.getElementById('id_service-{{ document.id }}');
  435.             const locationField = document.getElementById('id_location-{{ document.id }}');
  436.             const dateField = document.getElementById('id_date-{{ document.id }}');
  437.             const timeField = document.getElementById('id_time-{{ document.id }}');
  438.             const formFeedback = document.getElementById('form-termin-feedback-{{ document.id }}');
  439.             // Clear previous validation messages
  440.             const inputs = form.querySelectorAll('.invalid-feedback');
  441.             inputs.forEach(feedback => feedback.textContent = '');
  442.             let isValid = true;
  443.             // Validate Name
  444.             if (!nameField.value.trim()) {
  445.                 isValid = false;
  446.                 nameField.nextElementSibling.textContent = '{% if lang == "de" %}Bitte geben Sie Ihren Namen ein.{% else %}Please enter your name.{% endif %}';
  447.             }
  448.             // Validate Email
  449.             const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  450.             if (!emailField.value.trim() || !emailRegex.test(emailField.value)) {
  451.                 isValid = false;
  452.                 emailField.nextElementSibling.textContent = '{% if lang == "de" %}Bitte geben Sie eine gültige E-Mail-Adresse ein.{% else %}Please enter a valid email address.{% endif %}';
  453.             }
  454.             // Validate Service
  455.             if (!serviceField.value) {
  456.                 isValid = false;
  457.                 serviceField.nextElementSibling.textContent = '{% if lang == "de" %}Bitte wählen Sie einen Service.{% else %}Please choose a service.{% endif %}';
  458.             }
  459.             // Validate Location
  460.             if (!locationField.value) {
  461.                 isValid = false;
  462.                 locationField.nextElementSibling.textContent = '{% if lang == "de" %}Bitte wählen Sie einen Standort.{% else %}Please choose a location.{% endif %}';
  463.             }
  464.             // Validate Date
  465.             if (!dateField.value.trim()) {
  466.                 isValid = false;
  467.                 dateField.nextElementSibling.textContent = '{% if lang == "de" %}Bitte wählen Sie ein Datum.{% else %}Please select a date.{% endif %}';
  468.             }
  469.             // Validate Time
  470.             if (!timeField.value) {
  471.                 isValid = false;
  472.                 timeField.nextElementSibling.textContent = '{% if lang == "de" %}Bitte wählen Sie eine Zeit.{% else %}Please select a time.{% endif %}';
  473.             }
  474.             // If validation fails, do not proceed
  475.             if (!isValid) {
  476.                 return;
  477.             }
  478.             // Disable the button
  479.             formBtn.disabled = true;
  480.             try {
  481.                 // Prepare the form data
  482.                 const formData = new FormData(form);
  483.                 const response = await fetch(form.action, {
  484.                     method: form.method,
  485.                     body: formData,
  486.                 });
  487.                 const result = await response.json();
  488.                 if (result.success) {
  489.                     formFeedback.textContent = '{% if lang == "de" %}Termin erfolgreich gebucht.{% else %}Booking successfully completed.{% endif %}';
  490.                 } else {
  491.                     formFeedback.textContent = '{% if lang == "de" %}Etwas ist schief gelaufen.{% else %}Something went wrong.{% endif %}';
  492.                     if(result.error) {
  493.                         console.error("Mailer Error: ", result.error);
  494.                     }
  495.                 }
  496.             } catch (error) {
  497.                 formFeedback.textContent = '{% if lang == "de" %}Etwas ist schief gelaufen.{% else %}Something went wrong.{% endif %}';
  498.                 console.error('{% if lang == "de" %}Buchung fehlgeschlagen, Fehler:{% else %}Booking failed, error:{% endif %}', error);
  499.             }
  500.             // Re-enable the button
  501.             formBtn.disabled = false;
  502.         });
  503.     </script>
  504. {% endif %}
  505. {% endblock %}