templates/web/chatbot-page.html.twig line 1

Open in your IDE?
  1. {% extends 'web/base.html.twig' %}
  2. {% block title %}Pitaj Slađanu – 2sweet.eu{% endblock %}
  3. {% block body %}
  4.     {{ include('web/components/inner/breadcrumb.html.twig') }}
  5.     <div class="bgWhite">
  6.         <div class="container">
  7.             <div class="emptySpace-xs40 emptySpace80"></div>
  8.             <div class="row">
  9.                 <div class="col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3" style="text-align:center;">
  10.                     <img src="{{ asset('img/sweet.png') }}" alt="Slađana" style="height:60px; margin-bottom:20px;">
  11.                     <h2 class="h2">Pitaj Slađanu</h2>
  12.                     <div class="emptySpace15"></div>
  13.                     <p class="normall" style="color:#888;">
  14.                         Slađana je naša slatka asistentica — pitaj je sve o tortama, kolačima, cijenama i dostavi.
  15.                         Za osobni upit, pošalji nam poruku direktno iz chata.
  16.                     </p>
  17.                 </div>
  18.             </div>
  19.             <div class="emptySpace-xs30 emptySpace50"></div>
  20.             <div class="row">
  21.                 <div class="col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3">
  22.                     <div id="sladana-embed" style="
  23.                         background: #fff9f6;
  24.                         border: 1px solid #ead7d2;
  25.                         border-radius: 16px;
  26.                         box-shadow: 0 10px 40px rgba(0,0,0,0.1);
  27.                         overflow: hidden;
  28.                         display: flex;
  29.                         flex-direction: column;
  30.                         height: 560px;
  31.                     ">
  32.                         <div class="sibi-header" style="flex-shrink:0;">
  33.                             <span>Slađana – slatka asistentica</span>
  34.                         </div>
  35.                         <div class="sibi-messages" id="page-sibi-messages" aria-live="polite" style="flex:1; overflow-y:auto;"></div>
  36.                         <div class="sibi-quick" id="page-sibi-quick"></div>
  37.                         <form class="sibi-form" id="page-sibi-form">
  38.                             <input class="sibi-input" id="page-sibi-input" type="text" placeholder="Upiši poruku..." autocomplete="off" />
  39.                             <button class="sibi-send" type="submit">Pošalji</button>
  40.                         </form>
  41.                     </div>
  42.                 </div>
  43.             </div>
  44.             <div class="emptySpace-xs40 emptySpace80"></div>
  45.         </div>
  46.     </div>
  47.     <div class="footerSeparator"></div>
  48.     <div class="emptySpace-xs30 emptySpace50"></div>
  49. {% endblock %}
  50. {% block javascripts %}
  51.     {{ parent() }}
  52.     <script>
  53.     // Inicijalizacija chata na zasebnoj stranici
  54.     (function () {
  55.         var sessionToken = null;
  56.         var isWaiting = false;
  57.         var inquiryFormVisible = false;
  58.         var messagesEl = document.getElementById('page-sibi-messages');
  59.         var quickEl    = document.getElementById('page-sibi-quick');
  60.         var form       = document.getElementById('page-sibi-form');
  61.         var input      = document.getElementById('page-sibi-input');
  62.         if (!messagesEl) return;
  63.         function addMessage(text, who) {
  64.             var msg = document.createElement('div');
  65.             msg.className = 'sibi-message ' + who;
  66.             var bubble = document.createElement('div');
  67.             bubble.className = 'sibi-bubble';
  68.             bubble.textContent = text;
  69.             msg.appendChild(bubble);
  70.             messagesEl.appendChild(msg);
  71.             messagesEl.scrollTop = messagesEl.scrollHeight;
  72.         }
  73.         function showTyping() {
  74.             var el = document.createElement('div');
  75.             el.className = 'sibi-message bot sibi-typing';
  76.             el.id = 'page-typing';
  77.             el.innerHTML = '<div class="sibi-bubble"><span class="sibi-dot"></span><span class="sibi-dot"></span><span class="sibi-dot"></span></div>';
  78.             messagesEl.appendChild(el);
  79.             messagesEl.scrollTop = messagesEl.scrollHeight;
  80.         }
  81.         function hideTyping() {
  82.             var el = document.getElementById('page-typing');
  83.             if (el) el.parentNode.removeChild(el);
  84.         }
  85.         function ensureSession(cb) {
  86.             if (sessionToken) { cb(sessionToken); return; }
  87.             fetch('/chatbot/session', { method: 'POST', headers: { 'Content-Type': 'application/json' } })
  88.                 .then(function (r) { return r.json(); })
  89.                 .then(function (d) { sessionToken = d.session_token; cb(sessionToken); });
  90.         }
  91.         function setQuickReplies(items) {
  92.             quickEl.innerHTML = '';
  93.             items.forEach(function (item) {
  94.                 if (item.href) {
  95.                     var a = document.createElement('a');
  96.                     a.href = item.href; a.textContent = item.label; a.rel = 'noopener';
  97.                     quickEl.appendChild(a);
  98.                 } else if (item.label === 'Pošalji upit') {
  99.                     var btn = document.createElement('button');
  100.                     btn.type = 'button'; btn.textContent = item.label;
  101.                     btn.addEventListener('click', function () { openInquiryForm(); });
  102.                     quickEl.appendChild(btn);
  103.                 } else {
  104.                     var btn2 = document.createElement('button');
  105.                     btn2.type = 'button'; btn2.textContent = item.label;
  106.                     btn2.addEventListener('click', function () { sendMessage(item.payload || item.label); });
  107.                     quickEl.appendChild(btn2);
  108.                 }
  109.             });
  110.         }
  111.         function sendMessage(text) {
  112.             if (!text || isWaiting || inquiryFormVisible) return;
  113.             var raw = text.trim();
  114.             if (!raw) return;
  115.             addMessage(raw, 'user');
  116.             quickEl.innerHTML = '';
  117.             isWaiting = true;
  118.             input.disabled = true;
  119.             showTyping();
  120.             ensureSession(function (token) {
  121.                 fetch('/chatbot/message', {
  122.                     method: 'POST',
  123.                     headers: { 'Content-Type': 'application/json' },
  124.                     body: JSON.stringify({ message: raw, session_token: token })
  125.                 })
  126.                 .then(function (r) { return r.json(); })
  127.                 .then(function (d) {
  128.                     hideTyping();
  129.                     isWaiting = false;
  130.                     input.disabled = false;
  131.                     input.focus();
  132.                     if (d.session_token) sessionToken = d.session_token;
  133.                     if (d.response) addMessage(d.response, 'bot');
  134.                     setQuickReplies([
  135.                         { label: 'Pošalji upit' },
  136.                         { label: 'Kalkulator', href: '/svadbeni-kalkulator' }
  137.                     ]);
  138.                 })
  139.                 .catch(function () {
  140.                     hideTyping(); isWaiting = false; input.disabled = false;
  141.                     addMessage('Ups, problem s vezom. Probaj ponovo! 😅', 'bot');
  142.                 });
  143.             });
  144.         }
  145.         function openInquiryForm() {
  146.             if (inquiryFormVisible) return;
  147.             inquiryFormVisible = true;
  148.             var wrapper = document.createElement('div');
  149.             wrapper.className = 'sibi-inquiry-form';
  150.             wrapper.innerHTML = [
  151.                 '<p class="sibi-inquiry-title">Pošalji upit majstorima 🍰</p>',
  152.                 '<input type="text" class="sibi-inq-input" id="pinq-name" placeholder="Ime i prezime *" />',
  153.                 '<input type="tel" class="sibi-inq-input" id="pinq-phone" placeholder="Broj mobitela *" />',
  154.                 '<input type="email" class="sibi-inq-input" id="pinq-email" placeholder="Email *" />',
  155.                 '<input type="text" class="sibi-inq-input" id="pinq-date-place" placeholder="Datum i mjesto isporuke" />',
  156.                 '<input type="number" class="sibi-inq-input" id="pinq-guests" placeholder="Broj gostiju" min="1" />',
  157.                 '<select class="sibi-inq-input" id="pinq-category">',
  158.                 '  <option value="">Prigoda...</option>',
  159.                 '  <option>Vjenčanje</option><option>Krštenje</option><option>Rođendan</option>',
  160.                 '  <option>Pričest / Krizma</option><option>Korporativni event</option><option>Ostalo</option>',
  161.                 '</select>',
  162.                 '<textarea class="sibi-inq-input" id="pinq-message" rows="3" placeholder="Opis torte ili kolača..."></textarea>',
  163.                 '<div class="sibi-photo-upload">',
  164.                 '  <input type="file" id="pinq-photos" accept="image/*" multiple style="display:none;">',
  165.                 '  <label for="pinq-photos" class="sibi-inq-photo-label">📷 Dodaj fotografije (max 6)</label>',
  166.                 '  <div id="pinq-photos-preview" class="sibi-photos-preview"></div>',
  167.                 '</div>',
  168.                 '<div class="sibi-inq-actions">',
  169.                 '  <button type="button" id="pinq-submit" class="sibi-inq-btn-send">Pošalji upit 🚀</button>',
  170.                 '  <button type="button" id="pinq-cancel" class="sibi-inq-btn-cancel">Odustani</button>',
  171.                 '</div>',
  172.                 '<p class="sibi-inq-note">* Obavezna polja</p>',
  173.             ].join('');
  174.             messagesEl.appendChild(wrapper);
  175.             messagesEl.scrollTop = messagesEl.scrollHeight;
  176.             wrapper.querySelector('#pinq-photos').addEventListener('change', function () {
  177.                 var preview = document.getElementById('pinq-photos-preview');
  178.                 preview.innerHTML = '';
  179.                 Array.from(this.files).slice(0, 6).forEach(function (file) {
  180.                     var reader = new FileReader();
  181.                     reader.onload = function (e) {
  182.                         var img = document.createElement('img'); img.src = e.target.result; preview.appendChild(img);
  183.                     };
  184.                     reader.readAsDataURL(file);
  185.                 });
  186.             });
  187.             document.getElementById('pinq-cancel').addEventListener('click', function () {
  188.                 wrapper.parentNode.removeChild(wrapper);
  189.                 inquiryFormVisible = false;
  190.                 setQuickReplies([{ label: 'Pošalji upit' }, { label: 'Kalkulator', href: '/svadbeni-kalkulator' }]);
  191.             });
  192.             document.getElementById('pinq-submit').addEventListener('click', function () {
  193.                 var name  = document.getElementById('pinq-name').value.trim();
  194.                 var phone = document.getElementById('pinq-phone').value.trim();
  195.                 var email = document.getElementById('pinq-email').value.trim();
  196.                 if (!name || !phone || !email) { alert('Upiši ime, broj mobitela i email!'); return; }
  197.                 var btn = document.getElementById('pinq-submit');
  198.                 btn.disabled = true; btn.textContent = 'Šaljem...';
  199.                 var fd = new FormData();
  200.                 fd.append('name', name);
  201.                 fd.append('phone', phone);
  202.                 fd.append('email', email);
  203.                 fd.append('date_place', document.getElementById('pinq-date-place').value.trim());
  204.                 fd.append('guests', parseInt(document.getElementById('pinq-guests').value) || 0);
  205.                 fd.append('category', document.getElementById('pinq-category').value);
  206.                 fd.append('message', document.getElementById('pinq-message').value.trim());
  207.                 fd.append('session_token', sessionToken || '');
  208.                 var photoInput = document.getElementById('pinq-photos');
  209.                 if (photoInput && photoInput.files.length > 0) {
  210.                     Array.from(photoInput.files).slice(0, 6).forEach(function (f) { fd.append('photos[]', f); });
  211.                 }
  212.                 fetch('/chatbot/inquiry', { method: 'POST', body: fd })
  213.                     .then(function (r) {
  214.                         if (!r.ok) { throw new Error('server'); }
  215.                         return r.json();
  216.                     })
  217.                     .then(function (d) {
  218.                         wrapper.parentNode.removeChild(wrapper);
  219.                         inquiryFormVisible = false;
  220.                         addMessage(d.message || 'Upit poslan! Javimo se uskoro. 🍰', 'bot');
  221.                     })
  222.                     .catch(function () {
  223.                         btn.disabled = false; btn.textContent = 'Pošalji upit 🚀';
  224.                         alert('Greška pri slanju. Pokušaj ponovo.');
  225.                     });
  226.             });
  227.         }
  228.         // Pozdrav
  229.         addMessage('Bok! Ja sam Slađana, tvoja slatka asistentica iz 2sweet slastičarnice. 🍰', 'bot');
  230.         addMessage('Tu sam da ti pomognem odabrati savršenu tortu ili kolače za tvoj poseban dan.', 'bot');
  231.         addMessage('O čemu se radi?', 'bot');
  232.         setQuickReplies([
  233.             { label: 'Svadbena torta' },
  234.             { label: 'Torta za posebnu prigodu' },
  235.             { label: 'Kolači i desert stol' },
  236.             { label: 'Cijena i dostava' },
  237.             { label: 'Pošalji upit' }
  238.         ]);
  239.         form.addEventListener('submit', function (e) {
  240.             e.preventDefault();
  241.             var val = input.value;
  242.             input.value = '';
  243.             sendMessage(val);
  244.         });
  245.     })();
  246.     </script>
  247. {% endblock %}