1<!DOCTYPE html> 2<html lang="pt"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Amapizza</title> 6 <meta name="csrf-token" content="HDBg9B2KzZHDdOKTakPwEkNffqEqBE0Fw69HVnx2"> 7 <link rel="icon" type="image/png" href="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/thumbnail/5baf8b77ddb9e47946c876fd56e66c2c.png"> 8 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> 9 <link href="/assets/css/framework7.css" rel="stylesheet"> 10 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.css" /> 11 <!-- Light or Dark Theme --> 12 <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet"> 13 <style> 14 /* Importação da fonte Circular Std Book */ 15 @font-face { 16 font-family: 'Circular Std'; 17 src: url('/assets/font/Circular-Std/CircularStd-Book.woff2') format('woff2'), 18 url('/assets/font/Circular-Std/CircularStd-Book.woff') format('woff'); 19 font-weight: normal; 20 font-style: normal; 21 } 22 23 /* Importação da fonte Circular Std Book Italic */ 24 @font-face { 25 font-family: 'Circular Std'; 26 src: url('/assets/font/Circular-Std/CircularStd-BookItalic.woff2') format('woff2'), 27 url('/assets/font/Circular-Std/CircularStd-BookItalic.woff') format('woff'); 28 font-weight: normal; 29 font-style: italic; 30 } 31 32 /* Importação da fonte Circular Std Medium */ 33 @font-face { 34 font-family: 'Circular Std'; 35 src: url('/assets/font/Circular-Std/CircularStd-Medium.woff2') format('woff2'), 36 url('/assets/font/Circular-Std/CircularStd-Medium.woff') format('woff'); 37 font-weight: 500; /* Medium é geralmente considerado 500 */ 38 font-style: normal; 39 } 40 41 /* Importação da fonte Circular Std Bold */ 42 @font-face { 43 font-family: 'Circular Std'; 44 src: url('/assets/font/Circular-Std/CircularStd-Bold.woff2') format('woff2'), 45 url('/assets/font/Circular-Std/CircularStd-Bold.woff') format('woff'); 46 font-weight: bold; /* Bold é geralmente considerado 700 */ 47 font-style: normal; 48 } 49 50 #navbar-area-search, #logo-area-search, #close-area-search, #input-navbar-search { 51 transition: all 0.5s ease; /* Suaviza a transição de todos os elementos */ 52 } 53 .gm-ui-hover-effect{ 54 display: none !important 55 } 56 .gm-style .gm-style-iw-d { 57 overflow: auto !important; 58 } 59 60 </style> 61 <!-- Custom CSS --> 62 <link href="/assets/css/main.css" rel="stylesheet"> 63 <!-- Lozad --> 64
64<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/lozad.min.js"></script>
64 65 <!-- JQuery --> 66
66<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
66 67 <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> 68
68<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
68 69 70 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css" /> 71
71<script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js"></script>
71 72 <!-- Date Range FlatPckr --> 73
73<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
73 74
74<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
74 75 <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" /> 76 <!-- Bootstrap Icons --> 77 <link href="https://unpkg.com/[email protected]/font/bootstrap-icons.css" rel="stylesheet"> 78 <!-- Remix Icons --> 79 <link href="https://cdn.jsdelivr.net/npm/[email protected]/fonts/remixicon.css" rel="stylesheet"> 80 <!-- Toastfy --> 81 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css"> 82
82<script src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
82 83 <!-- Cookie --> 84 <link rel="preconnect" href="https://fonts.googleapis.com"> 85 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 86 <link href='https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&amp;amp;display=swap' rel='stylesheet'><style> body{font-family: 'Roboto', sans-serif !important} </style> 87<style> 88 89 90 91 /* BACKGROUND */ 92 body{ 93 background: #ffffff !important; 94 } 95 .page{ 96 background: #ffffff !important; 97 } 98 footer{ 99 background: #f5f5f5 !important; 100 } 101 .bg-primary{ 102 background: #ff3a00 !important; 103 } 104 .hover\:bg-primary:hover:{ 105 background: #ff3a00 !important; 106 } 107 .background-secondary{ 108 background: #ffffff !important; 109 } 110 .background-color-details{ 111 background: #fff9e5 !important; 112 } 113 .bg-primary-dark{ 114 background: #cd0800 !important; 115 } 116 .bg-primary-light{ 117 background: #ff6228 !important; 118 } 119 .bg-primary-white{ 120 background: #ffd096 !important; 121 } 122 .border-primary{ 123 border-color: #ff3a00 !important; 124 } 125 .text-primary{ 126 color: #ff3a00 !important; 127 } 128 .hover\:text-primary:hover:{ 129 color: #ff3a00 !important; 130 } 131 .bg-secondary{ 132 background: #fbc500 !important; 133 } 134 .bg-secondary\:dark{ 135 background: #fbc500 !important; 136 } 137 .swiper-pagination-bullet-active{ 138 background-color: #ff3a00 !important; 139 } 140 .bg-tertiary, .hover-tertiary:hover{ 141 background: yellow !important; 142 } 143 .btn-primary{ 144 background: #ff3a00 !important; 145 transition-duration:0.1s; 146 } 147 .border-primary{ 148 border-color: #ff3a00 !important; 149 } 150 151 /* BUTTON */ 152 .button-primary{ 153 background: #ff3a00 !important; 154 border: 1px solid #ff6c32 !important; 155 border-radius: 0.5rem !important; 156 color: #f7f7f7 !important; 157 } 158 .button-primary:hover{ 159 background: #b90000 !important; 160 transition-duration:0.3s; 161 color: #f7f7f7 !important; 162 } 163 .button-outline-primary{ 164 border: 1px solid #ff3a00 !important; 165 border-radius: 0.5rem !important; 166 color: #ff3a00 !important; 167 } 168 .button-outline-primary:hover{ 169 background: #ff3a0010 !important; 170 border: 1px solid #ff6c32 !important; 171 border-radius: 0.5rem !important; 172 color: #ff3a00 !important; 173 } 174 .button-outline-primary\:active{ 175 background: #ff3a0020 !important; 176 border: 1px solid #ff6c32 !important; 177 border-radius: 0.5rem !important; 178 color: #ff3a00 !important; 179 } 180 .button-primary:hover{ 181 background: #cd0800 !important; 182 transition-duration:0.3s; 183 color: #fff !important; 184 } 185 .button-secondary{ 186 background: #fbc500 !important; 187 border: 1px solid #fff732 !important; 188 border-radius: 0.5rem !important; 189 color: #000000 !important; 190 } 191 .button-secondary:hover{ 192 background: #b57f00 !important; 193 transition-duration:0.3s; 194 color: #000000 !important; 195 } 196 .button-outline-secondary{ 197 border: 1px solid #fbc500 !important; 198 border-radius: 0.5rem !important; 199 color: #fff732 !important; 200 } 201 .button-outline-secondary:hover{ 202 background: #fbc50030 !important; 203 border: 1px solid #fff732 !important; 204 border-radius: 0.5rem !important; 205 color: #fbc500 !important; 206 } 207 .button-outline-secondary\:active{ 208 background: #fbc50050 !important; 209 border: 1px solid #fff732 !important; 210 border-radius: 0.5rem !important; 211 color: #ffff64 !important; 212 } 213 214 .button-red{ 215 background: #ef4444 !important; 216 border: 1px solid rgba(239, 68, 68, 0.5) !important; 217 border-radius: 0.5rem !important; 218 color: #fff !important; 219 } 220 .button-red:hover{ 221 background: #d32d2d !important; 222 transition-duration:0.3s; 223 color: #fff !important; 224 } 225 .button-outline-red{ 226 border: 1px solid #ef4444 !important; 227 border-radius: 0.5rem !important; 228 color: rgba(239, 68, 68, 0.5) !important; 229 } 230 .button-outline-red:hover{ 231 background: rgba(239, 68, 68, 0.1) !important; 232 border: 1px solid rgba(239, 68, 68, 0.5) !important; 233 border-radius: 0.5rem !important; 234 color: #ef4444 !important; 235 } 236 .button-outline-red\:active{ 237 background: rgba(239, 68, 68, 0.1) !important; 238 border: 1px solid rgba(239, 68, 68, 0.5) !important; 239 border-radius: 0.5rem !important; 240 color: rgba(239, 68, 68, 1) !important; 241 } 242 .button-white { 243 background: #fff !important; 244 border: 1px solid rgba(255, 255, 255, 0.5) !important; 245 border-radius: 0.5rem !important; 246 color: #000 !important; 247 } 248 .button-white:hover { 249 background: #f2f2f2 !important; 250 transition-duration: 0.3s; 251 color: #000 !important; 252 } 253 .button-outline-white { 254 border: 1px solid #fff !important; 255 border-radius: 0.5rem !important; 256 color: rgba(255, 255, 255, 1) !important; 257 } 258 .button-outline-white:hover { 259 background: rgba(255, 255, 255, 0.2) !important; 260 border: 1px solid rgba(255, 255, 255, 0.5) !important; 261 border-radius: 0.5rem !important; 262 color: #fff !important; 263 } 264 .button-outline-white\:active { 265 background: rgba(255, 255, 255, 0.5) !important; 266 border: 1px solid rgba(255, 255, 255, 0.5) !important; 267 border-radius: 0.5rem !important; 268 color: rgba(255, 255, 255, 1) !important; 269 } 270 271 272 .button-gray{ 273 background: rgba(0, 0, 0, 0.1) !important; 274 border: 1px solid rgba(0, 0, 0, 0.11) !important; 275 border-radius: 0.5rem !important; 276 color: rgba(0, 0, 0, 1) !important; 277 } 278 279 .button-gray\:active{ 280 background: rgba(0, 0, 0, 0.8) !important; 281 border: 1px solid rgba(0, 0, 0, 0.81) !important; 282 border-radius: 0.5rem !important; 283 color: rgba(255, 255, 255, 1) !important; 284 } 285 286 @media screen and (max-width: 900px) { 287 .button-responsive-primary{ 288 background: #ff3a00 !important; 289 border-top: 1px solid #ff6c32 !important; 290 color: #f7f7f7 !important; 291 } 292 293 } 294 @media screen and (min-width: 901px) { 295 .button-responsive-primary{ 296 background: #ff3a00 !important; 297 border: 1px solid #ff6c32 !important; 298 border-radius: 0.5rem !important; 299 color: #f7f7f7 !important; 300 bottom: 20px; 301 } 302 } 303 304 .radius-theme{ 305 border-radius: 0.5rem !important; 306 } 307 308 309 .gm-style .gm-style-iw-c{ 310 position: absolute; 311 -webkit-box-sizing: border-box; 312 box-sizing: border-box; 313 overflow: hidden; 314 top: 32px; 315 left: 0; 316 -webkit-transform: translate3d(-50%,-100%,0); 317 transform: translate3d(-50%,-100%,0); 318 background-color: #ff3a00 !important; 319 border: 1px solid #cd0800; 320 border-radius: 8px; 321 padding: 12px; 322 -webkit-box-shadow: none !important; 323 box-shadow: none !important; 324 display: -webkit-box; 325 display: -webkit-flex; 326 display: flex; 327 -webkit-box-orient: vertical; 328 -webkit-box-direction: normal; 329 -webkit-flex-direction: column; 330 flex-direction: column; 331 } 332 333 334 .gm-style .gm-style-iw-tc::after { 335 background: #ff3a00; 336 top: 29px !important; 337 content: ""; 338 height: 20px !important; 339 left: 0; 340 position: absolute; 341 bottom: -11px; 342 width: 25px; 343 border-top: none; 344 -webkit-filter: none !important; 345 filter: none !important; 346 -webkit-clip-path: polygon(100% 3%, 78% 36%, 59% 71%, 50% 96%, 41% 73%, 22% 36%, 0 2%) !important; 347 348 } 349 .gm-style .gm-style-iw-tc::before { 350 background: #cd0800; 351 top: 30.5px !important; 352 content: ""; 353 height: 20.1px !important; 354 left: -1; 355 position: absolute; 356 bottom: -11px; 357 width: 25.1px; 358 border-top: none; 359 -webkit-filter: none !important; 360 filter: none !important; 361 -webkit-clip-path: polygon(100% 3%, 78% 36%, 59% 71%, 53% 97%, 50% 98%, 46% 96%, 41% 73%, 22% 36%, 0 2%) !important; 362 } 363 364 365 .hover\:border-primary:hover{ 366 border-color: #ff3a00 367 } 368 369 370 .active-dott { 371 border: 2px dotted black; 372 } 373 374 .hover-dott { 375 border: 2px dotted transparent; 376 } 377 .hover-dott:hover { 378 border: 2px dotted black; 379 } 380 381</style> 382 383 384 <style> 385 .button-black{ 386 background: #111 !important; 387 border-radius: 0.5rem !important; 388 color: #fff !important; 389 border: 1px solid #fff !important; 390 } 391 .button-black:hover{ 392 background: #444 !important; 393 transition-duration:0.3s; 394 color: #111 !important; 395 border: 1px solid #222 !important; 396 } 397 .button-outline-black { 398 border: 1px solid #111 !important; 399 border-radius: 0.5rem !important; 400 color: rgba(0, 0, 0, 1) !important; 401 } 402 .button-outline-black:hover { 403 background: rgba(0, 0, 0, 0.1) !important; 404 border: 1px solid rgba(0, 0, 0, 0.5) !important; 405 border-radius: 0.5rem !important; 406 color: #111 !important; 407 } 408 .button-outline-black:active { 409 background: rgba(0, 0, 0, 0.1) !important; 410 border: 1px solid rgba(0, 0, 0, 0.5) !important; 411 border-radius: 0.5rem !important; 412 color: rgba(0, 0, 0, 1) !important; 413 } 414 415 </style> 416 417 <!-- FACEBOOK PIXEL --> 418 419
419<script> 420 !function(f,b,e,v,n,t,s) 421 {if(f.fbq)return;n=f.fbq=function(){n.callMethod? 422 n.callMethod.apply(n,arguments):n.queue.push(arguments)}; 423 if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; 424 n.queue=[];t=b.createElement(e);t.async=!0; 425 t.src=v;s=b.getElementsByTagName(e)[0]; 426 s.parentNode.insertBefore(t,s)}(window, document,'script', 427 'https://connect.facebook.net/en_US/fbevents.js'); 428 429// // fbq('init', '1218728262065392'); 430// 431// console.log("FBQ inicializado com matching:", []); 432 433 434 435 fbq('init', '1218728262065392'); 436 fbq('track', 'PageView'); 437 const params = new URLSearchParams(window.location.search); 438 const fbclid = params.get('fbclid'); 439 440 if (fbclid) { 441 const now = Date.now(); 442 const fbc = `fb.1.${Math.floor(now / 1000)}.${fbclid}`; 443 localStorage.setItem('fbc', fbc); 444 document.cookie = `_fbc=${fbc}; path=/`; 445 } 446 447 document.cookie.split(';').forEach(function(cookie) { 448 if (cookie.includes('_fbp')) { 449 localStorage.setItem('fbp', cookie.split('=')[1].trim()); 450 } 451 if (cookie.includes('_fbc')) { 452 localStorage.setItem('fbc', cookie.split('=')[1].trim()); 453 } 454 }); 455 456 window.fbPixelIsActive = true; 457 458// console.log("fbq typeof:", typeof fbq); 459// console.log("window.fbPixelIsActive:", window.fbPixelIsActive); 460// console.log("Cookies:", document.cookie); 461 462 463 </script>
463 464 <noscript> 465 <img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1218728262065392&ev=PageView&noscript=1"/> 466 </noscript> 467 468<!-- GOOGLE TAG MANAGER (HEAD) --> 469 470<!-- ANALYSTICS -->
vendor: 66 bytes, lines 470-471
470 471 <script async src="https://www.googletagmanager.com/gtag/js?id=
471AW-16448995597
vendor: 14 bytes, lines 471-472
471"></script> 472
472<script> 473
vendor: 139 bytes, lines 473-476
473window.dataLayer = window.dataLayer || []; 474 function gtag(){dataLayer.push(arguments);} 475 gtag('js', new Date()); 476 gtag('config', '
476AW-16448995597
vendor: 6 bytes, lines 476-477
476'); 477
477</script>
477 478<!-- TIKTOK ADS --> 479<!-- GOOGLE ADS --> 480
480<script async src="https://www.googletagmanager.com/gtag/js?id=16448995597"></script>
480 481
481<script> 482 window.dataLayer = window.dataLayer || []; 483 function gtag(){dataLayer.push(arguments);} 484 gtag('js', new Date()); 485 gtag('config', '16448995597'); 486 window.googleAdsIsActive = true; 487 window.googleAdsConversionId = '16448995597'; 488 window.googleAdsConversionLabel = 'JDCYCJKtnpUZEI2Cv6M9'; 489 </script>
489 490 491 492 493
493<script src="/assets/js/helpers/storeRedirectHelper.js"></script>
493 494 495 496 </head> 497 498 <body class=""> 499 <div id="app-loader" class="w-full h-screen flex items-center justify-center"> 500 <!-- <div class="w-16 h-16 relative mx-auto"> 501 <svg class="animate-spin h-full w-full block" viewBox="0 0 24 24"> 502 <circle class="opacity-10 bg-primary" cx="12" cy="12" r="11" stroke="currentColor" stroke-width="1.8" fill="transparent"></circle> 503 <circle class="opacity-100 absolute" cx="12" cy="12" r="11" stroke="#ff3a00" stroke-width="1.8" stroke-dasharray="10 52" stroke-linecap="round" fill="transparent"></circle> 504 </svg> 505</div> --> 506 507<!-- <div class="w-16 h-16 relative mx-auto"> 508 <img src="/assets/img/gif/basket.gif" alt="Loading..." class="w-full h-full object-contain" /> 509</div> --> 510 511<div class=" relative mx-auto" style="width: 120px; height: 120px;"> 512 <img src="/assets/img/gif/basket.gif" alt="Loading..." class="w-full h-full object-contain" /> 513</div> 514 </div> 515 <div id="app"> 516 517 <div class="panel panel-right panel-more panel-floating panel-resizable panel-init dark:bg-black border-l border-gray-400"> 518 <div class="page-content mt-5"> 519 <div class="list links-list"> 520 <ul> 521 <li class=" lg:hidden "> 522 <a href="/searchresults" class="panel-close external "> <div class="pr-2"><i class="bi bi-cart3"></i></div> 523 <div class="w-full"> Encomendar </div> 524 </a> 525 </li> 526 <li class=""> 527 <a href="/reserva" class="panel-close external "> <div class="pr-2"><i class="bi bi-calendar-check"></i></div> 528 <div class="w-full"> Reservar </div> 529 </a> 530 </li> 531 <li class=""> 532 <a href="/about" class="panel-close external "> <div class="pr-2"><i class="bi bi-briefcase"></i></div> 533 <div class="w-full"> Sobre nós </div> 534 </a> 535 </li> 536 <li class=""> 537 <a href="contact" class="panel-close external "> <div class="pr-2"><i class="bi bi-telephone-forward"></i></div> 538 <div class="w-full"> Contacto </div> 539 </a> 540 </li> 541 <li class=""> 542 <a href="/blog" class="panel-close external "> <div class="pr-2"><i class="bi bi-book"></i></div> 543 <div class="w-full"> Blog </div> 544 </a> 545 </li> 546 547 <li class="lg:hidden"> 548 <a id="open-auth" data-modal-target="auth" class="panel-close"> 549 <i class="bi bi-person-circle mr-2"></i> <div class="w-full">Entrar</div> 550 </a> 551 </li> 552 </ul> 553 </div> 554 </div> 555</div> <style> 556 .popover-cart { 557 width: 100%; 558 max-width: 400px; 559 box-sizing: border-box; 560} 561 562 .popover-cart .delete-cart { 563 display: inline-flex !important; 564 align-items: center; 565 justify-content: center; 566 color: #ef4444 !important; 567 opacity: 1 !important; 568 pointer-events: auto !important; 569 cursor: pointer; 570 } 571 572 .popover-cart .delete-cart i { 573 color: #ef4444 !important; 574 opacity: 1 !important; 575 } 576 577.store-top-highlight-item { 578 position: absolute; 579 inset: 0; 580 display: block; 581 opacity: 0; 582 pointer-events: none; 583 transition: opacity 0.45s ease; 584} 585 586.store-top-highlight-item.is-active { 587 position: relative; 588 opacity: 1; 589 pointer-events: auto; 590 z-index: 1; 591} 592 593/* Responsivo para telas pequenas */ 594@media (max-width: 480px) { 595 .popover-cart { 596 max-width: calc(100vw - 20px); 597 left: 50% !important; 598 transform: translateX(-50%) !important; 599 } 600} 601 602</style> 603 604 605 606<div id="main-navbar-shell" class="fixed w-full dark:border-zinc-500" style="top: var(--store-highlight-height, 0px); z-index: 9000 !important;"> 607 <div class="w-full relative dark:bg-black dark:bg-opacity-60 dark:backdrop-filter dark:backdrop-blur-xl" style="z-index: 550 !important;background-color:#f93b0b"> 608 609 <div class=" border-gray-400 border-b" style="border-color:#c70900" 610 > 611 <div class=" text-gray-900 ease-out duration-50 dark:border-zinc-500 dark:border-gray-700 ease-out duration-300"> 612 <div class="max-w-6xl grid lg:grid-cols-10 grid-cols- items-center lg:justify-between mx-auto px-4 gap-" style="color:#ffffff"> 613 <div id="navbar-area-search" class="lg:col-span-4 flex items-center lg:h-16 h-16 space-x-4 lg:pr-4 relative grid lg:grid-cols-4 grid-cols-1"> 614 <div id="logo-area-search" class="lg:inline-flex lg:w-auto w-full col-span-2"> 615 <a href="/" class="main-link external flex items-center lg:pt-1 lg:h-12 h-10"> 616 <div class="h-4"></div> 617 <img src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/0842a48e5579c23f2afc8df9d81b2ce2.png" class="logo-dark lg:h-12 h-10 lg:mr-3 mx-auto mt-4 lg:mt-0" alt="Amapizza" /> 618 619 620<img style="display: none" class="logo-light" src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/6706ef288778c744cbd16350c9c2d6e0.png" /> </a> 621 </div> 622 <div id="input-navbar-search" class="flex lg:col-span-2 col-span-3 items-center lg:space-x-2" onclick="showNavbarSearch()"> 623 <!-- <div class="w-full"> 624 <style> 625 .input-destaque { 626 box-shadow: 0 0 0 3px #facc15; /* amarelo (tailwind yellow-400) */ 627 border-color: #facc15 !important; 628 transition: box-shadow 0.3s ease, border-color 0.3s ease; 629 border-radius: 2px; 630 631 } 632</style> 633 634 635 636<div class="w-full border border-gray-400 shadow-sm dark:bg-zinc-950 dark:border-zinc-600 dark:text-white text-gray-700 rounded-md py-2 px-4 transition duration-300 ease-in-out bg-white flex items-center border border-gray-400 popup-open relative" style=" border-color: ;"> 637 <i class="bi bi-geo-alt-fill text-black"></i> 638 <input type="text" value="" data-current-lat="41.8483" data-current-lng="-87.6517" placeholder="Endereço" id="autocomplete" name="address" class="px-1 overflow-hidden text-black w-full bg-transparent cursor-pointer" required> 639 640</div> 641 642 643<div id="autocomplete-suggestions" class="text-gray-800 absolute bg-white shadow-md w-full mt-1 rounded-md overflow-hidden left-0 z-50" style="z-index: 9000 top: 100%"></div> 644 645 </div> --> 646 <div id="close-area-search" onclick="hideNavbarSearch()" class="hidden"> 647 <a class="py-1 px-2 rounded-full hover:bg-gray-100 hover:text-black"> 648 <i class="bi bi-x-lg text"></i> 649 </a> 650 </div> 651 </div> 652 </div> 653 <div class="lg:col-span-2 lg:flex hidden justify-center"> 654 </div> 655 <div class="lg:col-span-4 lg:flex hidden justify-end"> 656 <ul class="col-span-3 flex flex-col lg:items-center justify-end md:p-0 font-medium md:flex-row md:space-x-3 md:border-0"> 657 <li class="ml-auto hidden lg:inline-flex flex-shrink-0" style="color:#ffffff"> 658 <a href="/searchresults" class="inline-flex items-center whitespace-nowrap gap-1 text-md font-medium pl-1 pr-1 external rounded duration-200 font-normal hover:bg-gray-100 md:hover:bg-transparent md:p-0 dar
658k:text-white dark:hover:text-white md:dark:hover:bg-transparent"> 659 <i class="bi bi-cart3"></i> Encomendar 660 </a> 661 </li> 662 <li class="flex justify-end pt-0.5" style="color:#ffffff"> 663 <a id="open-auth" data-modal-target="auth" class="truncate cursor-pointer flex px-4 py-2 md:mr-0 "> 664 <i class="bi bi-person-circle mr-2"></i> Entrar 665 </a> 666 667 668 <button style="color:#ffffff" type="button" class="menu-sidebar flex text-3xl dark:text-white rounded-full md:mr-0 panel-open" data-panel=".panel-more"> 669 <i class="bi bi-three-dots px-2"></i> 670 </button> 671 <button style="color:#ffffff" class="flex text-sm text-3xl dark:text-white lg:hidden hidden rounded-full md:mr-0 lg:mt-0 mt-0.5 popover-open" data-popover=".popover-more"> 672 <i class="bi bi-three-dots px-2"></i> 673 </button> 674 <div class="popover popover-more"> 675 <div class="popover-angle"></div> 676 <div class="popover-inner"> 677 <div class="list"> 678 <ul> 679 <li> 680 <a href="/reserva" class="list-button text-gray-800 dark:text-gray-100 external "> 681 <i class="bi bi-calendar-check"></i> Reservar 682 </a> 683 </li> 684 <li> 685 <a href="/about" class="list-button text-gray-800 dark:text-gray-100 external "> 686 <i class="bi bi-briefcase"></i> Sobre nós 687 </a> 688 </li> 689 <li> 690 <a href="contact" class="list-button text-gray-800 dark:text-gray-100 external "> 691 <i class="bi bi-telephone-forward"></i> Contacto 692 </a> 693 </li> 694 <li> 695 <a href="/blog" class="list-button text-gray-800 dark:text-gray-100 external "> 696 <i class="bi bi-book"></i> Blog 697 </a> 698 </li> 699 </ul> 700 </div> 701 </div> 702 </div> 703 <button class="cart-navbar flex text-sm text-2xl dark:text-white rounded-full md:mr-0 -mt-1 pl-4 popover-open" style="color:#ffffff" data-popover=".popover-cart"> 704 <i class="cart-icon bi bi-cart pt-2"></i> 705 <sup class="lg:-ml-2 -ml-4 lg:mt-3 -mt-2"> 706 <small class="badge bg-black text-xs cart-badge">0</small> 707 </sup> 708 </button> 709 <div class="popover popover-cart rounded-lg border border-black shadow bg-white"> 710 <!-- <div class="popover popover-cart rounded-lg border border-black shadow bg-white" style="width:400px"> --> 711 <div class="popover-angle"></div> 712 <div class="popover-inner"> 713 <div class="list"> 714 <ul> 715 <div class="text-gray-600 px-6 py-4"> 716 <div class="flex flex-col"> 717 <div class="items-baseline gap-2 flex flex-wrap justify-between mb-2"> 718 <div> 719 <div class="items-start flex flex-col"> 720 <span class="text-[1.38rem] leading-7"> 721 <div class="items-baseline flex flex-wrap justify-start">
722 <span class="pr-1 text-primary text-xl dark:text-gray-200"> 723 Carrinho 724 </div> 725 </span> 726 </div> 727 </div> 728 <button class="popover-close ml-auto text-gray-400 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-100 transition-colors"> 729 <i class="bi bi-x-lg text-lg"></i> 730 </button> 731 </div> 732 <div class="text-neutral-800 flex items-center border-b mb-1 mt-1 dark:border-zinc-700"></div> 733 <div class="checkout-btn hidden"> 734 <div class="mt-3"> 735 <div class="text-neutral-500 text-sm cart-list"></div> 736 <div class="border-t text-neutral-500 text-md mt-3 pt-3 border-zinc-300 dark:border-zinc-600 border-solid"> 737 <div class="text-gray-600 dark:text-gray-300 flex font-semibold justify-between"> 738 <div>Total</div><span class="cart-total">0,00 â¬</span> 739 </div> 740 </div> 741</div> 742 </div> 743 <div class="anti-checkout-btn text-center flex space-x-4 items-center"> 744 <div> 745 <h1 class="text-4xl mb-2"> 746 <i class="bi bi-cart4"></i> 747 </h1> 748 </div> 749 <div class="text-left w-full pt-8 pb-12"> 750 <h3 class="text-md font-semibold mt-2">Seu carrinho está vazio</h3> 751 <div class="text-gray-500 text-sm"> 752 <p class="">Seus itens aparecerão aqui</p> 753 </div> 754 755 </div> 756 <div class="pt-1.5"> 757 <a class="items-start popover-close dark:bg-zinc-900 dark:border-zinc-600 text-gray-600 dark:text-gray-300 cursor-pointer inline-block font-semibold py-2 px-4 text-center text-sm border border-black border-solid rounded-full"> 758 Fechar 759 </a> 760 </div> 761 </div> 762 <div class="items-center text-sm mt-2 text-center w-full checkout-btn hidden"> 763 <!-- <button class="btn-go-checkout items-start button-primary cursor-pointer inline-block text-lg py-2 px-6 relative text-center w-full" >Continuar Checkout</button> --> 764 765 <button class="btn-go-checkout items-start button-primary cursor-pointer inline-block text-lg py-2 px-6 relative text-center w-full"> 766 Continuar Checkout 767 </button> 768 769 </div> 770 </div> 771 </div> 772 </ul> 773 </div> 774 </div> 775 </div> 776 </li> 777 </ul> 778 </div> 779 780 781 782 783 </div> 784 </div> 785 </div> 786 </div> 787</div> 788<div class="h-16 mt-0"></div> 789 790 791 792
793<script> 794 document.addEventListener('DOMContentLoaded', function () { 795 const banner = document.getElementById('store-top-highlight'); 796 const spacer = document.getElementById('store-top-highlight-spacer'); 797 const root = document.documentElement; 798 const items = banner ? banner.querySelectorAll('.store-top-highlight-item') : []; 799 const rotationDelay = 5000; 800 801 if (!banner) { 802 root.style.setProperty('--store-highlight-height', '0px'); 803 if (spacer) spacer.style.height = '0px'; 804 return; 805 } 806 807 const getActiveItem = function () { 808 return banner.querySelector('.store-top-highlight-item.is-active') || items[0] || null; 809 }; 810 811 const syncBannerHeight = function () { 812 const activeItem = getActiveItem(); 813 const h = activeItem ? activeItem.offsetHeight || 0 : 0; 814 root.style.setProperty('--store-highlight-height', h + 'px'); 815 if (spacer) spacer.style.height = h + 'px'; 816 }; 817 818 syncBannerHeight(); 819 window.addEventListener('resize', syncBannerHeight); 820 821 if (items.length <= 1) { 822 return; 823 } 824 825 let currentIndex = 0; 826 827 window.setInterval(function () { 828 items[currentIndex].classList.remove('is-active'); 829 830 currentIndex = (currentIndex + 1) % items.length; 831 832 items[currentIndex].classList.add('is-active'); 833 834 window.requestAnimationFrame(syncBannerHeight); 835 }, rotationDelay); 836 }); 837 838 // JavaScript 839 function navigateAndActivate(route, iconID) { 840 // Navigate 841 if(route == "/"){ 842 843 app.views.main.router.navigate("/", {animate: false}); 844 }else{ 845 app.preloader.show(); 846 app.views.main.router.navigate('/' + route + '/', {animate: false}); 847 } 848 $(".bi").each(function() { 849 var iconClasses = $(this).attr('class').split(' '); 850 for (var i = 0; i < iconClasses.length; i++) { 851 if (iconClasses[i].includes('-fill')) { 852 iconClasses[i] = iconClasses[i].replace('-fill', ''); 853 } 854 } 855 $(this).attr('class', iconClasses.join(' ')); 856 }); 857 var clickedIcon = $("#" + iconID); 858 var clickedIconClass = clickedIcon.attr('class').split(' '); 859 for (var i = 0; i < clickedIconClass.length; i++) { 860 if (clickedIconClass[i].startsWith('bi-') && !clickedIconClass[i].includes('-fill')) { 861 clickedIconClass[i] = clickedIconClass[i] + '-fill'; 862 } 863 } 864 clickedIcon.attr('class', clickedIconClass.join(' ')); 865 } 866 </script>
866 867 <div class="view view-main view-init" data-url="///"> 868 <div class="page absolute" data-name="/"> 869 870 <div class="ptr-content page-content" data-ptr-distance="120"> 871 <div class="ptr-preloader"> 872 <div class="preloader"></div> 873 <div class="ptr-arrow"></div> 874 </div> 875 876 <div id="a__7" class="relative"> 877 <!-- Slide --> 878 <div class="section-slide z-10"> 879 <div class="relative"> 880 <div class="swiper autoplay-slide"> 881 <div class="swiper-wrapper h-40vh lg:h-70vh"> 882 <div class="swiper-slide h-full w-full" style="background-color:#050505"> 883 <div class="max-w-6xl mx-auto flex items-center h-full px-4"> 884 <img class="lozad absolute top-0 left-0 object-cover w-full h-full" data-src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/original/63f9e4742f514192465edb2510987816.gif"/> <div class="bg-black bg-opacity-50 absolute top-0 left-0 object-cover w-full h-full"></div> <div class="relative lg:w-2/3" style="color:#ffffff"> 885 <div class="lg:text-4xl text-4xl font-semibold leading-thight lg:mb-2 mb-2">Amapizza ®</div> 886 <div class="lg:text-2xl lg:mb-4 text-md mt-1 mb-2"><p>Italianas & Brasileiras no Forno a Lenha</p> </div> 887 <div class="space-x-2 mt-5"> 888 <a href="/searchresults" class="external button-primary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Encomendar <i class="bi bi-arrow-right"></i></a> <a href="/reserva" class="external button-secondary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Reservar <i class="bi bi-arrow-right"></i></a> </div> 889 </div> 890 </div> 891 </div> 892 <div class="swiper-slide h-full w-full" style="background-color:#050505"> 893 <div class="max-w-6xl mx-auto flex items-center h-full px-4"> 894 <img class="lozad absolute top-0 left-0 object-cover w-full h-full" data-src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/original/930506de9f00c8427a988a245fbe7e0b.png"/> <div class="bg-black bg-opacity-50 absolute top-0 left-0 object-cover w-full h-full"></div> <div class="relative lg:w-2/3" style="color:#ffffff"> 895 <div class="lg:text-4xl text-4xl font-semibold leading-thight lg:mb-2 mb-2">Jiripoca ®</div> 896 <div class="lg:text-2xl lg:mb-4 text-md mt-1 mb-2"><p>Diversos pratos do Dia </p> </div> 897 <div class="space-x-2 mt-5"> 898 <a href="/store/jiripoca" class="external button-primary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Encomendar <i class="bi bi-arrow-right"></i></a> <a href="/reserva" class="external button-secondary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Reservar <i class="bi bi-arrow-right"></i></a> </div> 899 </div> 900 </div> 901 </div> 902 <div class="swiper-slide h-full w-full" style="background-color:#050505"> 903 <div class="max-w-6xl mx-auto flex items-center h-full px-4"> 904 <img class="lozad absolute top-0 left-0 object-cover w-full h-full" data-src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/original/8bdf5ff4ddd9970e7ff6c8b59b57b008.gif"/> <div class="bg-black bg-opacity-40 absolute top-0 left-0 object-cover w-full h-full"></div> <div class="relative lg:w-2/3" style="color:#ffffff"> 905 <div class="lg:text-4xl text-4xl font-semibold leading-thight lg:mb-2 mb-2">Dadinhos de Tapioca</div> 906 <div class="lg:text-2xl lg:mb-4 text-md mt-1 mb-2"><p>Crocrantes por Fora, Cremosos por Dentro</p> </div> 907 <div class="space-x-2 mt-5"> 908 <a href="/store/amapizza" class="external button-primary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Encomendar <i class="bi bi-arrow-right"></i></a> <a href="/reserva" class="external button-secondary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Reservar <i class="bi bi-arrow-right"></i></a> </div> 909 </div> 910 </div> 911 </div> 912 <div class="swiper-slide h-full w-full" style="background-color:#050505"> 913 <div class="max-w-6xl mx-auto flex items-center h-full px-4"> 914 <img class="lozad absolute top-0 left-0 object-cover w-full h-full" data-src="https://d2dabtcvjjecap.cloudfront.net/platform/slim/c611b227d32286af1fa1299b420a5f2d.png"/> <div class="relative lg:w-2/3" style="color:#ffffff"> 915 <div class="lg:text-4xl text-4xl font-semibold leading-thight lg:mb-2 mb-2"></div> 916 <div class="lg:text-2xl lg:mb-4 text-md mt-1 mb-2"> </div> 917 <div class="space-x-2 mt-5"> 918 </div> 919 </div> 920 </div> 921 </div> 922 </div> 923 </div> 924 <div style="margin-top: -40px !important;z-index:1000000000 !important;margin-bottom:40px !important" class="autoplay-slide-pagination hidden lg:block slide-pagination-relative"></div> 925 <div style="right:30px !important" class="swiper-button-next autoplay-slide-next bg-white rounded-full w-20 h-20 shadow flex items-center justify-center"> 926 <i class="bi bi-arrow-right"></i> 927 </div> 928 <div style="left:30px !important" class="swiper-button-prev autoplay-slide-prev bg-white rounded-full w-20 h-20 shadow flex items-center justify-center"> 929 <i class="bi bi-arrow-left"></i> 930 </div> 931 932 </div> 933</div> </div> 934 <div id="a__16" class="relative"> 935 <!-- Column --> 936 <div class="max-w-6xl mx-auto lg:py-8 py-5 px-4"> 937 <div class="lg:gap-4 grid lg:grid-cols-3 grid-cols-1"> 938 <div class="text-gray-900 dark:text-gray-100 duration-200 "> 939 <a href="/searchresults" class="external
939cursor-pointer"> 940 <img src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/6b3c4200ae8dfe903076904e9a7fa6b7.png" class="w-full mb-3 align-middle object-cover rounded overflow-clip h-48 " /> 941 </a> 942 <a href="/searchresults" class="external cursor-pointer"> 943 <h1 class="text-lg font-semibold mb-1">Delivery ou Takeaway</h1> 944 <div class="text-sm mb-4"></div> 945 </a> 946 <div class="space-x-2 pb-10 lg:pb-2"> 947 <a href="/searchresults" class="external button-primary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Peça agora <i class="bi bi-arrow-right"></i></a> </div> 948 </div> 949 <div class="text-gray-900 dark:text-gray-100 duration-200 "> 950 <a href="/store/amapizza" class="external cursor-pointer"> 951 <img src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/f4f297f11ab48c1d4a662bdad0b63f80.png" class="w-full mb-3 align-middle object-cover rounded overflow-clip h-48 " /> 952 </a> 953 <a href="/store/amapizza" class="external cursor-pointer"> 954 <h1 class="text-lg font-semibold mb-1">Amapizza</h1> 955 <div class="text-sm mb-4"></div> 956 </a> 957 <div class="space-x-2 pb-10 lg:pb-2"> 958 <a href="/store/amapizza" class="external button-primary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Encomendar Agora <i class="bi bi-arrow-right"></i></a> <a href="/reserva" class="external button-secondary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Reservar <i class="bi bi-arrow-right"></i></a> </div> 959 </div> 960 <div class="text-gray-900 dark:text-gray-100 duration-200 "> 961 <a href="/store/jiripoca" class="external cursor-pointer"> 962 <img src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/63b70a02ed691ece7967a175b6d613e6.png" class="w-full mb-3 align-middle object-cover rounded overflow-clip h-48 " /> 963 </a> 964 <a href="/store/jiripoca" class="external cursor-pointer"> 965 <h1 class="text-lg font-semibold mb-1">Jiripoca</h1> 966 <div class="text-sm mb-4"></div> 967 </a> 968 <div class="space-x-2 pb-10 lg:pb-2"> 969 <a href="/store/jiripoca" class="external button-primary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Encomendar Agora <i class="bi bi-arrow-right"></i></a> <a href="/reserva" class="external button-secondary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Reservar <i class="bi bi-arrow-right"></i></a> </div> 970 </div> 971 </div> 972</div> </div> 973 <div id="a__5" class="relative"> 974 <!-- CTA --> 975 <div class="hidden-app"> 976 <div class="lg:pt-5 lg:pb-10 py-5" > 977 <div class="" > 978 <div class="max-w-6xl mx-auto px-4 shine"> 979 <div style='background-image: url("");background-color: #ff3900;' class="items-stretch dark:bg-zinc-900 hover-dott lg:text-left text-center rounded-lg bg-no-repeat text-neutral-800 gap-4 grid text-sm border-neutral-200 dark:border-zinc-700 p-6 overflow-hidden"> 980 <div class="lg:grid lg:grid-cols-10 gap-5 space-y-4"> 981 <div class="flex col-span-5 items-center justify-center pb-0"> 982 <img class="lg:w-full w-full rounded-lg float" src="https://d2dabtcvjjecap.cloudfront.net/platform/slim/34ff91ef47c4abb252a3dfba650db02e.png" alt=""> 983 </div> 984 <div class="col-span-4 flex items-center" style='color: #ffffff;'> 985 <div> 986 <h2 class="lg:text-3xl text-2xl font-bold mb-2"> Descarregue a nossa App</h2> 987 <div class="mb-6 mt-1 text-lg"><div class="mb-6 mt-1 text-lg"> 988<p class="">Instale nossa app Android e iOS da Google Play ou App Store e desfrute de benefícios exclusivos!</p> 989</div></div> 990 <div class="space-x-2 mb-5"> 991 <a href="https://play.google.com/store/apps/details?id=com.lojadodia.amapizza&pli=1" class="external button-secondary duration-200 font-medium text-sm px-5 py-2.5 mb-2"><i class="bi bi-google-play"></i> Google Play</a> <a href="https://apps.apple.com/pt/app/amapizza/id1670447588" class="external button-secondary duration-200 font-medium text-sm px-5 py-2.5 mb-2"><i class="bi bi-apple"></i> App Store</a> </div> 992 </div> 993 994 </div> 995 <div></div> 996 </div> 997 </div> 998 </div> 999 </div> 1000 </div> 1001</div> </div> 1002 <div id="a__27" class="relative"> 1003 <!-- Information --> 1004 <div class=""> 1005 <div class="max-w-6xl mx-auto relative"> 1006 <div class="lg:py-8 py-5 px-4 flex flex-wrap lg:flex-nowrap lg:gap-14 lg:flex-row"> 1007 <!-- Image Container --> 1008 <div class="lg:w-1/3 w-full pt-1 pb-4"> 1009 <img class="w-full object-cover h-64 roun
1009ded-lg" src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/d0059ebf116da7c3b854b1bf8fe45f05.png" alt=""> 1010 </div> 1011 <!-- Text Container --> 1012 <div class="flex w-full lg:w-2/3"> 1013 <div class=""> 1014 <h1 class="text-2xl font-semibold mb-2">ð A nossa história começa aqui!</h1> 1015 <div class="text-md mb-5 opacity-60"><p class="" data-start="213" data-end="345">Bem-vindo à <strong data-start="225" data-end="237">Amapizza</strong>, onde a arte das <strong data-start="255" data-end="306">pizzas italianas e brasileiras no forno a lenha</strong> ganha vida com sabor, alma e tradição.</p> 1016<p class="" data-start="213" data-end="345"> </p> 1017<p class="" data-start="347" data-end="474">Cada receita é feita com ingredientes frescos e carinho, criando momentos que vão muito além da refeição — são memórias à mesa.</p> 1018<p class="" data-start="476" data-end="540"> </p> 1019<p class="" data-start="476" data-end="540"><strong>Na Amapizza, sabor é afeto. E cada fatia conta uma história.</strong></p></div> 1020 <div class="space-x-2"> 1021 <a href="/about" class="external button-secondary duration-200 font-medium text-sm px-5 py-2.5 mb-2">Conheça a Nossa Essência <i class="bi bi-arrow-right"></i></a> </div> 1022 </div> 1023 </div> 1024 </div> 1025 </div> 1026</div> </div> 1027 <div id="a__30" class="relative"> 1028 <!-- Location --> 1029 <div class="max-w-6xl mx-auto lg:py-8 py-5 px-4"> 1030 <div class="text-xl font-medium items-center mb-5 text-gray-900 dark:text-gray-100 lg:flex items-center"> 1031 <div class="w-full text-center "> 1032 <h4 class="text-2xl font-semibold"> 1033 NOSSAS LOJAS 1034 </h4> 1035 <p class="text-sm text-gray-600 font-normal"></p> 1036 </div> 1037 </div> 1038 <div class="lg:gap-4 grid lg:grid-cols-2 grid-cols-1"> 1039
1039<script> 1040 $(function(){showMap("map_33", 38.75699537671437, -9.247340570040109, [{"lat":"38.75699537671437","lng":"-9.247340570040109","mapa_logo":"https:\/\/d2dabtcvjjecap.cloudfront.net\/platform\/slim\/f1a29230502863175fd82328cf19317f.png"}], false, 15)}) 1041 </script>
1041 1042 <div> 1043 <h4 class="text-xl mb-4 mt-4 text-center"> 1044 Amapizza 1045 </h4> 1046 <div class="block w-full overflow-hidden bg-gray-50 border lg:h-96 h-52 border-gray-200 rounded shadow dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700"> 1047 <div id="map_33" class="w-full h-full"></div> 1048 </div> 1049 </div> 1050 1051
1051<script> 1052 $(function(){showMap("map_92", 38.75810127515434, -9.246583489939473, [{"lat":"38.75699537671437","lng":"-9.247340570040109","mapa_logo":"https:\/\/d2dabtcvjjecap.cloudfront.net\/platform\/slim\/f1a29230502863175fd82328cf19317f.png"},{"lat":"38.75810127515434","lng":"-9.246583489939473","mapa_logo":"https:\/\/d2dabtcvjjecap.cloudfront.net\/platform\/slim\/6aa8346432c493201f472a0fdb3e48fe.png"}], false, 15)}) 1053 </script>
1053 1054 <div> 1055 <h4 class="text-xl mb-4 mt-4 text-center"> 1056 Jiripoca 1057 </h4> 1058 <div class="block w-full overflow-hidden bg-gray-50 border lg:h-96 h-52 border-gray-200 rounded shadow dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700"> 1059 <div id="map_92" class="w-full h-full"></div> 1060 </div> 1061 </div> 1062 1063 </div> 1064</div> </div> 1065 <a href="javascript:void(0);" onclick="backToStore()"> 1066<button class="hidden checkout-btn fixed bottom-9 mb-1.5 lg:mb-0 lg:w-auto w-full text-lg lg:shadow-xl lg:left-1/2 transform lg:-translate-x-1/2 text-gray-800 z-10 text-sm font-medium"> 1067 <div class="w-full h-full left-0 top-0 button-responsive-primary text-xl overflow-hidden"> 1068 <div class="shine px-10 lg:py-2.5 py-2.5" style="border-radius: "> 1069 <span class="checkout-btn-name truncate"></span> <span class="checkout-btn-total hidden px-2 py-0.5 background-secondary rounded text-black text-sm font-normal"></span> 1070 </div> 1071 </div> 1072</button> 1073</a> <div class="anti-hidden-app lg:hidden block mt-44"></div> 1074 1075<footer class=" dark:bg-black pb-10 hidden-app" style="background:#000000 !important" > 1076 <div class="max-w-6xl mx-auto mb-10"> 1077 <div class="grid lg:grid-cols-5 grid-cols-2 gap-2 px-4"> 1078 <div class="text-neutral-800 float-left text-sm pr-3 pt-10"> 1079 <ul> 1080 <li class="text-[0.70rem] mb-3"> 1081 <div class="text-gray-800 dark:text-zinc-400 mb-4 opacity-50" style="color:#ffffff"> Formas de Pagamento </div> 1082 </li> 1083 <li class="text-[0.81rem]"> 1084 <a href="#" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1085 <div class="mb-1"><img class="w-20" src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/f3d886f56ad83c56adc8de0e49589d6c.png " alt=""></div> 1086 </a> 1087 </li> 1088 <li class="text-[0.81rem]"> 1089 <a href="#" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1090 <div class="mb-1"><img class="w-20" src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/aecf973f221bb23c8b90ba94a71cca5b.png " alt=""></div> 1091 </a> 1092 </li> 1093 <li class="text-[0.81rem]"> 1094 <a href="#" target="_blank" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1095 <div class="mb-1"><img class="w-20" src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/da38960dc377db43ceb214c946ece3cd.png " alt=""></div> 1096 </a> 1097 </li> 1098 <li class="text-[0.81rem]"> 1099 <a href="#" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1100 <div class="mb-3">DINHEIRO</div> 1101 </a> 1102 </li> 1103 </ul> 1104 </div> 1105 <div class="text-neutral-800 float-left text-sm pr-3 pt-10"> 1106 <ul> 1107 <li class="text-[0.70rem] mb-3"> 1108 <div class="text-gray-800 dark:text-zinc-400 mb-4 opacity-50" style="color:#ffffff"> Links Ãteis </div> 1109 </li> 1110 <li class="text-[0.81rem]"> 1111 <a href="/about" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1112 <div class="mb-3">Sobre nós</div> 1113 </a> 1114 </li> 1115 <li class="text-[0.81rem]"> 1116 <a href="/career" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1117 <div class="mb-3">Carreira</div> 1118 </a> 1119 </li> 1120 <li class="text-[0.81rem]"> 1121 <a href="/blog" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1122 <div class="mb-3">Nosso Blog</div> 1123 </a> 1124 </li> 1125 </ul> 1126 </div> 1127 <div class="text-neutral-800 float-left text-sm pr-3 pt-10"> 1128 <ul> 1129 <li class="text-[0.70rem] mb-3"> 1130 <div class="text-gray-800 dark:text-zinc-400 mb-4 opacity-50" style="color:#ffffff"> Legal </div> 1131 </li> 1132 <li class="text-[0.81rem]"> 1133 <a href="/terms-and-conditions" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1134 <div class="mb-3">Termos & Condições</div> 1135 </a> 1136 </li> 1137 <li class="text-[0.81rem]"> 1138 <a href="/privacy" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1139 <div class="mb-3">PolÃtica de Privacidade</div> 1140 </a> 1141 </li> 1142 <li class="text-[0.81rem]"> 1143 <a href="/refund" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1144 <div class="mb-3">Reembolso</div> 1145 </a> 1146 </li> 1147 <li class="text-[0.81rem]"> 1148 <a href="https://www.livroreclamacoes.pt/Inicio/" target="_blank" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1149 <div class="mb-1"><img class="w-full" src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/cbd69b35c7b8b52c460f7cc395633efa.png " alt=""></div> 1150 </a> 1151 </li> 1152 </ul> 1153 </div> 1154 <div class="text-neutral-800 float-left text-sm pr-3 pt-10"> 1155 <ul> 1156 <li class="text-[0.70rem] mb-3"> 1157 <div class="text-gray-800 dark:text-zinc-400 mb-4 opacity-50" style="color:#ffffff"> Baixe a App </div> 1158 </li> 1159 <li class="text-[0.81rem]"> 1160 <a href="https://play.google.com/store/apps/details?id=com.lojadodia.amapizza" target="_blank" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1161 <div class="mb-1"><img class="w-32" src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/be6a49f35087d2fc9209460e29710c9e.png " alt=""></div> 1162 </a> 1163 </li> 1164 <li class="text-[0.81rem]"> 1165 <a href="https://apps.apple.com/pt/app/amapizza/id1670447588" target="_blank" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1166 <div class="mb-1"><img class="w-32" src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/ef10e10ae72729d7c35e01faded7f752.png " alt=""></div> 1167 </a> 1168 </li> 1169 </ul> 1170 </div> 1171 <div class="text-neutral-800 float-left text-sm pr-3 pt-10"> 1172 <ul> 1173 <li class="text-[0.70rem] mb-3"> 1174 <div class="text-gray-800 dark:text-zinc-400 mb-4 opacity-50" style="color:#ffffff"> Contactos </div> 1175 </li> 1176 <li class="text-[0.81rem]"> 1177 <a href="#" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1178 <div class="mb-3">[email protected]</div> 1179 </a> 1180 </li> 1181 <li class="text-[0.81rem]"> 1182 <a href="#" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1183 <div class="mb-3">+351 913 020 444 (rede móvel)</div> 1184 </a> 1185 </li> 1186 <li class="text-[0.81rem]"> 1187 <a href="https://www.instagram.com/amapizza.pt/" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1188 <div class="mb-3"><i class="bi bi-instagram"></i> Instagram</div> 1189 </a> 1190 </li> 1191 <li class="text-[0.81rem]"> 1192 <a href="https://www.facebook.com/amapizza.pt" target="_self" class="external text-gray-800 dark:text-gray-300 cursor-pointer" style="color:#ffffff"> 1193 <div class="mb-3"><i class="bi bi-facebook"></i> Facebook</div> 1194 </a> 1195 </li> 1196 </ul> 1197 </div> 1198 </div> 1199 </div> 1200 <div class="lg:pt-5 lg:pb-0 pt-5 hidden-app pb-10 mb-8 lg:mb-0 text-center"> 1201 <div class="text-gray-800 dark:text-gray-400 text-xs py-3" style="color:#ffffff; margin-bottom:25px">Amapizza 2026 © Todos os direitos reservados, ESCOLHA ESSÃNCIA, LDA, com sede Avenida de Ceuta 31, Amadora, Contribuinte nº 518530787 </div> 1202 </div> 1203 1204 <div class="lg:pt-2 lg:pb-8 pt-2 hidden-app pb-10 mb-12 lg:mb-0 text-center"> 1205 <a href="https://sistemaquevende.pt/" class="external" target="_blank"> 1206 <div class="text-gray-800 text-center mb-14 dark:text-gray-400 text-xs py-3" style="color:#ffffff">Powered by <img class="w-36 mx-auto" src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/sqv/sqv_logo.png" alt=""></div> 1207 </a> 1208 </div> 1209 1210 1211 1212</footer> 1213 1214 1215 1216 1217 1218 </div> 1219 </div> 1220 <div class="lg:hidden block toolbar tabbar-icons toolbar-bottom bottom-0 fixed left-0 w-full"> 1221 <div class="toolbar-inner text-2xl"> 1222 <div class="relative"> 1223 <a href="#" class="main-link" onclick="navigateAndActivate('/', 'bi-house-fill')"> 1224 <div class="py-4 px-5 text-center hover:bg-gray-100 dark:hover:bg-zinc-800 relative"> 1225 <i id="bi-house-fill" class="bi bi-house-fill dark:text-zinc-100"></i> 1226 </div> 1227 </a> 1228 </div> 1229 1230 <div class="relative"> 1231 <a class="cursor-pointer cart-navbar py-4 px-5 text-center hover:bg-gray-100 dark:hover:bg-zinc-800 relative popover-open" data-popover=".popover-cart"> 1232 <i class="cart-icon bi bi-cart pt-2"></i> 1233 <sup class="lg:-ml-2 -ml-4 lg:mt-3 -mt-2">
1234 <small class="badge bg-black text-xs cart-badge">0</small> 1235 </sup> 1236 </a> 1237 </div> 1238 1239 <div class="relative"> 1240 <!-- Forcing Login to Access --> 1241 <div data-modal-target="auth" onclick='saveData("nextUrl","/myorders")' class="cursor-pointer z-30 absolute w-full h-full top-0 left-0"></div> <a href="#" onclick="navigateAndActivate('myorders', 'bi-receipt')"> 1242 <div class="py-4 px-5 text-center hover:bg-gray-100 dark:hover:bg-zinc-800 relative"> 1243 <i id="bi-calendar2-range" class="bi bi-receipt dark:text-zinc-400"></i> 1244 </div> 1245 </a> 1246 </div> 1247 1248 1249 1250 <div class="relative"> 1251 <a class="panel-open" data-panel=".panel-more"> 1252 <div class="py-4 px-5 text-center hover:bg-gray-100 dark:hover:bg-zinc-800 relative"> 1253 <i id="bi-person" class="bi bi-person dark:text-zinc-400"></i> 1254 </div> 1255 </a> 1256 </div> 1257 </div> 1258 </div> 1259 1260 <div class="lg:hidden block mt-24"></div> 1261 <div class="popup modal-address"> 1262 <div class="page"> 1263 <div class="navbar"> 1264 <div class="navbar-bg"></div> 1265 <div class="navbar-inner"> 1266 <div class="title">Detalhes do Endereço</div> 1267 <div class="right"> 1268 <a class="link popup-close cursor-pointer px-4 pt-1"> 1269 <i class="bi bi-x-lg"></i> 1270 </a> 1271 </div> 1272 </div> 1273 </div> 1274 <div class="page-content pt-14"> 1275 <div class=" px-4 grid grid-cols-10 gap-2"> 1276 <!-- Address Input --> 1277 <div class="col-span-7"> 1278 <div class="label-space"> 1279 <label for="address-street" class="text-sm text-gray-700 dark:text-zinc-300"> 1280 Rua 1281 </label> 1282 </div> 1283 <input id="address-street" data-field="Rua" type="text" placeholder=" Rua" readonly 1284 class="dark:bg-zinc-900 bg-gray-50 mt-1 w-full py-2 block w-full border-zinc-600 border rounded dark:text-white border-gray-400 rounded-md shadow-sm px-3 input-with-value" /> 1285 </div> 1286 <div class="col-span-3"> 1287 <div class="label-space"> 1288 <label for="address-street" class="text-sm text-gray-700 dark:text-zinc-300"> 1289 Número da Rua 1290 </label> 1291 </div> 1292 <input id="address-street-number" data-field="Número da Rua" type="text" placeholder="Número da Rua" 1293 class="dark:bg-zinc-900 mt-1 py-2 block w-full border-zinc-600 border rounded dark:text-white border-gray-400 rounded-md shadow-sm px-3 input-with-value" 1294 required /> 1295 </div> 1296 <div class="col-span-10"> 1297 <div class="label-space"> 1298 <label for="address-street" class="text-sm text-gray-700 dark:text-zinc-300"> 1299 Detalhes do Endereço 1300 </label> 1301 </div> 1302 <input id="address-details" data-field="Detalhes do Endereço" type="text" placeholder="Apto/SuÃte" 1303 class="dark:bg-zinc-900 mt-1 py-2 block w-full border-zinc-600 border rounded dark:text-white border-gray-400 rounded-md shadow-sm px-3 input-with-value" 1304 required /> 1305 </div> 1306 <div class="col-span-5"> 1307 <div class="label-space"> 1308 <label for="address-street" class="text-sm text-gray-700 dark:text-zinc-300"> 1309 Cidade 1310 </label> 1311 </div> 1312 <input id="address-city" type="text" placeholder="Cidade" 1313 class="dark:bg-zinc-900 mt-1 py-2 block w-full border-zinc-600 border rounded dark:text-white border-gray-400 rounded-md shadow-sm px-3 input-with-value" 1314 required /> 1315 </div> 1316 <div class="col-span-5 hidden"> 1317 <div class="label-space"> 1318 <label for="address-street" class="text-sm text-gray-700 dark:text-zinc-300"> 1319 State 1320 </label> 1321 </div>
1322 <input id="address-state" type="text" placeholder="State" 1323 class="dark:bg-zinc-900 mt-1 py-2 block w-full border-zinc-600 border rounded dark:text-white border-gray-400 rounded-md shadow-sm px-3 input-with-value" 1324 required /> 1325 </div> 1326 <div class="col-span-5 hidden"> 1327 <div class="label-space"> 1328 <label for="address-street" class="text-sm text-gray-700 dark:text-zinc-300"> 1329 Lat 1330 </label> 1331 </div> 1332 <input id="address-lat" type="text" placeholder="Lat" 1333 class="dark:bg-zinc-900 mt-1 py-2 block w-full border-zinc-600 border rounded dark:text-white border-gray-400 rounded-md shadow-sm px-3 input-with-value" 1334 required /> 1335 </div> 1336 <div class="col-span-5 hidden"> 1337 <div class="label-space"> 1338 <label for="address-street" class="text-sm text-gray-700 dark:text-zinc-300"> 1339 Lng 1340 </label> 1341 </div> 1342 <input id="address-lng" type="text" placeholder="Lng" 1343 class="dark:bg-zinc-900 mt-1 py-2 block w-full border-zinc-600 border rounded dark:text-white border-gray-400 rounded-md shadow-sm px-3 input-with-value" 1344 required /> 1345 </div> 1346 <div class="col-span-5 "> 1347 <div class="label-space"> 1348 <label for="address-zip" class="text-sm text-gray-700 dark:text-zinc-300"> 1349 Código Postal 1350 </label> 1351 </div> 1352 <input id="address-zip" data-field="Código Postal" type="text" placeholder="Código Postal" 1353 class="dark:bg-zinc-900 mt-1 py-2 block w-full border-zinc-600 border rounded dark:text-white border-gray-400 rounded-md shadow-sm px-3 input-with-value" 1354 required /> 1355 </div> 1356 <div class="col-span-5 "> 1357 <div class="label-space"> 1358 <label for="address-street" class="text-sm text-gray-700 dark:text-zinc-300"> 1359 PaÃs 1360 </label> 1361 </div> 1362 <input id="address-country" type="text" placeholder="PaÃs" 1363 class="dark:bg-zinc-900 mt-1 py-2 block w-full border-zinc-600 border rounded dark:text-white border-gray-400 rounded-md shadow-sm px-3 input-with-value" 1364 required /> 1365 </div> 1366 <!-- Instructions Textarea --> 1367 <div class="col-span-10 mb-14"> 1368 <div class="label-space"> 1369 <label for="address-street" class="text-sm text-gray-700 dark:text-zinc-300"> 1370 Notas do Endereço 1371 </label> 1372 </div> 1373 <textarea id="address-note" placeholder="Instruções para Entrega" 1374 class="dark:bg-zinc-900 mt-1 py-2 block w-full border-zinc-600 border rounded dark:text-white border-gray-400 rounded-md shadow-sm px-3 input-with-value"></textarea> 1375 </div> 1376 </div> 1377 <div 1378 class="space-y-2 z-30 fixed bg-white dark:bg-zinc-900 bottom-0 w-full border-t border-gray-300 dark:border-zinc-600 lg:py-2 py-2 px-5"> 1379 <button id="save-address" 1380 class="button-primary cursor-pointer inline-block w-full text-lg lg:py-2 py-2 px-8 relative text-center"> 1381 Salvar 1382 </button> 1383 </div> 1384 </div> 1385 </div> 1386</div> <div class="popup modal-schedule"> 1387 <div class="page"> 1388 <div class="navbar"> 1389 <div class="navbar-bg"></div> 1390 <div class="navbar-inner"> 1391 <div class="title capitalize"> 1392 <!-- Agendar 1393 Takeaway --> 1394 Agende e aproveite!
1395 <span class="block text-xs font-normal normal-case text-gray-500"> 1396 Horários de Entrega e Levantamento 1397 </span> 1398 </div> 1399 <div class="right"> 1400 <a class="link popup-close cursor-pointer px-4 pt-1"> 1401 <i class="bi bi-x-lg"></i> 1402 </a> 1403 </div> 1404 </div> 1405 </div> 1406 <div class="page-content"> 1407 <div class="text-sm isolate"> 1408 <div class="pt-14"> 1409 <div class="sticky top-10 bg-white"> 1410 <div class="flex relative py-4"> 1411 <div class="overflow-x-scroll overflow-y-auto scroll-smooth"> 1412 <div class="flex"> 1413 <div> 1414 <button data-day="Today" data-date="2026-10-02" class="day-selector w-32 first-day lg:ml-6 ml-3 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1415 <span class="font-medium">Hoje</span> 1416 <span>02/10</span> 1417 </button> 1418 </div> 1419 <div> 1420 <button data-day="Tomorrow" data-date="2026-10-03" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1421 <span class="font-medium">Amanhã</span> 1422 <span>03/10</span> 1423 </button> 1424 </div> 1425 <div> 1426 <button data-day="Sunday" data-date="2026-10-04" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1427 <span class="font-medium">Domingo</span> 1428 <span>04/10</span> 1429 </button> 1430 </div> 1431 <div> 1432 <button data-day="Monday" data-date="2026-10-05" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1433 <span class="font-medium">Segunda</span> 1434 <span>05/10</span> 1435 </button> 1436 </div> 1437 <div> 1438 <button data-day="Tuesday" data-date="2026-10-06" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1439 <span class="font-medium">Terça</span> 1440 <span>06/10</span> 1441 </button> 1442 </div> 1443 <div> 1444 <button data-day="Wednesday" data-date="2026-10-07" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4">
1445 <span class="font-medium">Quarta</span> 1446 <span>07/10</span> 1447 </button> 1448 </div> 1449 <div> 1450 <button data-day="Thursday" data-date="2026-10-08" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1451 <span class="font-medium">Quinta</span> 1452 <span>08/10</span> 1453 </button> 1454 </div> 1455 <div> 1456 <button data-day="Friday" data-date="2026-10-09" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1457 <span class="font-medium">Sexta</span> 1458 <span>09/10</span> 1459 </button> 1460 </div> 1461 <div> 1462 <button data-day="Saturday" data-date="2026-10-10" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1463 <span class="font-medium">Sábado</span> 1464 <span>10/10</span> 1465 </button> 1466 </div> 1467 <div> 1468 <button data-day="Sunday" data-date="2026-10-11" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1469 <span class="font-medium">Domingo</span> 1470 <span>11/10</span> 1471 </button> 1472 </div> 1473 <div> 1474 <button data-day="Monday" data-date="2026-10-12" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1475 <span class="font-medium">Segunda</span> 1476 <span>12/10</span> 1477 </button> 1478 </div> 1479 <div> 1480 <button data-day="Tuesday" data-date="2026-10-13" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1481 <span class="font-medium">Terça</span> 1482 <span>13/10</span> 1483 </button> 1484 </div> 1485 <div> 1486 <button data-day="Wednesday" data-date="2026-10-14" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4">
1487 <span class="font-medium">Quarta</span> 1488 <span>14/10</span> 1489 </button> 1490 </div> 1491 <div> 1492 <button data-day="Thursday" data-date="2026-10-15" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1493 <span class="font-medium">Quinta</span> 1494 <span>15/10</span> 1495 </button> 1496 </div> 1497 <div> 1498 <button data-day="Friday" data-date="2026-10-16" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1499 <span class="font-medium">Sexta</span> 1500 <span>16/10</span> 1501 </button> 1502 </div> 1503 <div> 1504 <button data-day="Saturday" data-date="2026-10-17" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1505 <span class="font-medium">Sábado</span> 1506 <span>17/10</span> 1507 </button> 1508 </div> 1509 <div> 1510 <button data-day="Sunday" data-date="2026-10-18" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1511 <span class="font-medium">Domingo</span> 1512 <span>18/10</span> 1513 </button> 1514 </div> 1515 <div> 1516 <button data-day="Monday" data-date="2026-10-19" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1517 <span class="font-medium">Segunda</span> 1518 <span>19/10</span> 1519 </button> 1520 </div> 1521 <div> 1522 <button data-day="Tuesday" data-date="2026-10-20" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1523 <span class="font-medium">Terça</span> 1524 <span>20/10</span> 1525 </button> 1526 </div> 1527 <div> 1528 <button data-day="Wednesday" data-date="2026-10-21" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4">
1529 <span class="font-medium">Quarta</span> 1530 <span>21/10</span> 1531 </button> 1532 </div> 1533 <div> 1534 <button data-day="Thursday" data-date="2026-10-22" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1535 <span class="font-medium">Quinta</span> 1536 <span>22/10</span> 1537 </button> 1538 </div> 1539 <div> 1540 <button data-day="Friday" data-date="2026-10-23" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1541 <span class="font-medium">Sexta</span> 1542 <span>23/10</span> 1543 </button> 1544 </div> 1545 <div> 1546 <button data-day="Saturday" data-date="2026-10-24" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1547 <span class="font-medium">Sábado</span> 1548 <span>24/10</span> 1549 </button> 1550 </div> 1551 <div> 1552 <button data-day="Sunday" data-date="2026-10-25" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1553 <span class="font-medium">Domingo</span> 1554 <span>25/10</span> 1555 </button> 1556 </div> 1557 <div> 1558 <button data-day="Monday" data-date="2026-10-26" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1559 <span class="font-medium">Segunda</span> 1560 <span>26/10</span> 1561 </button> 1562 </div> 1563 <div> 1564 <button data-day="Tuesday" data-date="2026-10-27" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1565 <span class="font-medium">Terça</span> 1566 <span>27/10</span> 1567 </button> 1568 </div> 1569 <div> 1570 <button data-day="Wednesday" data-date="2026-10-28" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4">
1571 <span class="font-medium">Quarta</span> 1572 <span>28/10</span> 1573 </button> 1574 </div> 1575 <div> 1576 <button data-day="Thursday" data-date="2026-10-29" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1577 <span class="font-medium">Quinta</span> 1578 <span>29/10</span> 1579 </button> 1580 </div> 1581 <div> 1582 <button data-day="Friday" data-date="2026-10-30" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1583 <span class="font-medium">Sexta</span> 1584 <span>30/10</span> 1585 </button> 1586 </div> 1587 <div> 1588 <button data-day="Saturday" data-date="2026-10-31" class="day-selector w-32 mr-2 items-start cursor-pointer flex flex-col text-center border-2 border-neutral-200 border-solid rounded-xl p-4"> 1589 <span class="font-medium">Sábado</span> 1590 <span>31/10</span> 1591 </button> 1592 </div> 1593 </div> 1594 </div> 1595 </div> 1596 </div> 1597 1598 <div class="lg:px-6"> 1599 <div class="p-4 text-red-600 font-semibold">Loja não encontrada ou inativa.</div> 1600 1601 </div> 1602 1603 </div> 1604 </div> 1605 1606 <div class="space-y-2 z-30 fixed bg-white dark:bg-zinc-900 bottom-0 w-full border-t border-gray-300 dark:border-zinc-600 lg:py-2 py-2 px-5"> 1607 <div class="hidden"> 1608 <input type="text" id="date-time" readonly value="02/10"> 1609 <input type="text" id="hour-time" readonly> 1610 <input type="text" id="field-time" readonly> 1611 </div> 1612 <input id="filter-time" value="Agora" readonly class="px-2 bg-transparent cursor-pointer hidden" type="text" /> 1613 <input type="hidden" id="start_date" name="start_date" value=""> 1614 <input type="hidden" id="end_date" name="end_date" value=""> 1615 1616 <button disabled id="schedule-time" class="button-primary relative cursor-pointer inline-block popup-close w-full text-lg lg:py-2 py-2 px-8 relative text-center"> 1617 <div class="schedule-time-block disabled-toast absolute w-full h-full top-0 left-0" style="z-index: 6000000"></div> 1618 Agendar 1619 </button> 1620 <button id="order-now" class="button-secondary capitalize cursor-pointer inline-block popup-close w-full text-lg lg:py-2 py-2 px-8 relative text-center"> 1621 <!-- Takeaway Agora --> 1622 Pedir Agora 1623 </button> 1624 </div> 1625 </div> 1626 </div> 1627</div> 1628
1629<script> 1630 1631$(document).ready(function() { 1632 $('.day-selector').click(function () { 1633 $('.day-selector').removeClass('border-black').addClass('border-neutral-200'); 1634 $(this).addClass('border-black'); 1635 1636 let selectedDay = $(this).data('day').toLowerCase(); 1637 const selectedDateIso = $(this).data('date'); 1638 if (selectedDay === 'today') selectedDay = moment().format('dddd').toLowerCase(); 1639 if (selectedDay === 'tomorrow') selectedDay = moment().add(1, 'day').format('dddd').toLowerCase(); 1640 1641 $('.day-slots').hide(); 1642 $('#slots-' + selectedDateIso).show(); 1643 1644 // Filtro para hoje real - excluir horários dentro dos próximos 25 minutos 1645 if (selectedDateIso === moment().format('YYYY-MM-DD')) { 1646 let now = moment(); 1647 let cutoff = now.clone().add({ minutes: 25 }); 1648 1649 $('#slots-' + selectedDateIso + ' .time-slot').each(function () { 1650 let time = $(this).data('start-time'); 1651 let slotMoment = moment(time, 'HH:mm'); 1652 slotMoment.set({ 1653 year: now.year(), 1654 month: now.month(), 1655 date: now.date() 1656 }); 1657 1658 if (slotMoment.isBefore(cutoff)) { 1659 $(this).hide(); 1660 } else { 1661 $(this).show(); 1662 } 1663 }); 1664 } 1665 1666 let formattedDate = $(this).find('span:nth-child(2)').text(); 1667 let parts = formattedDate.split('/'); 1668 let reorderedDate = parts[1] + '-' + parts[0]; 1669 $('#date-time').val(reorderedDate); 1670 completeTime(); 1671 }); 1672 1673 $('.time-slot input[type=radio]').change(function() { 1674 let selectedTime = $(this).val(); 1675 $('#hour-time').val(selectedTime); 1676 completeTime(); 1677 }); 1678 1679 $(".disabled-toast").on("click", function(){ 1680 toast("error", 'Campos obrigatórios', 3000); 1681 }); 1682 1683 $("#schedule-time").on("click", async function(){ 1684 let selectedDate = $('#field-time').val(); 1685 localStorage.setItem('sqv_just_scheduled', '1'); 1686 1687 // Captura a modal pendente ANTES de qualquer operação async 1688 const toReopen = (typeof pendingProductModal !== 'undefined' && pendingProductModal) 1689 ? pendingProductModal 1690 : localStorage.getItem('reabrir_modal_produto'); 1691 if (toReopen) localStorage.setItem('reabrir_modal_produto', toReopen); 1692 1693 // Fecha a modal de agendamento 1694 if (typeof app !== 'undefined') app.popup.close('.modal-schedule'); 1695 1696 const storeId = window.sqvStoreId ?? null; 1697 if (storeId && typeof sqvFetchStoreState === 'function') { 1698 await sqvFetchStoreState({ store_id: storeId, order_time: selectedDate }); 1699 } else { 1700 await saveData('order_time', selectedDate); 1701 let formattedDate = moment(selectedDate, 'YYYY-MM-DD HH:mm:ss').format('DD/MM HH:mm'); 1702 $(".filter-time").val(formattedDate); 1703 $(".data-order-time").text(formattedDate); 1704 } 1705 1706 // O utilizador agendou â loja está acessÃvel para esse horário 1707 window.sqvStoreIsOpen = true; 1708 document.querySelectorAll('.sqv-product-open-section').forEach(function(el) { el.classList.remove('hidden'); }); 1709 document.querySelectorAll('.sqv-product-closed-section').forEach(function(el) { el.classList.add('hidden'); }); 1710 1711 // Reabre a modal do produto sempre que havia uma pendente 1712 if (toReopen && typeof app !== 'undefined') { 1713 setTimeout(() => { 1714 app.popup.open(toReopen); 1715 localStorage.removeItem('reabrir_modal_produto'); 1716 }, 500); 1717 } 1718 }); 1719 1720 $("#order-now").on("click", async function(){ 1721 // Fecha a modal de agendamento 1722 if (typeof app !== 'undefined') app.popup.close('.modal-schedule'); 1723 1724 // Marca como fechado imediatamente â evita race condition se o utilizador 1725 // clicar num produto antes de a resposta da API chegar 1726 window.sqvStoreIsOpen = false; 1727 document.querySelectorAll('.sqv-product-open-section').forEach(function(el) { el.classList.add('hidden'); }); 1728 document.querySelectorAll('.sqv-product-closed-section').forEach(function(el) { el.classList.remove('hidden'); }); 1729 localStorage.removeItem('reabrir_modal_produto'); 1730 1731 const storeId = window.sqvStoreId ?? null; 1732 if (storeId && typeof sqvFetchStoreState === 'function') { 1733 const data = await sqvFetchStoreState({ store_id: storeId, order_time: 'now' }); 1734 if (data && data.isOpen) { 1735 // Loja aberta agora â corrige o estado e pode reabrir modal de produto 1736 window.sqvStoreIsOpen = true; 1737 document.querySelectorAll('.sqv-product-open-section').forEach(function(el) { el.classList.remove('hidden'); }); 1738 document.querySelectorAll('.sqv-product-closed-section').forEach(function(el) { el.classList.add('hidden'); }); 1739 const toReopen = (typeof pendingProductModal !== 'undefined' && pendingProductModal) 1740 ? pendingProductModal 1741 : localStorage.getItem('reabrir_modal_produto'); 1742 if (toReopen && typeof app !== 'undefined') { 1743 setTimeout(() => { 1744 app.popup.open(toReopen); 1745 localStorage.removeItem('reabrir_modal_produto'); 1746 }, 350); 1747 } 1748 } 1749 } else { 1750 await saveData('order_time', 'now'); 1751 $(".filter-time").val("Agora"); 1752 $(".data-order-time").text("Agora"); 1753 } 1754 }); 1755}); 1756 1757function completeTime() { 1758 var selectedDate = $('#date-time').val(); 1759 var selectedTime = $('#hour-time').val(); 1760 if (selectedDate && selectedTime) { 1761 var time = "2026-" + selectedDate + ' ' + selectedTime + ':00'; 1762 $('#field-time').val(time); 1763 $(".schedule-time-block").hide(); 1764 $("#schedule-time").attr("disabled", false); 1765 } 1766} 1767 1768 1769 1770 1771</script>
1771 1772 </div> 1773 </div> 1774
1774<script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.2.1/js.cookie.min.js"></script>
1774 1775<div id="cookie-banner" class="fixed lg:bottom-0 bottom-9 left-0 right-0 text-white flex justify-center items-center space-x-4 hidden" style="z-index: 50000000000000 !important"> 1776 <div class="max-w-6xl mx-auto relative"> 1777 <div class="lg:w-2/3 pb-2"> 1778 <div class="items-center justify-between bg-black bg-opacity-80 backdrop-filter backdrop-blur-lg dark:bg-black dark:bg-opacity-60 dark:backdrop-filter dark:backdrop-blur-xl text-white border border-gray-800 shadow-sm p-5 lg:rounded-lg"> 1779 <div class="flex"> 1780 <div class="pr-3"> 1781 <img class="w-10" src="https://i.pinimg.com/originals/dc/c8/1a/dcc81ae124a78573b1c8bae1586d4efe.png" alt=""> 1782 </div> 1783 <p class="w-full text-sm">Utilizamos cookies próprios e de terceiros em nossos sites para melhorar sua experiência, analisar nosso tráfego e para fins de segurança e marketing. Selecione "Eu aceito" para permitir seu uso. Leia nosso<a href="/privacy" class="text-yellow-500 cursor-pointer font-medium"> PolÃtica de Cookies</a>.</p> 1784 </div> 1785 <div class="items-center mt-0 text-right"> 1786 1787 <a onclick="rejectCookies()" class="bg-black bg-opacity-20 text-secondary cursor-pointer text-sm font-medium ml-2 py-2 px-5 text-center rounded-full"><i class="bi bi-x-lg"></i> Rejeitar Todos</a> 1788 <button onclick="acceptCookies()" class="items-start bg-primary-light text-white cursor-pointer text-sm font-medium ml-2 py-2 px-5 text-center rounded-full">Eu aceito</button> 1789 </div> 1790 </div> 1791 </div> 1792 </div> 1793</div> 1794<!-- Cookie Management --> 1795<div id="cookie-consent-modal" class="z-50 fixed inset-0 bg-black bg-opacity-50 backdrop-filter backdrop-blur-lg flex items-center hidden"> 1796 <div class="bg-white rounded-lg p-6 max-w-2xl mx-auto "> 1797 <div class="flex"> 1798 <a href="/" class="flex items-center mx-auto pt-5 pb-5"> 1799 <img src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/0842a48e5579c23f2afc8df9d81b2ce2.png" class="logo-dark lg:h-12 h-10 lg:mr-3 mx-auto mt-4 lg:mt-0" alt="Amapizza" /> 1800 1801 1802<img style="display: none" class="logo-light" src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/6706ef288778c744cbd16350c9c2d6e0.png" /> </a> 1803 </div> 1804 <div class="h-1/2 overflow-x-scroll pt-5 pb-5 border border-gray-200 bg-gray-50 rounded px-5"> 1805 <div class="text-gray-500 font-light"> 1806 <div> 1807 <p class="text-gray-900 text-2xl font-bold mb-4">Configurações de Cookies</p> 1808 <p class="mb-2">To use these Services, we need your consent. By clicking âAccept allâ, you declare your consent to the use of all Services. You can also declare your consent by clicking individually on the sliders for each cookie category and save.</p> 1809 <a href="#" class="items-center text-primary cursor-pointer inline-flex text-sm font-medium"> 1810 Leia Mais 1811 <svg fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-1"> 1812 <path fill-rule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd" fill="currentColor"></path> 1813 </svg> 1814 </a> 1815 </div> 1816 <div class="border-t mt-4 pt-4 border-gray-200 border-solid"> 1817 <div class="items-start flex"> 1818 <div> 1819 <div class="flex"> 1820 <p class="w-full text-gray-900 text-lg font-semibold mb-2">Essential Cookies</p> 1821 <div class="toggle-content mt-2"> 1822 <label class="cursor-pointer switch relative inline-block w-10 h-5 rounded-full"> 1823 <input type="checkbox" checked class="checkbox opacity-0 w-full h-full left-0 top-0 cursor-pointer absolute" />
1824 <span class="slider block bg-gray-500 rounded-full transition-colors ease-in-out duration-200 w-full h-full absolute "></span> 1825 <span class="dot absolute w-4 h-4 bg-white rounded-full shadow transform transition-transform ease-in-out duration-200 left-0.5 top-0.5"></span> 1826 </label> 1827 </div> 1828 </div> 1829 <p class="mb-2">To use these Services, we need your consent. By clicking âAccept allâ, you declare your consent to the use of all Services. You can also declare your consent by clicking individually on the sliders for each cookie category and save.</p> 1830 <a data-expand="essencial-cookies" class="cursor-pointer items-center text-primary cursor-pointer inline-flex text-sm font-medium"> 1831 Ver Cookies 1832 <svg fill="currentColor" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 ml-1"> 1833 <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" fill="currentColor"></path> 1834 </svg> 1835 </a> 1836 </div> 1837 </div> 1838 <div id="essencial-cookies" class="hidden bg-gray-100 mt-4 rounded-lg overflow-auto"> 1839 <table class="border-collapse table text-sm"> 1840 <thead class="text-gray-700 table-header-group text-xs uppercase align-middle"> 1841 <tr class="table-row"> 1842 <th class="table-cell font-bold py-3 px-6">Name</th> 1843 <th class="table-cell font-bold py-3 px-6">Provider</th> 1844 <th class="table-cell font-bold py-3 px-6">Expiration</th> 1845 <th class="table-cell font-bold py-3 px-6">Purpose</th> 1846 </tr> 1847 </thead> 1848 <tbody class="table-row-group align-middle"> 1849 <tr class="table-row"> 1850 <th class="table-cell py-4 px-6">_cfduid</th> 1851 <td class="table-cell py-4 px-6">CloudFlare Inc</td> 1852 <td class="table-cell py-4 px-6">1 Year</td> 1853 <td class="table-cell py-4 px-6">Static file delivery</td> 1854 </tr> 1855 <tr class="table-row"> 1856 <th class="table-cell py-4 px-6">_cfruid</th> 1857 <td class="table-cell py-4 px-6">Hubspot Inc</td> 1858 <td class="table-cell py-4 px-6">Session</td> 1859 <td class="table-cell py-4 px-6">Web page delivery</td> 1860 </tr> 1861 <tr class="table-row"> 1862 <th class="table-cell py-4 px-6">_lidc</th> 1863 <td class="table-cell py-4 px-6">Linkedin</td> 1864 <td class="table-cell py-4 px-6">1 Day</td> 1865 <td class="table-cell py-4 px-6">Marketing tracking</td> 1866 </tr> 1867 </tbody> 1868 </table> 1869 </div> 1870 </div> 1871 1872 </div> 1873 </div> 1874 <div class="items-center flex justify-between mt-5"> 1875 <div class="items-center flex"> 1876 <button class="items-start text-gray-500 cursor-pointer text-sm font-medium py-3 px-5 text-center border border-gray-200 border-solid rounded-full">PolÃtica de Privacidade</button> 1877 </div> 1878 <div class="items-center text-gray-500 flex text-sm"> 1879 <button class="items-start bg-red-500 text-white cursor-pointer font-medium mr-2 py-3 px-5 text-center rounded-full" onclick="rejectCookies()">Rejeitar Todos</button> 1880 <button class="items-start bg-primary text-white cursor-pointer font-medium py-3 px-5 text-center rounded-full" onclick="acceptCookies()">Aceitar</button> 1881 </div> 1882 </div> 1883 </div> 1884</div> <!-- Loader --> 1885 <div id="page-loader" class="fixed z-20 hidden" style="z-index: 60000 !important" aria-labelledby="modal-title" role="dialog" aria-modal="true"> 1886 <div class="modal-backdrop fixed opacity-100 inset-0 backdrop-filter backdrop-blur-md bg-black bg-opacity-60 transition-opacity ease-out duration-300"></div> 1887 <div class="fixed inset-0 z-30 overflow-y-auto"> 1888 <div class="text-white min-h-full items-center justify-center text-center "> 1889 <div class="modal-content flex items-center opacity-100 relative transform h-screen transition-all "> 1890 <div class="mx-auto"> 1891 <h1 class="text-4xl w-full mb-5"> 1892 <!-- <div class="w-16 h-16 relative mx-auto">
1893 <svg class="animate-spin h-full w-full block" viewBox="0 0 24 24"> 1894 <circle class="opacity-10 bg-primary" cx="12" cy="12" r="11" stroke="currentColor" stroke-width="1.8" fill="transparent"></circle> 1895 <circle class="opacity-100 absolute" cx="12" cy="12" r="11" stroke="white" stroke-width="1.8" stroke-dasharray="10 52" stroke-linecap="round" fill="transparent"></circle> 1896 </svg> 1897</div> --> 1898 1899<!-- <div class="w-16 h-16 relative mx-auto"> 1900 <img src="/assets/img/gif/basket.gif" alt="Loading..." class="w-full h-full object-contain" /> 1901</div> --> 1902 1903<div class=" relative mx-auto" style="width: 120px; height: 120px;"> 1904 <img src="/assets/img/gif/basket.gif" alt="Loading..." class="w-full h-full object-contain" /> 1905</div> 1906 </h1> 1907 <h1 class="text-xl font-light mb-5 text-gray-200">Por favor, aguarde...</h1> 1908 </div> 1909 </div> 1910 </div> 1911 </div> 1912</div> 1913 <div id="auth" class="relative z-20 hidden " style="z-index: 6000000 !important" aria-labelledby="modal-title" role="dialog" aria-modal="true"> 1914 <div class="modal-backdrop fixed opacity-0 inset-0 backdrop-filter backdrop-blur-md bg-black bg-opacity-75 transition-opacity ease-out duration-300"></div> 1915 <div class="fixed inset-0 z-30 overflow-y-auto"> 1916 <div class="flex min-h-full items-center justify-center lg:p-4 text-center sm:items-center sm:p-0"> 1917 <div class="modal-content opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95 relative transform overflow-hidden lg:h-auto h-screen lg:rounded-lg bg-white dark:bg-zinc-950 lg:border border-primary dark:border-zinc-600 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg"> 1918 <div class="bg-white dark:bg-zinc-950 px-8 pb-8 pt-8 relative"> 1919 <a class="close-auth cursor-pointer px-7 py-5 absolute right-0 top-0 hover:bg-gray-100 dark:hover:bg-zinc-950" data-modal-close="auth"> 1920 <i class="bi bi-x-lg text-2xl dark:text-white"></i> 1921 </a> 1922 <div class="flex"> 1923 <div class=" mx-auto"> 1924 <a href="/" class="flex items-center mx-auto pt-5 pb-5"> 1925 <img src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/0842a48e5579c23f2afc8df9d81b2ce2.png" class="logo-dark lg:h-12 h-10 lg:mr-3 mx-auto mt-4 lg:mt-0" alt="Amapizza" /> 1926 1927 1928<img style="display: none" class="logo-light" src="https://sistemaquevende.s3.eu-north-1.amazonaws.com/platform/slim/6706ef288778c744cbd16350c9c2d6e0.png" /> </a> 1929 </div> 1930 1931 </div> 1932 <!-- Initial Block Start Authentication --> 1933 <div class="block block-active" id="block-phone"> 1934 <div class="block-content opacity-100 translate-y-0 scale-100 transition-all ease-in-out duration-150"> 1935 <form id="auth-start"> 1936 <div class="mb-10 text-center"> 1937 <div class="text-xl font-medium dark:text-gray-100">Faça login ou crie uma conta</div> 1938 </div> 1939 <div class="mb-4 flex"> 1940 <div class="w-1/3 hidden pr-2" id="country-code"> 1941 <label for="phone-code" class="block mb-2 text-sm text-gray-800 dark:text-white">PaÃs</label> 1942 <select id="phone-code" name="phone-code" class="bg-gray-50 border border-gray-400 text-gray-900 text-sm rounded-lg block w-full p-2.5 dark:bg-zinc-950 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white"> 1943 <option value="+351">(+351) ðµð¹ Portugal</option> 1944<option value="+1">ðºð¸ United States (+1)</option> 1945<option value="+44">ð¬ð§ United Kingdom (+44)</option> 1946<option value="+93">ð¦ð« Afghanistan (+93)</option> 1947<option value="+355">ð¦ð± Albania (+355)</option> 1948<option value="+213">ð©ð¿ Algeria (+213)</option> 1949<option value="+376">ð¦ð© Andorra (+376)</option> 1950<option value="+244">ð¦ð´ Angola (+244)</option> 1951<option value="+54">ð¦ð· Argentina (+54)</option> 1952<option value="+374">ð¦ð² Armenia (+374)</option> 1953<option value="+61">ð¦ðº Australia (+61)</option> 1954<option value="+43">ð¦ð¹ Austria (+43)</option> 1955<option value="+994">ð¦ð¿ Azerbaijan (+994)</option> 1956<option value="+973">ð§ð Bahrain (+973)</option> 1957<option value="+880">ð§ð© Bangladesh (+880)</option> 1958<option value="+32">ð§ðª Belgium (+32)</option> 1959<option value="+501">ð§ð¿ Belize (+501)</option> 1960<option value="+229">ð§ð¯ Benin (+229)</option> 1961<option value="+975">ð§ð¹ Bhutan (+975)</option> 1962<option value="+387">ð§ð¦ Bosnia and Herzegovina (+387)</option> 1963<option value="+55">ð§ð· Brazil (+55)</option> 1964<option value="+359">ð§ð¬ Bulgaria (+359)</option> 1965<option value="+226">ð§ð« Burkina Faso (+226)</option> 1966<option value="+257">ð§ð® Burundi (+257)</option> 1967<option value="+237">ð¨ð² Cameroon (+237)</option> 1968<option value="+1">ð¨ð¦ Canada (+1)</option> 1969<option value="+238">ð¨ð» Cape Verde (+238)</option> 1970<option value="+236">ð¨ð« Central African Republic (+236)</option> 1971<option value="+235">ð¹ð© Chad (+235)</option> 1972<option value="+56">ð¨ð± Chile (+56)</option> 1973<option value="+86">ð¨ð³ China (+86)</option> 1974<option value="+57">ð¨ð´ Colombia (+57)</option> 1975<option value="+269">ð°ð² Comoros (+269)</option> 1976<option value="+242">ð¨ð¬ Congo (+242)</option> 1977<option value="+243">ð¨ð© Congo, Dem. Rep. (+243)</option> 1978<option value="+506">ð¨ð· Costa Rica (+506)</option> 1979<option value="+385">ðð· Croatia (+385)</option> 1980<option value="+53">ð¨ðº Cuba (+53)</option> 1981<option value="+357">ð¨ð¾ Cyprus (+357)</option> 1982<option value="+420">ð¨ð¿ Czech Republic (+420)</option> 1983<option value="+45">ð©ð° Denmark (+45)</option> 1984<option value="+253">ð©ð¯ Djibouti (+253)</option> 1985<option value="+1">ð©ð² Dominica (+1)</option> 1986<option value="+1">ð©ð´ Dominican Republic (+1)</option> 1987<option value="+593">ðªð¨ Ecuador (+593)</option> 1988<option value="+20">ðªð¬ Egypt (+20)</option> 1989<option value="+503">ð¸ð» El Salvador (+503)</option> 1990<option value="+240">ð¬ð¶ Equatorial Guinea (+240)</option> 1991<option value="+291">ðªð· Eritrea (+291)</option> 1992<option value="+372">ðªðª Estonia (+372)</option> 1993<option value="+251">ðªð¹ Ethiopia (+251)</option> 1994<option value="+679">ð«ð¯ Fiji (+679)</option> 1995<option value="+358">ð«ð® Finland (+358)</option> 1996<option value="+33">ð«ð· France (+33)</option> 1997<option value="+241">ð¬ð¦ Gabon (+241)</option> 1998<option value="+220">ð¬ð² Gambia (+220)</option> 1999<option value="+995">ð¬ðª Georgia (+995)</option> 2000<option value="+49">ð©ðª Germany (+49)</option> 2001<option value="+233">ð¬ð Ghana (+233)</option> 2002<option value="+30">ð¬ð· Greece (+30)</option> 2003<option value="+1">ð¬ð© Grenada (+1)</option> 2004<option value="+502">ð¬ð¹ Guatemala (+502)</option> 2005<option value="+224">ð¬ð³ Guinea (+224)</option> 2006<option value="+245">ð¬ð¼ Guinea-Bissau (+245)</option> 2007<option value="+592">ð¬ð¾ Guyana (+592)</option> 2008<option value="+509">ðð¹ Haiti (+509)</option> 2009<option value="+504">ðð³ Honduras (+504)</option> 2010<option value="+36">ððº Hungary (+36)</option> 2011<option value="+354">ð®ð¸ Iceland (+354)</option> 2012<option value="+91">ð®ð³ India (+91)</option> 2013<option value="+62">ð®ð© Indonesia (+62)</option> 2014<option value="+98">ð®ð· Iran (+98)</option> 2015<option value="+964">ð®ð¶ Iraq (+964)</option> 2016<option value="+353">ð®ðª Ireland (+353)</option> 2017<option value="+972">ð®ð± Israel (+972)</option> 2018<option value="+39">ð®ð¹ Italy (+39)</option> 2019<option value="+1">ð¯ð² Jamaica (+1)</option> 2020<option value="+81">ð¯ðµ Japan (+81)</option> 2021<option value="+962">ð¯ð´ Jordan (+962)</option> 2022<option value="+7">ð°ð¿ Kazakhstan (+7)</option> 2023<option value="+254">ð°ðª Kenya (+254)</option> 2024<option value="+686">ð°ð® Kiribati (+686)</option> 2025<option value="+383">ð½ð° Kosovo (+383)</option> 2026<option value="+965">ð°ð¼ Kuwait (+965)</option> 2027<option value="+996">ð°ð¬ Kyrgyzstan (+996)</option> 2028<option value="+856">ð±ð¦ Laos (+856)</option> 2029<option value="+371">ð±ð» Latvia (+371)</option> 2030<option value="+961">ð±ð§ Lebanon (+961)</option> 2031<option value="+266">ð±ð¸ Lesotho (+266)</option> 2032<option value="+231">ð±ð· Liberia (+231)</option> 2033<option value="+218">ð±ð¾ Libya (+218)</option> 2034<option value="+423">ð±ð® Liechtenstein (+423)</option> 2035<option value="+370">ð±ð¹ Lithuania (+370)</option> 2036<option value="+352">ð±ðº Luxembourg (+352)</option> 2037<option value="+853">ð²ð´ Macau (+853)</option> 2038<option value="+389">ð²ð° Macedonia (+389)</option> 2039<option value="+261">ð²ð¬ Madagascar (+261)</option> 2040<option value="+265">ð²ð¼ Malawi (+265)</option> 2041<option value="+60">ð²ð¾ Malaysia (+60)</option> 2042<option value="+960">ð²ð» Maldives (+960)</option> 2043<option value="+223">ð²ð± Mali (+223)</option> 2044<option value="+356">ð²ð¹ Malta (+356)</option> 2045<option value="+692">ð²ð Marshall Islands (+692)</option> 2046<option value="+222">ð²ð· Mauritania (+222)</option> 2047<option value="+230">ð²ðº Mauritius (+230)</option> 2048<option value="+52">ð²ð½ Mexico (+52)</option> 2049<option value="+373">ð²ð© Moldova (+373)</option> 2050<option value="+377">ð²ð¨ Monaco (+377)</option> 2051<option value="+976">ð²ð³ Mongolia (+976)</option> 2052<option value="+382">ð²ðª Montenegro (+382)</option> 2053<option value="+212">ð²ð¦ Morocco (+212)</option> 2054<option value="+258">ð²ð¿ Mozambique (+258)</option> 2055<option value="+95">ð²ð² Myanmar (+95)</option> 2056<option value="+264">ð³ð¦ Namibia (+264)</option> 2057<option value="+674">ð³ð· Nauru (+674)</option> 2058<option value="+977">ð³ðµ Nepal (+977)</option> 2059<option value="+31">ð³ð± Netherlands (+31)</option> 2060<option value="+687">ð³ð¨ New Caledonia (+687)</option> 2061<option value="+64">ð³ð¿ New Zealand (+64)</option> 2062<option value="+505">ð³ð® Nicaragua (+505)</option> 2063<option value="+227">
2063ð³ðª Niger (+227)</option> 2064<option value="+234">ð³ð¬ Nigeria (+234)</option> 2065<option value="+850">ð°ðµ North Korea (+850)</option> 2066<option value="+47">ð³ð´ Norway (+47)</option> 2067<option value="+968">ð´ð² Oman (+968)</option> 2068<option value="+92">ðµð° Pakistan (+92)</option> 2069<option value="+680">ðµð¼ Palau (+680)</option> 2070<option value="+970">ðµð¸ Palestine (+970)</option> 2071<option value="+507">ðµð¦ Panama (+507)</option> 2072<option value="+675">ðµð¬ Papua New Guinea (+675)</option> 2073<option value="+595">ðµð¾ Paraguay (+595)</option> 2074<option value="+51">ðµðª Peru (+51)</option> 2075<option value="+63">ðµð Philippines (+63)</option> 2076<option value="+48">ðµð± Poland (+48)</option> 2077<option value="+1">ðµð· Puerto Rico (+1)</option> 2078<option value="+974">ð¶ð¦ Qatar (+974)</option> 2079<option value="+40">ð·ð´ Romania (+40)</option> 2080<option value="+7">ð·ðº Russia (+7)</option> 2081<option value="+250">ð·ð¼ Rwanda (+250)</option> 2082<option value="+1">ð°ð³ Saint Kitts and Nevis (+1)</option> 2083<option value="+1">ð±ð¨ Saint Lucia (+1)</option> 2084<option value="+1">ð»ð¨ Saint Vincent and the Grenadines (+1)</option> 2085<option value="+685">ð¼ð¸ Samoa (+685)</option> 2086<option value="+378">ð¸ð² San Marino (+378)</option> 2087<option value="+239">ð¸ð¹ Sao Tome and Principe (+239)</option> 2088<option value="+966">ð¸ð¦ Saudi Arabia (+966)</option> 2089<option value="+221">ð¸ð³ Senegal (+221)</option> 2090<option value="+381">ð·ð¸ Serbia (+381)</option> 2091<option value="+248">ð¸ð¨ Seychelles (+248)</option> 2092<option value="+232">ð¸ð± Sierra Leone (+232)</option> 2093<option value="+65">ð¸ð¬ Singapore (+65)</option> 2094<option value="+421">ð¸ð° Slovakia (+421)</option> 2095<option value="+386">ð¸ð® Slovenia (+386)</option> 2096<option value="+677">ð¸ð§ Solomon Islands (+677)</option> 2097<option value="+252">ð¸ð´ Somalia (+252)</option> 2098<option value="+27">ð¿ð¦ South Africa (+27)</option> 2099<option value="+82">ð°ð· South Korea (+82)</option> 2100<option value="+211">ð¸ð¸ South Sudan (+211)</option> 2101<option value="+34">ðªð¸ Spain (+34)</option> 2102<option value="+94">ð±ð° Sri Lanka (+94)</option> 2103<option value="+249">ð¸ð© Sudan (+249)</option> 2104<option value="+597">ð¸ð· Suriname (+597)</option> 2105<option value="+46">ð¸ðª Sweden (+46)</option> 2106<option value="+41">ð¨ð Switzerland (+41)</option> 2107<option value="+963">ð¸ð¾ Syria (+963)</option> 2108<option value="+886">ð¹ð¼ Taiwan (+886)</option> 2109<option value="+992">ð¹ð¯ Tajikistan (+992)</option> 2110<option value="+255">ð¹ð¿ Tanzania (+255)</option> 2111<option value="+66">ð¹ð Thailand (+66)</option> 2112<option value="+228">ð¹ð¬ Togo (+228)</option> 2113<option value="+676">ð¹ð´ Tonga (+676)</option> 2114<option value="+1-868">ð¹ð¹ Trinidad and Tobago (+1-868)</option> 2115<option value="+216">ð¹ð³ Tunisia (+216)</option> 2116<option value="+90">ð¹ð· Turkey (+90)</option> 2117<option value="+993">ð¹ð² Turkmenistan (+993)</option> 2118<option value="+688">ð¹ð» Tuvalu (+688)</option> 2119<option value="+256">ðºð¬ Uganda (+256)</option> 2120<option value="+380">ðºð¦ Ukraine (+380)</option> 2121<option value="+971">ð¦ðª United Arab Emirates (+971)</option> 2122<option value="+44">ð¬ð§ United Kingdom (+44)</option> 2123<option value="+1">ðºð¸ United States (+1)</option> 2124<option value="+598">ðºð¾ Uruguay (+598)</option> 2125<option value="+998">ðºð¿ Uzbekistan (+998)</option> 2126<option value="+678">ð»ðº Vanuatu (+678)</option> 2127<option value="+39">ð»ð¦ Vatican City (+39)</option> 2128<option value="+58">ð»ðª Venezuela (+58)</option> 2129<option value="+84">ð»ð³ Vietnam (+84)</option> 2130<option value="+1-340">ð»ð® U.S. Virgin Islands (+1-340)</option> 2131<option value="+681">ð¼ð« Wallis and Futuna (+681)</option> 2132<option value="+212">ðªð Western Sahara (+212)</option> 2133<option value="+967">ð¾ðª Yemen (+967)</option> 2134<option value="+260">ð¿ð² Zambia (+260)</option> 2135<option value="+263">ð¿ð¼ Zimbabwe (+263)</option> </select> 2136 </div> 2137 <div class="w-full"> 2138 <label for="email" class="block mb-2 text-sm text-gray-800 dark:text-white ">Email ou Contato</label> 2139 <input id="auth-input" placeholder="Digite seu Email ou Contato" type="text" class="bg-gray-50 border border-gray-400 text-gray-900 text-sm rounded-lg block w-full p-2.5 dark:bg-zinc-950 dark:border-zinc-600 dark:placeholder-gray-300 dark:text-white" required> 2140 </div> 2141 </div> 2142 <div id="phone-real-number-warning" class="hidden flex items-start gap-2 p-3 mb-4 text-xs text-yellow-800 rounded-lg bg-yellow-50 dark:bg-gray-800 dark:text-yellow-300" role="alert"> 2143 <i class="bi bi-exclamation-triangle-fill mt-0.5"></i>
2144 <span>Introduza um número de telemóvel real: vamos enviar um SMS com o código de verificação para confirmar a sua identidade.</span> 2145 </div> 2146 <div class=" w-full"> 2147 <button type="submit" class="button-primary disable-after-click w-full text-sm px-5 py-2.5 text-center"> 2148 Continuar 2149 </button> 2150 </div> 2151 </form> 2152 </div> 2153 </div> 2154 <!-- Block Verify Phone Code --> 2155 <div class="block hidden" id="block-phone-verify"> 2156 <div class="block-content opacity-100 translate-y-0 scale-100 transition-all ease-in-out duration-150"> 2157 <form id="verify-email"> 2158 <div class="mb-10 text-left relative grid grid-cols-10"> 2159 <div> 2160 <a href="#" id="phone-verify-back" data-prev-block="block-phone" class="cursor-pointer px-2 pt-3 pb-2 rounded top-0 hover:bg-gray-100"> 2161 <i class="bi bi-chevron-left text-2xl"></i> 2162 </a> 2163 </div> 2164 <div class="text-xl font-medium dark:text-gray-100 text-center col-span-8">Verificar o código</div> 2165 <div></div> 2166 </div> 2167 <p id="verify-code-target" class="text-sm text-center text-gray-600 dark:text-gray-300 mb-4 px-4"></p> 2168 <div id="digit-container" class="flex mb-4 space-x-4 lg:px-8"> 2169 <input id="verification-code-focus" type="number" maxlength="1" class="w-full py-4 text-center text-xl rounded-lg bg-gray-50 dark:bg-zinc-900 border-2 border-gray-400 digit-input dark:text-gray-100" /> 2170 <input type="number" maxlength="1" class="w-full py-4 text-center text-xl rounded-lg bg-gray-50 dark:bg-zinc-900 border-2 border-gray-400 digit-input dark:text-gray-100" /> 2171 <input type="number" maxlength="1" class="w-full py-4 text-center text-xl rounded-lg bg-gray-50 dark:bg-zinc-900 border-2 border-gray-400 digit-input dark:text-gray-100" /> 2172 <input type="number" maxlength="1" class="w-full py-4 text-center text-xl rounded-lg bg-gray-50 dark:bg-zinc-900 border-2 border-gray-400 digit-input dark:text-gray-100" /> 2173 </div> 2174 <div class="text-center text-sm mt-2"> 2175 <span class="text-gray-600 dark:text-gray-300">Não recebeu o código?</span> 2176 <button type="button" id="resend-phone-code" class="text-primary font-medium ml-1 disabled:opacity-50 disabled:cursor-not-allowed">Reenviar código</button> 2177 </div> 2178 <div class="text-center text-sm mt-3"> 2179 <a href="#" id="switch-to-email-login" class="text-primary font-medium">Prefere continuar com e-mail?</a> 2180 </div> 2181 </form> 2182 </div> 2183 </div> 2184 <!-- Block Login With E-mail --> 2185 <div class="block hidden" id="block-login"> 2186 <div class="block-content opacity-0 translate-y-4 scale-95 -mr-10 transition-all ease-in-out duration-150"> 2187 <form id="form-login" method="POST"> 2188 <input type="hidden" name="_token" value="HDBg9B2KzZHDdOKTakPwEkNffqEqBE0Fw69HVnx2"> <div class="mb-10 text-left relative grid grid-cols-10"> 2189 <div> 2190 <a href="#" data-prev-block="block-phone" class="cursor-pointer px-2 pt-3 pb-2 rounded top-0 hover:bg-gray-100"> 2191 <i class="bi bi-chevron-left text-2xl"></i> 2192 </a> 2193 </div> 2194 <div class="text-xl font-medium dark:text-gray-100 text-center col-span-8">Entrar</div> 2195 <div></div> 2196 </div> 2197 <div class="mb-4 hidden"> 2198 <label for="email" class="block mb-2 text-sm text-gray-800 dark:text-white">Endereço de email</label> 2199 <input id="email-login" placeholder="Endereço de email" type="email" name="email" class="bg-gray-50 border border-gray-400 text-gray-900 text-sm rounded-lg block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white" required> 2200 </div> 2201 <div class="mb-4"> 2202 <div class="flex"> 2203 <div class="w-1/2"> 2204 <label for="password" class="block mb-2 text-sm text-gray-800 dark:text-white">Digite seu Senha</label> 2205 </div> 2206 <div class="w-1/2 text-right"> 2207 <a href="#" data-next-block="block-password-reset" class="text-primary mb-2 text-sm">Recuperar Senha</a> 2208 </div> 2209 </div> 2210 <div class="relative"> 2211 <input placeholder="Digite seu Senha" type="password" name="password" id="password" class="bg-gray-50 border border-gray-400 text-gray-900 text-sm rounded-lg block w-full p-2.5 pr-10 dark:bg-zinc-950 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white" required> 2212 <button type="button" onclick="togglePassword('password', this)" class="absolute inset-y-0 right-0 flex items-center px-3 text-gray-500 dark:text-gray-300 hover:text-gray-700 dark:hover:text-white focus:outline-none"> 2213 <i class="bi bi-eye text-lg"></i> 2214 </button> 2215 </div> 2216 </div> 2217 <div class=" w-full"> 2218 <button type="submit" class="button-primary w-full text-sm px-5 py-2.5 text-center"> 2219 Entrar 2220 </button> 2221 </div> 2222 </form> 2223 </div> 2224 </div> 2225 <!-- Block Send Reset Link --> 2226 <div class="block hidden" id="block-password-reset"> 2227 <div class="block-content opacity-0 translate-y-4 scale-95 -mr-10 transition-all ease-in-out duration-150"> 2228 <form id="form-password-reset"> 2229 <input type="hidden" name="_token" value="HDBg9B2KzZHDdOKTakPwEkNffqEqBE0Fw69HVnx2"> <div class="mb-10 text-left relative grid grid-cols-10"> 2230 <div> 2231 <a href="#" data-prev-block="block-login" class="cursor-pointer px-2 pt-3 pb-2 rounded top-0 hover:bg-gray-100"> 2232 <i class="bi bi-chevron-left text-2xl"></i> 2233 </a> 2234 </div> 2235 <div class="text-xl font-medium dark:text-gray-100 text-center col-span-8">Recuperar Senha</div> 2236 <div></div> 2237 </div> 2238 <div class="mb-4"> 2239 <div class="flex items-center p-4 mb-4 text-sm text-yellow-800 rounded-lg bg-yellow-50 dark:bg-gray-800 dark:text-yellow-300" role="alert"> 2240 <svg class="flex-shrink-0 inline w-4 h-4 mr-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"> 2241 <path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"/> 2242 </svg>
2243 <span class="sr-only">Info</span> 2244 <div> 2245 <span class="font-medium">Nota: </span> Pode demorar entre 1 a 10 minutos até o email chegar à sua caixa de entrada. 2246 <br> Se não o receber dentro deste perÃodo, por favor verifique também a pasta de spam. 2247 </div> 2248 </div> 2249 </div> 2250 <div class="mb-4 "> 2251 <label for="email" class="block mb-2 text-sm text-gray-800 dark:text-white">Endereço de email</label> 2252 <input id="email-reset" placeholder="Digite seu Endereço de email" type="email" name="email" class="bg-gray-50 border border-gray-400 text-gray-900 text-sm rounded-lg block w-full p-2.5 dark:bg-zinc-950 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white" required> 2253 </div> 2254 <div class=" w-full"> 2255 <button type="submit" class="button-primary disable-after-click w-full text-sm px-5 py-2.5 text-center"> 2256 Enviar email de recuperação 2257 </button> 2258 </div> 2259 </form> 2260 </div> 2261 </div> 2262 <!-- Block Login Register with E-mail --> 2263 <div class="block hidden" id="block-register"> 2264 <div class="block-content opacity-0 translate-y-4 scale-95 -mr-10 transition-all ease-in-out duration-150"> 2265 <form id="form-register" method="POST"> 2266 <input type="hidden" name="_token" value="HDBg9B2KzZHDdOKTakPwEkNffqEqBE0Fw69HVnx2"> <div class="mb-10 text-left relative grid grid-cols-10"> 2267 <div> 2268 <a href="#" data-prev-block="block-phone" class="cursor-pointer px-2 pt-3 pb-2 rounded top-0 hover:bg-gray-100"> 2269 <i class="bi bi-chevron-left text-2xl"></i> 2270 </a> 2271 </div> 2272 <div class="text-xl font-medium dark:text-gray-100 text-center col-span-8">Criar uma conta</div> 2273 <div></div> 2274 </div> 2275 <div class="mb-4"> 2276 <label for="name" class="block mb-2 text-sm text-gray-800 dark:text-white">Digite seu Nome</label> 2277 <input id="name" placeholder="Seu(a) Nome" type="text" name="name" class="bg-gray-50 border border-gray-400 text-gray-900 text-sm rounded-lg block w-full p-2.5 dark:bg-zinc-950 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white" required> 2278 </div> 2279 <div class="mb-4 hidden"> 2280 <label for="email" class="block mb-2 text-sm text-gray-800 dark:text-white">site.common.email-adress</label> 2281 <input id="email-register" placeholder="Seu(a) site.common.email-adress" type="email" name="email" class="bg-gray-50 border border-gray-400 text-gray-900 text-sm rounded-lg block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white" required> 2282 </div> 2283 <div class="mb-4"> 2284 <label for="passwo5rd" class="block mb-2 text-sm text-gray-800 dark:text-white">Digite seu Senha</label> 2285 <div class="relative"> 2286 <input id="password-register" placeholder="Senha" name="password" type="password" class="bg-gray-50 border border-gray-400 text-gray-900 text-sm rounded-lg block w-full p-2.5 pr-10 dark:bg-zinc-950 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white" required> 2287 <button type="button" onclick="togglePassword('password-register', this)" class="absolute inset-y-0 right-0 flex items-center px-3 text-gray-500 dark:text-gray-300 hover:text-gray-700 dark:hover:text-white focus:outline-none"> 2288 <i class="bi bi-eye text-lg"></i> 2289 </button> 2290 </div> 2291 </div> 2292 <div class="mb-4"> 2293 <label for="password" class="block mb-2 text-sm text-gray-800 dark:text-white">Confirmar Senha</label> 2294 <div class="relative"> 2295 <input id="password-confirmation" type="password" placeholder="Confirmar Senha" class="bg-gray-50 border border-gray-400 text-gray-900 text-sm rounded-lg block w-full p-2.5 pr-10 dark:bg-zinc-950 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white" name="password_confirmation" required autocomplete="new-password"> 2296 <button type="button" onclick="togglePassword('password-confirmation', this)" class="absolute inset-y-0 right-0 flex items-center px-3 text-gray-500 dark:text-gray-300 hover:text-gray-700 dark:hover:text-white focus:outline-none"> 2297 <i class="bi bi-eye text-lg"></i> 2298 </button> 2299 </div> 2300 </div> 2301 2302 <div class="text-gray-800 dark:text-gray-300 flex mb-2 hidden "> 2303 <div class="bg-no-repeat table mr-3 align-middle overflow-hidden"><input id="newsletter-register" type="checkbox" checked class="h-4 w-4 text-black dark:border-gray-200 dark:bg-black cursor-pointer overflow-hidden" /></div> 2304 <label for="newsletter-register" class="flex-grow text-sm pb-3 cursor-pointer"> 2305 Não desejo receber e-mails sobre atualizações de produtos e recursos, melhores práticas de marketing e promoções relacionadas. 2306 </label> 2307 </div> 2308 2309 <div class=" w-full"> 2310 <button type="submit" class="button-primary disable-after-click w-full text-sm px-5 py-2.5 text-center"> 2311 Criar uma conta 2312 </button> 2313 </div> 2314 </form> 2315 </div> 2316 </div> 2317 <!-- Another Login Ways --> 2318 <div class="text-xs text-center mt-5"> 2319 <hr class="dark:border-zinc-700"> 2320 <input class="hidden" type="text" id="auth-type" value="phone"> 2321 <p class="mt-5 mx-5 text-gray-600 dark:text-gray-300">Ao fazer login ou criar uma conta, você concorda com nossos 2322 <a href="/terms-and-conditions" class="text-primary external">Termos e Condições</a> 2323 e com a 2324 <a href="/privacy" class="text-primary external">PolÃtica de Privacidade</a> 2325 </p> 2326 </div> 2327 </div> 2328 </div> 2329 </div> 2330 </div> 2331 </div> 2332 2333 2334
2334<script> 2335 $(function() { 2336 // Auth Start 2337 $('#auth-start').on('submit', function(e) { 2338 e.preventDefault(); // prevent form from reloading page 2339 if ($("#auth-type").val() == "email") { 2340 $.ajax({ 2341 type: 'POST', 2342 url: '/auth/email/verify', // URL to your Laravel route for verifying email 2343 headers: { 2344 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') 2345 }, 2346 data: { 2347 email: $("#auth-input").val() 2348 }, // Serialize form data for submission 2349 dataType: "json", 2350 success: function(response) { 2351 if (response.success) { 2352 $("#email-login").val($("#auth-input").val()); 2353 $("#email-reset").val($("#auth-input").val()); 2354 transitionToNextBlock("block-login"); 2355 setTimeout(() => { 2356 $('#password').focus(); 2357 }, 1000); 2358 2359 } else { 2360 var errors = response.errors; 2361 // Check if errors is a string 2362 if (typeof errors === 'string') { 2363 // If so, just display it 2364 //toast('error', errors, 4000); 2365 if (errors == "email-not-found") { 2366 $("#email-register").val($("#auth-input").val()); 2367 2368 transitionToNextBlock("block-register"); 2369 2370 $('#name').focus(); 2371 2372 } 2373 } else { 2374 // If not, then it's an object, so loop through it 2375 for (var key in errors) { 2376 if (errors.hasOwnProperty(key)) { 2377 toast('error', errors[key], 4000); 2378 } 2379 } 2380 } 2381 } 2382 }, 2383 error: function() { 2384 toast('error', '[500] Algo Deu Errado', 3000); 2385 } 2386 }).fail(function(jqXHR, textStatus, errorThrown) { 2387 if (jqXHR.status == 419) { 2388 // CSRF token expired 2389 window.location.reload(); 2390 } 2391 }); 2392 } else { 2393 requestPhoneVerificationCode(function() { 2394 transitionToNextBlock("block-phone-verify"); 2395 startResendCooldown(30); 2396 setTimeout(() => { 2397 $("#verification-code-focus").focus(); 2398 }, 500); 2399 }); 2400 } 2401 }); 2402 2403 // Send/Resend Phone Verification Code 2404 function requestPhoneVerificationCode(onSuccess) { 2405 const rawPhone = $("#auth-input").val() || ''; 2406 const normalizedPhone = rawPhone.replace(/\D/g, ''); 2407 const selectedCode = $("#phone-code").val(); 2408 2409 if (!isValidPhoneByCountry(normalizedPhone, selectedCode)) { 2410 showPhoneMinLengthError(selectedCode); 2411 return; 2412 } 2413 2414 $.ajax({ 2415 type: 'POST', 2416 url: '/auth/phone/verify/code', // URL to your Laravel route for verifying email 2417 headers: { 2418 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') 2419 }, 2420 data: { 2421 code: selectedCode, 2422 phone: normalizedPhone 2423 }, // Serialize form data for submission 2424 dataType: "json", 2425 success: function(response) { 2426 if (response.success) { 2427 updateVerifyCodeTarget(selectedCode, normalizedPhone); 2428 if (typeof onSuccess === 'function') { 2429 onSuccess(); 2430 } 2431 } else { 2432 var errors = response.errors; 2433 // Check if errors is a string 2434 if (typeof errors === 'string') { 2435 // If so, just display it 2436 toast('error', errors, 4000); 2437 } else { 2438 // If not, then it's an object, so loop through it 2439 for (var key in errors) { 2440 if (errors.hasOwnProperty(key)) { 2441 toast('error', errors[key], 4000); 2442 } 2443 } 2444 } 2445 } 2446 }, 2447 error: function() { 2448 toast('error', '[500] Algo Deu Errado', 3000); 2449 } 2450 }).fail(function(jqXHR, textStatus, errorThrown) { 2451 if (jqXHR.status == 419) { 2452 // CSRF token expired 2453 window.location.reload(); 2454 } 2455 }); 2456 } 2457 2458 function maskPhoneNumber(phone) { 2459 const digits = String(phone || '').replace(/\D/g, ''); 2460 if (digits.length <= 4) { 2461 return digits.replace(/./g, 'â¢'); 2462 } 2463 return digits.slice(0, 2) + 'â¢'.repeat(digits.length - 4) + digits.slice(-2); 2464 } 2465 2466 function updateVerifyCodeTarget(code, phone) { 2467 $('#verify-code-target').html( 2468 'Enviámos um código de verificação por SMS para <strong>' + code + ' ' + maskPhoneNumber(phone) + '</strong>.' 2469 ); 2470 } 2471 2472 var resendCooldownTimer = null; 2473 2474 function startResendCooldown(seconds) { 2475 const $btn = $('#resend-phone-code'); 2476 let remaining = seconds; 2477 $btn.prop('disabled', true).text('Reenviar código (' + remaining + 's)'); 2478 clearInterval(resendCooldownTimer); 2479 resendCooldownTimer = setInterval(function() { 2480 remaining -= 1; 2481 if (remaining <= 0) { 2482 clearInterval(resendCooldownTimer); 2483 $btn.prop('disabled', false).text('Reenviar código'); 2484 } else { 2485 $btn.text('Reenviar código (' + remaining + 's)'); 2486 } 2487 }, 1000); 2488 } 2489 2490 $('#resend-phone-code').on('click', function() { 2491 requestPhoneVerificationCode(function() { 2492 $('.digit-input').val(''); 2493 $('#verification-code-focus').focus(); 2494 toast('success', 'Um novo código foi enviado.', 3000); 2495 startResendCooldown(30); 2496 }); 2497 }); 2498 2499 $('#switch-to-email-login').on('click', function(e) { 2500 e.preventDefault(); 2501 clearInterval(resendCooldownTimer); 2502 $('.digit-input').val(''); 2503 $('#auth-type').val('email'); 2504 $('#country-code').addClass('hidden'); 2505 $('#phone-real-number-warning').addClass('hidden'); 2506 $('#auth-input').val('').removeAttr('inputmode').removeAttr('minlength').removeAttr('title'); 2507 transitionToPrevBlock('block-phone'); 2508 setTimeout(function() { 2509 $('#auth-input').focus(); 2510 }, 300); 2511 }); 2512 2513 $('#phone-verify-back').on('click', function() { 2514 clearInterval(resendCooldownTimer); 2515 $('#resend-phone-code').prop('disabled', false).text('Reenviar código'); 2516 $('.digit-input').val(''); 2517 }); 2518 // Auth Input 2519 function resolveAuthInputType(rawValue) { 2520 const value = (rawValue || '').trim(); 2521 2522 if (!value) { 2523 return null; 2524 } 2525 2526 // While typing an email, prefer email mode as soon as user shows email intent. 2527 const hasAt = value.includes('@'); 2528 const hasLetters = /[a-zA-Z]/.test(value); 2529 if (hasAt || hasLetters) { 2530 return 'email'; 2531 } 2532 2533 // Phone mode only when the value is composed of phone-like chars. 2534 const phoneLike = /^[0-9+()\-\s]+$/.test(value); 2535 return phoneLike ? 'phone' : null; 2536 } 2537 2538 function normalizePhone(value) { 2539 return (value || '').replace(/\D/g, ''); 2540 } 2541 2542 function getPhoneMinLengthByCode(code) { 2543 const normalizedCode = String(code || '').trim(); 2544 return normalizedCode === '+351' ? 9 : 4; 2545 } 2546 2547 function isValidPhoneByCountry(phoneValue, codeValue) { 2548 return normalizePhone(phoneValue).length >= getPhoneMinLengthByCode(codeValue); 2549 } 2550 2551 function updatePhoneConstraints() { 2552 const selectedCode = $("#phone-code").val(); 2553 const minLength = getPhoneMinLengthByCode(selectedCode); 2554 2555 $("#auth-input") 2556 .attr('minlength', minLength) 2557 .attr('title', 'Para o indicativo selecionado, informe no minimo ' + minLength + ' digitos.'); 2558 } 2559 2560 function showPhoneMinLengthError(codeValue) { 2561 const minLength = getPhoneMinLengthByCode(codeValue); 2562 toast('error', 'Para o indicativo selecionado, o numero de telefone deve ter no minimo ' + minLength + ' caracteres.', 4000); 2563 } 2564 2565 $("#auth-input").on("input", function() { 2566 const type = resolveAuthInputType($(this).val()); 2567 2568 if (type === 'email') { 2569 $("#auth-type").val("email"); 2570 $("#country-code").addClass("hidden"); 2571 $("#phone-real-number-warning").addClass("hidden"); 2572 return; 2573 } 2574 2575 if (type === 'phone') { 2576 $("#auth-type").val("phone"); 2577 $("#country-code").removeClass("hidden"); 2578 $("#phone-real-number-warning").removeClass("hidden"); 2579 $(this).attr('inputmode', 'numeric'); 2580 updatePhoneConstraints(); 2581 return; 2582 } 2583 2584 $("#auth-type").val("email"); 2585 $("#country-code").addClass("hidden"); 2586 $("#phone-real-number-warning").addClass("hidden"); 2587 $(this).removeAttr('inputmode'); 2588 $(this).removeAttr('minlength').removeAttr('title'); 2589 }); 2590 2591 $("#phone-code").on("change", function() { 2592 updatePhoneConstraints(); 2593 }); 2594 $('#form-login').on('submit', function(e) { 2595 e.preventDefault(); 2596 var email = $('#email-login').val(); 2597 var password = $('#password').val(); 2598 $.ajax({ 2599 type: 'POST', 2600 url: '/auth/login', // URL to your Laravel route for login 2601 headers: { 2602 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') // Laravel CSRF token 2603 }, 2604 data: { 2605 email: email, 2606 password: password 2607 }, 2608 dataType: "json", 2609 success: function(response) { 2610 if (response.success) { 2611 if (response.url) { 2612 window.location.href=response.url 2613 } else { 2614 location.reload(); 2615 } 2616 } else { 2617 var errors = response.errors; 2618 // Check if errors is a string 2619 if (typeof errors === 'string') { 2620 // If so, just display it 2621 toast('error', errors, 4000); 2622 } else { 2623 // If not, then it's an object, so loop through it 2624 for (var key in errors) { 2625 if (errors.hasOwnProperty(key)) { 2626 toast('error', errors[key], 4000); 2627 } 2628 } 2629 } 2630 } 2631 }, 2632 error: function() { 2633 toast('error', '[500] Algo Deu Errado', 3000); 2634 } 2635 }).fail(function(jqXHR, textStatus, errorThrown) { 2636 if (jqXHR.status == 419) { 2637 // CSRF token expired 2638 window.location.reload(); 2639 } 2640 }); 2641 }); 2642 $('#form-register').on('submit', function(e) { 2643 e.preventDefault(); 2644 var name = $('#name').val(); 2645 var email = $('#email-register').val(); 2646 var password = $('#password-register').val(); 2647 var password_confirmation = $('#password-confirmation').val(); 2648 var newsletter = $('#newsletter-register').prop('checked'); 2649 $.ajax({ 2650 type: 'POST',
2651 url: '/auth/register', // URL to your Laravel route for login 2652 headers: { 2653 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') // Laravel CSRF token 2654 }, 2655 data: { 2656 name: name, 2657 email: email, 2658 password: password, 2659 password_confirmation: password_confirmation, 2660 newsletter: newsletter, 2661 }, 2662 dataType: "json", 2663 success: function(response) { 2664 if (response.success) { 2665 const goToNextPage = () => { 2666 if (response.url) { 2667 window.location.href = response.url; 2668 } else { 2669 location.reload(); 2670 } 2671 }; 2672 2673 if (window.dataLayer && typeof window.dataLayer.push === 'function') { 2674 dataLayer.push({ 2675 event: 'registration_success', 2676 user_name: name, 2677 user_email: email, 2678 newsletter_subscribed: newsletter, 2679 eventCallback: goToNextPage, 2680 eventTimeout: 2000 // fallback se GTM demorar ou falhar 2681 }); 2682 } else { 2683 goToNextPage(); // GTM inativo: seguir normalmente 2684 } 2685 } 2686 else { 2687 var errors = response.errors; 2688 // Check if errors is a string 2689 if (typeof errors === 'string') { 2690 // If so, just display it 2691 toast('error', errors, 4000); 2692 } else { 2693 // If not, then it's an object, so loop through it 2694 for (var key in errors) { 2695 if (errors.hasOwnProperty(key)) { 2696 toast('error', errors[key], 4000); 2697 } 2698 } 2699 } 2700 } 2701 }, 2702 error: function() { 2703 toast('error', '[500] Algo Deu Errado', 3000); 2704 } 2705 }).fail(function(jqXHR, textStatus, errorThrown) { 2706 if (jqXHR.status == 419) { 2707 // CSRF token expired 2708 window.location.reload(); 2709 } 2710 }); 2711 }); 2712 $('#form-password-reset').on('submit', function(e) { 2713 e.preventDefault(); 2714 var email = $('#email-reset').val(); 2715 $.ajax({ 2716 type: 'POST', 2717 url: '/auth/password-reset', // URL to your Laravel route for login 2718 headers: { 2719 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') // Laravel CSRF token 2720 }, 2721 data: { 2722 email: email 2723 }, 2724 dataType: "json", 2725 success: function(response) { 2726 if (response.success) { 2727 toast('success', response.message, 4000); 2728 } else { 2729 var errors = response.errors; 2730 // Check if errors is a string 2731 if (typeof errors === 'string') { 2732 // If so, just display it 2733 toast('error', errors, 4000); 2734 } else { 2735 // If not, then it's an object, so loop through it 2736 for (var key in errors) { 2737 if (errors.hasOwnProperty(key)) { 2738 toast('error', errors[key], 4000); 2739 } 2740 } 2741 } 2742 } 2743 }, 2744 error: function() { 2745 toast('error', '[500] Algo Deu Errado', 3000); 2746 } 2747 }).fail(function(jqXHR, textStatus, errorThrown) { 2748 if (jqXHR.status == 419) { 2749 // CSRF token expired 2750 window.location.reload(); 2751 } 2752 }); 2753 }); 2754 $('.digit-input').first().on('input', function(e) { 2755 var inputVal = $(this).val(); 2756 // Split the input into an array of characters 2757 var inputArray = inputVal.split(''); 2758 // Assign each character to an input field 2759 if (inputArray.length == 4) { 2760 $('.digit-input').each(function(index) { 2761 $(this).val(inputArray[index]); 2762 }); 2763 verifyCode(inputVal) 2764 } 2765 }); 2766 $('.digit-input').on('paste', function(e) { 2767 // Prevent the default action 2768 e.preventDefault(); 2769 // Get pasted data 2770 var pastedData = e.originalEvent.clipboardData.getData('text'); 2771 // Split the pasted data into an array of characters 2772 var pastedDataArray = pastedData.split(''); 2773 // Assign each character to an input field 2774 $('.digit-input').each(function(index) { 2775 $(this).val(pastedDataArray[index]); 2776 }); 2777 verifyCode(pastedData) 2778 }); 2779 // Digit Verification Code 2780 $('.digit-input').keyup(function(e) { 2781 var key = e.which; 2782 // only allow numeric input 2783 if (key >= 48 && key <= 57) { 2784 $(this).next('.digit-input').focus(); 2785 } 2786 // backspace key 2787 else if (key === 8) { 2788 $(this).prev('.digit-input').focus(); 2789 } 2790 var totalCharCount = 0; 2791 var completeNumber = ""; 2792 // Loop through all input elements 2793 $('.digit-input').each(function() { 2794 totalCharCount += $(this).val().length; 2795 completeNumber += $(this).val(); 2796 }); 2797 // Once four characters are entered 2798 if (totalCharCount === 4) { 2799 verifyCode(completeNumber) 2800 } 2801 }); 2802 // Default phone country code: Portugal (+351) 2803 if ($('#phone-code option[value="+351"]').length) { 2804 $("#phone-code").val("+351").change(); 2805 } else { 2806 $("#phone-code option:first").prop('selected', true); 2807 } 2808 2809 updatePhoneConstraints(); 2810 }); 2811 2812 function getPhoneMinLengthByCode(code) { 2813 const normalizedCode = String(code || '').trim(); 2814 return normalizedCode === '+351' ? 9 : 4; 2815 } 2816 2817 function isValidPhoneByCountry(phoneValue, codeValue) { 2818 return String(phoneValue || '').replace(/\D/g, '').length >= getPhoneMinLengthByCode(codeValue); 2819 } 2820 2821 function showPhoneMinLengthError(codeValue) { 2822 const minLength = getPhoneMinLengthByCode(codeValue); 2823 toast('error', 'Para o indicativo selecionado, o numero de telefone deve ter no minimo ' + minLength + ' caracteres.', 4000); 2824 } 2825 2826 function togglePassword(inputId, btn) { 2827 var input = document.getElementById(inputId); 2828 var icon = btn.querySelector('i'); 2829 if (input.type === 'password') { 2830 input.type = 'text'; 2831 icon.classList.remove('bi-eye'); 2832 icon.classList.add('bi-eye-slash'); 2833 } else { 2834 input.type = 'password'; 2835 icon.classList.remove('bi-eye-slash'); 2836 icon.classList.add('bi-eye'); 2837 } 2838 } 2839 2840 function verifyCode(code) { 2841 const selectedCode = $("#phone-code").val(); 2842 const normalizedPhone = ($("#auth-type").val() === 'phone') ? (($("#auth-input").val() || '').replace(/\D/g, '')) : $("#auth-input").val(); 2843 2844 if ($("#auth-type").val() === 'phone' && !isValidPhoneByCountry(normalizedPhone, selectedCode)) { 2845 showPhoneMinLengthError(selectedCode); 2846 return; 2847 } 2848 2849 $.ajax({ 2850 type: 'POST',
2851 url: '/auth/phone/verify', // URL to your Laravel route for verifying email 2852 headers: { 2853 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') // Laravel CSRF Token 2854 }, 2855 data: { 2856 code: $("#phone-code").val(), 2857 phone: normalizedPhone, 2858 verification_code: code 2859 }, // Serialized form data for submission 2860 dataType: "json", 2861 success: function(response) { 2862 if (response.success) { 2863 window.location.href = ""; // Replace with the actual URL 2864 } else { 2865 var errors = response.errors; 2866 // Check if errors is a string 2867 if (typeof errors === 'string') { 2868 // If so, just display it 2869 toast('error', errors, 4000); 2870 } else { 2871 // If not, then it's an object, so loop through it 2872 for (var key in errors) { 2873 if (errors.hasOwnProperty(key)) { 2874 toast('error', errors[key], 4000); 2875 } 2876 } 2877 } 2878 } 2879 }, 2880 error: function() { 2881 toast('error', '[500] Algo Deu Errado', 3000); 2882 } 2883 }).fail(function(jqXHR, textStatus, errorThrown) { 2884 if (jqXHR.status == 419) { 2885 // CSRF token expired 2886 window.location.reload(); 2887 } 2888 }); 2889 } 2890 </script>
2890 2891 2892 2893 2894 <!-- Payment Redirect --> 2895<div id="payment-redirect" class="fixed z-20 hidden" style="z-index: 60000 !important" aria-labelledby="modal-title" role="dialog" aria-modal="true"> 2896 <div class="modal-backdrop fixed opacity-0 inset-0 backdrop-filter backdrop-blur-md bg-black bg-opacity-60 transition-opacity ease-out duration-300"></div> 2897 <div class="fixed inset-0 z-30 overflow-y-auto"> 2898 <div class="text-white min-h-full items-center justify-center text-center "> 2899 <div class="modal-content flex items-center opacity-0 relative transform h-screen transition-all "> 2900 <div class="mx-auto px-5"> 2901 <h1 class="text-4xl w-full mb-4">Continuar Pagamento</h1> 2902 <h1 class="text-xl font-light mb-5 text-gray-200">Por favor, continue na página do provedor de pagamento</h1> 2903 <div class="text-center"> 2904 <a class="text-xl font-light text-gray-100 inline-block underline cursor-pointer mx-3" data-modal-close="payment-redirect">Fechar</a> 2905 <a class="text-xl font-light text-gray-100 inline-block underline cursor-pointer mx-3 redirect-to-provider" target="_blank">Voltar para Provedor</a> 2906 </div> 2907 </div> 2908 </div> 2909 </div> 2910 </div> 2911</div> 2912<!-- Payment Response --> 2913<div id="payment-response-modal" class="fixed z-20 hidden" style="z-index: 60000 !important" aria-labelledby="modal-title" role="dialog" aria-modal="true"> 2914 <div class="modal-backdrop fixed opacity-0 inset-0 backdrop-filter backdrop-blur-sm bg-white dark:bg-zinc-950 bg-opacity-90 dark:bg-opacity-70 transition-opacity ease-out duration-300"></div> 2915 <div class="fixed inset-0 z-30 overflow-y-auto"> 2916 <div class="flex min-h-full items-center justify-center lg:p-4 px-4 text-center sm:items-center sm:p-0"> 2917 <div class="modal-content border border-gray-300 dark:border-zinc-600 opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95 relative transform overflow-hidden lg:h-auto rounded lg:rounded-lg bg-white dark:bg-zinc-950 text-left shadow-lg transition-all w-full max-w-xl"> 2918 <div class="bg-white dark:bg-zinc-950 relative"> 2919 <div class="px-6 pb-4 pt-3 border-b border-gray-200 dark:border-zinc-700"> 2920 <h1 class="text-xl text-center payment-response-title uppercase pt-2"></h1> 2921 </div> 2922 <div class="px-6 py-6 payment-response-body bg-gray-50 dark:bg-zinc-950 text-gray-800 dark:text-white"> 2923 2924 </div> 2925 <div class="text-center px-6 pb-4 bg-gray-50 dark:bg-zinc-950 dark:text-white space-x-2 flex"> 2926 <a class="button-black cursor-pointer payment-response-copy inline-block w-full px-7 py-3 transition-all ease-in-out duration-150 copy-text"> 2927 <i class="bi bi-clipboard"></i> Copiar 2928 </a> 2929 <a class="button-outline-red:active cursor-pointer payment-response-close inline-block w-full px-7 py-3 transition-all ease-in-out duration-150" data-modal-close="payment-response-modal"> 2930 Fechar 2931 </a> 2932 <input type="text" id="data-to-copy" class="hidden"> 2933 </div> 2934 </div> 2935 </div> 2936 </div> 2937 </div> 2938</div>
2939<script> 2940 let countdownInterval; 2941 function startCountdown(minutes) { 2942 if (countdownInterval) clearInterval(countdownInterval); 2943 let seconds = minutes * 180; 2944 let totalSeconds = minutes * 180; 2945 const countdownContainer = $(` 2946 <div class="countdown-container w-64 h-64 mx-auto rounded-full flex items-center justify-center text-4xl relative"> 2947 <div class="countdown">${formatTime(seconds)}</div> 2948 <svg class="countdown-svg absolute top-0 left-0 w-full h-full" viewBox="0 0 100 100"> 2949 <circle class="countdown-circle" cx="50" cy="50" r="45" stroke="black" stroke-width="2" fill="none" /> 2950 </svg> 2951 </div> 2952 `); 2953 $('.countdown-area').append(countdownContainer); 2954 const circle = countdownContainer.find('.countdown-circle')[0]; 2955 const radius = circle.r.baseVal.value; 2956 const circumference = radius * 2 * Math.PI; 2957 circle.style.strokeDasharray = `${circumference} ${circumference}`; 2958 circle.style.strokeDashoffset = `${circumference}`; 2959 function setProgress(percent) { 2960 const offset = circumference - (percent / 100 * circumference); 2961 circle.style.strokeDashoffset = offset; 2962 } 2963 countdownInterval = setInterval(function() { 2964 seconds--; 2965 countdownContainer.find('.countdown').text(formatTime(seconds)); 2966 setProgress((seconds / totalSeconds) * 100); 2967 if (seconds <= 0) { 2968 clearInterval(countdownInterval); 2969 closeModal("payment-response-modal") 2970 } 2971 }, 1000); 2972 } 2973 function formatTime(seconds) { 2974 let minutes = Math.floor(seconds / 180); 2975 let remainingSeconds = seconds % 180; 2976 if (minutes < 10) minutes = '0' + minutes; 2977 if (remainingSeconds < 10) remainingSeconds = '0' + remainingSeconds; 2978 return `${minutes}:${remainingSeconds}`; 2979 } 2980</script>
2980 2981
2981<script> 2982 $(function (){ 2983 2984 2985 }) 2986</script>
2986 2987 </div> 2988
2988<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBfFYFwmiDI1__TWJyHZfg1vev1uT4TAVY&callback=initMap&libraries=places"></script>
2988 2989
2989<script src="https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.js"></script>
2989 2990
2990<script src="/assets/js/script.js"></script>
2990 2991
2991<script src="/assets/js/cart.js"></script>
2991 2992
2992<script src="/assets/js/function.js"></script>
2992 2993
2993<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.7.0/min/dropzone.min.js"></script>
2993 2994
2994<script src="https://cdn.jsdelivr.net/npm/framework7/js/framework7.bundle.min.js"></script>
2994 2995 2996
2996<script> 2997 (function() { 2998 const existingFbp = localStorage.getItem('fbp'); 2999 if (!existingFbp) { 3000 const fbp = 'fb.1.' + Math.floor(Date.now() / 1000) + '.' + Math.floor(Math.random() * 1e17); 3001 localStorage.setItem('fbp', fbp); 3002 document.cookie = `_fbp=${fbp}; path=/;`; 3003 } 3004 })(); 3005 </script>
3005 3006 3007
3007<script> 3008 window.user = { 3009 id: null, 3010 email: null, 3011 name: null, 3012 phone: null, 3013 first_name: null, 3014 last_name: null, 3015 city: null, 3016 zip: null, 3017 country: null 3018 }; 3019 </script>
3019 3020 3021 3022 3023 <!-- GOOGLE TAG MANAGER (NOSCRIPT) --> 3024<!-- --> 3025
3025<script> 3026 3027 function setCookie(name, value, days) { 3028 const d = new Date(); 3029 d.setTime(d.getTime() + (days*24*60*60*1000)); 3030 const expires = "expires=" + d.toUTCString(); 3031 document.cookie = name + "=" + value + ";" + expires + ";path=/"; 3032 } 3033 3034 function getCookie(name) { 3035 const cname = name + "="; 3036 const decodedCookie = decodeURIComponent(document.cookie); 3037 const ca = decodedCookie.split(';'); 3038 for(let i = 0; i < ca.length; i++) { 3039 let c = ca[i].trim(); 3040 if (c.indexOf(cname) === 0) { 3041 return c.substring(cname.length, c.length); 3042 } 3043 } 3044 return ""; 3045 } 3046 3047 // function deleteCookie(name) { 3048 // document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 3049 // } 3050 3051 3052 3053 $(function(){ 3054 const urlParams = new URLSearchParams(window.location.search); 3055 3056 3057 // App Verifications 3058 checkAppModeVisibility(); 3059 3060 3061 redirectToSearchIfAuthenticated(); 3062 3063 if (localStorage.getItem("app_mode") == "true") { 3064 if(!isAuth()){ 3065 // openAuthModal(); 3066 } 3067 $(".main-link").attr("href", appendAppContextToUrl("/searchresults")).attr("onclick","").addClass("external"); 3068 } 3069 // End of App Verifications 3070 3071 preserveAppContextAcrossNavigation(); 3072 3073 if (urlParams.get('app') === "true") { 3074 localStorage.setItem("device", urlParams.get('device')); 3075 const appToken = urlParams.get('fcm_token') || urlParams.get('token') || urlParams.get('app_token'); 3076 if (appToken) { 3077 localStorage.setItem("app_token", appToken); 3078 localStorage.setItem("sqv_fcm_token", appToken); 3079 localStorage.setItem("app_token_key", urlParams.get('fcm_token') ? 'fcm_token' : (urlParams.get('token') ? 'token' : 'fcm_token')); 3080 } 3081 } 3082 3083 3084 }) 3085 // Currency Format 3086 let locale = 'pt_PT'; 3087 let currency = new Intl.NumberFormat(locale.replace("_", "-"), { 3088 style: 'currency', 3089 currency: 'eur', 3090 }); 3091 // Is Authenticated 3092 function isAuth(){ 3093 return false; 3094 } 3095 let app; // Declare app here 3096 var isDesktop = Framework7.prototype.device.desktop; 3097 3098 var options = { 3099 transition: isDesktop ? 'f7-cover' : 'f7-parallax', // Custom transition name 3100 animate: !isDesktop // No animation for desktop, animation for mobile 3101 }; 3102 // Initialize Framework7 after DOM is ready 3103 $(document).ready(function() { 3104 app = new Framework7({ 3105 root: '#app', 3106 theme: "ios", 3107 //theme: getOperatingSystem(), 3108 dark: true, 3109 on: { 3110 pageInit: function(page) { 3111 initScript() 3112 initVariableScript(); 3113 if(isDesktop){ 3114 $('.back').attr('data-animate', 'false'); 3115 } 3116 3117 if(page.route.path == "///" || page.route.path == "/"){ 3118 homeScript() 3119 } 3120 if(page.route.path == "/searchresults/"){ 3121 initSearchScript() 3122 } 3123 if(page.route.path == "/myaccount/personal-details/"){ 3124 initAccountScript() 3125 } 3126 if(page.route.path == "/myaccount/my-reservations/"){ 3127 initReservationsScript() 3128 } 3129 if (page.el.querySelector('.ptr-content')) { 3130 page.$el.find('.ptr-content').on('ptr:refresh', function (e) { 3131 setTimeout(function () { 3132 window.location.reload(); 3133 }, 1000); 3134 }); 3135 } 3136 } 3137 }, 3138 routes: [ 3139 { 3140 path: '/', 3141 url:'/', 3142 options: { 3143 transition: 'f7-cover', 3144 animate: false 3145 }, 3146 on: { 3147 pageBeforeIn: function(event, page) { 3148 navigateUrl(page.route.path) 3149 }, 3150 pageAfterIn: function(event, page) { 3151 if(!isDesktop){app.preloader.hide()} 3152 } 3153 } 3154 }, 3155 { 3156 path: '/:page', 3157 async(routeTo, routeFrom, resolve, reject) { 3158 if(!isDesktop){app.preloader.show()} 3159 var page = routeTo.params.page; 3160 app.request.get('/' + page, function(data) { 3161 if(!isDesktop){app.preloader.hide()} 3162 resolve({ content: data }); 3163 }, function(xhr, status) { 3164 if (status == 401) { 3165 window.location.href='/?auth=true'; 3166 } else if (status == 404 || status == 500) { 3167 window.location.href='/?auth=true'; 3168 } else { 3169 console.error("Request failed with status:", status); 3170 } 3171 }); 3172 }, 3173 options: options, 3174 on: { 3175 pageBeforeIn: function(event, page) { 3176 navigateUrl(page.route.path) 3177 }, 3178 pageAfterIn: function(event, page) { 3179 3180 } 3181 } 3182 }, 3183 { 3184 path: '/:page/:page2', 3185 async(routeTo, routeFrom, resolve, reject) { 3186 if(!isDesktop){app.preloader.show()} 3187 var page = routeTo.params.page; 3188 var page2 = routeTo.params.page2; 3189 app.request.get('/' + page + '/' + page2, function(data) { 3190 if(!isDesktop){app.preloader.hide()} 3191 resolve({ content: data }); 3192 }, function(xhr, status) { 3193 if (status == 401) { 3194 window.location.href='/?auth=true'; 3195 } else if (status == 404 || status == 500) { 3196 window.location.href='/?auth=true'; 3197 } else { 3198 console.error("Request failed with status:", status); 3199 } 3200 }); 3201 }, 3202 options: options, 3203 on: { 3204 pageBeforeIn: function(event, page) { 3205 navigateUrl(page.route.path) 3206 }, 3207 pageAfterIn: function(event, page) { 3208 3209 } 3210 } 3211 }, 3212 { 3213 path: '/:page/:page2/:page3', 3214 async(routeTo, routeFrom, resolve, reject) { 3215 if(!isDesktop){app.preloader.show()} 3216 var page = routeTo.params.page; 3217 var page2 = routeTo.params.page2; 3218 var page3 = routeTo.params.page3; 3219 app.request.get('/' + page + '/' + page2 + '/' + page3, function(data) { 3220 if(!isDesktop){app.preloader.hide()} 3221 resolve({ content: data }); 3222 }, function(xhr, status) { 3223 if (status == 401) { 3224 window.location.href='/?auth=true'; 3225 } else if (status == 404 || status == 500) { 3226 window.location.href='/?auth=true'; 3227 } else { 3228 console.error("Request failed with status:", status); 3229 } 3230 }); 3231 }, 3232 options: options, 3233 on: { 3234 pageBeforeIn: function(event, page) { 3235 navigateUrl(page.route.path) 3236 }, 3237 pageAfterIn: function(event, page) { 3238 } 3239 } 3240 }, 3241 ], 3242 methods: { 3243 navigateToPage: function(page) { 3244 this.$f7router.navigate('/' + page + ''); 3245 } 3246 } 3247 }); 3248 window.addEventListener('popstate', function(event) { 3249 var url = window.location.pathname; 3250 app.view.main.router.navigate(url) 3251 }); 3252 app.on('routeChanged', function(route) { 3253 if (route.path == "/searchresults") { 3254 initSearchScript() 3255 } 3256 if (route.path == "/myaccount/personal-details") { 3257 initAccountScript() 3258 } 3259 if (route.path == "/myaccount/my-reservations") { 3260 initReservationsScript() 3261 } 3262 }); 3263 3264 3265 3266 // Event when panel opens 3267 app.on('panelOpen', function(panel) { 3268 if (panel.side === 'right') { 3269 $('.menu-sidebar i').removeClass('bi-list').addClass('bi-x-lg'); 3270 setTimeout(() => { 3271 $('.menu-sidebar').removeClass('panel-open').addClass('panel-close'); 3272 }, 100); 3273 } 3274 }); 3275 // Event when panel closes 3276 app.on('panelClose', function(panel) { 3277 if (panel.side === 'right') { 3278 $('.menu-sidebar i').removeClass('bi-x-lg').addClass('bi-list'); 3279 setTimeout(() => { 3280 $('.menu-sidebar').removeClass('panel-close').addClass('panel-open'); 3281 }, 100); 3282 } 3283 }); 3284 3285 // P2: Limpar opções fantasma ao fechar modal de produto 3286 app.on('popupClosed', function(popup) { 3287 const $el = $(popup.el); 3288 if (!$el.hasClass('modal-product') && !$el.is('[class*="modal-product-"]')) return; 3289 3290 // Extrair productId do class (ex: modal-product-123-45) 3291 const classes = $el.attr('class') || ''; 3292 const match = classes.match(/modal-product-([\w-]+)/); 3293 if (!match) return; 3294 const productId = match[1]; 3295 3296 // Limpar selectedOptionsMap 3297 delete selectedOptionsMap[productId]; 3298 3299 // Reset checkboxes 3300 $el.find('.option-checkbox').prop('checked', false).prop('disabled', false); 3301 3302 // Reset steppers de opções para 0 3303 $el.find('.option-stepper').val(0); 3304 3305 // Re-enable all stepper-plus buttons disabled by max-limit logic 3306 $el.find('.stepper-button-plus').prop('disabled', false); 3307 3308 // Reset quantidade para 1 (modal input only) 3309 $el.find('#qty-' + productId).val(1); 3310 $('.qty-' + productId).text('1'); 3311 3312 // Reset selected-options textarea 3313 $('#selected-options-' + productId).val('{}'); 3314 3315 // Recalcular totais com estado limpo 3316 if (typeof showTotals === 'function') { 3317 showTotals(productId); 3318 } 3319 }); 3320 3321 }); 3322 function navigateUrl(path) { 3323 // Captura os parâmetros de consulta atuais da URL 3324 const queryParams = window.location.search; 3325 3326 // Constrói a nova URL com os parâmetros existentes 3327 const newPath = `${path}${queryParams}`; 3328 3329 // Atualiza o histórico mantendo os parâmetros 3330 window.history.pushState(null, "", newPath); 3331} 3332 3333 function getOperatingSystem() { 3334 var userAgent = navigator.userAgent || navigator.vendor || window.opera; 3335 // For iPhones, iPads, and iPods 3336 if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) { 3337 return "ios"; 3338 } 3339 // For Android 3340 else if (/android/i.test(userAgent)) { 3341 return "md"; 3342 } 3343 // For macOS 3344 else if (/Macintosh|MacIntel|MacPPC|Mac68K/.test(userAgent)) { 3345 return "ios"; 3346 } 3347 // For Windows 3348 else if (/Win32|Win64/.test(userAgent)) { 3349 return "md"; 3350 } 3351 return "md"; 3352 } 3353 async function handleCheckout() { 3354 loading(); 3355 3356 // Obtenha o valor toda vez que precisar usar 3357 var TOTAL = parseFloat(localStorage.getItem('checkout-total')) || 0; 3358 const MIN_AMOUNT = 4; 3359 3360 if (TOTAL < MIN_AMOUNT) { 3361 loaded(); 3362 toast("error", `Você não atingiu o valor mÃnimo de 4,00 â¬.`, 3000); 3363 return; 3364 } 3365 3366 const migrated = await migrateCheckoutData(this); 3367 3368 if (migrated) { 3369 setTimeout(() => { 3370 window.location.href = "/checkout"; 3371 }, 250); 3372 } else { 3373 loaded(); 3374 toast("error", "Não foi possÃvel sincronizar o carrinho. Tente novamente.", 3000); 3375 console.error("Failed to synchronize checkout data before redirect"); 3376 } 3377 } 3378 3379 // Função para obter o total do carrinho 3380 function getCartTotal() { 3381 return $(".cart-total").data("total"); 3382 } 3383 3384 3385 function initVariableScript() { 3386 3387 3388 $('.page-content').on('scroll', function () { 3389 $('.group-list').each(function () { 3390 const top = window.pageYOffset; 3391 const distance = top - $(this).offset().top; 3392 const hash = '#' + $(this).find('.group-title').attr('id'); // Adjusted here 3393 3394 // Check if we're within the section 3395 if (distance > (isDesktop ? -60 : -100)) { 3396 $('.link').removeClass('text-primary'); 3397 $('a.link[href="' + hash + '"]').addClass('text-primary'); 3398 } 3399 }); 3400 }); 3401 const is24HourFormat = true;
3401 // Change this to false for 12-hour format 3402 var startDate = moment().startOf('hour') 3403 var endDate = moment().startOf('hour').add(32, 'hour'); 3404 $('.daterange').daterangepicker({ 3405 parentEl: isDesktop ? '.daterangepicker-content' : "", 3406 timePicker: true, 3407 timePicker24Hour: is24HourFormat, 3408 timePickerIncrement: 15, // Set the step of minutes to 15 3409 startDate: startDate, 3410 endDate: endDate, 3411 locale: { 3412 format: 'DD/MM/Y HH:mm', 3413 applyLabel: 'Aplicar', 3414 cancelLabel: 'Cancelar', 3415 fromLabel: 'De', 3416 toLabel: 'Para', 3417 customRangeLabel: 'Personalizado', 3418 weekLabel: 'S', 3419 daysOfWeek: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'], 3420 monthNames: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'], 3421 firstDay: 0 3422 } 3423 }, function(start, end) { 3424 // This function will be called when the user applies a date range 3425 // Calculate the difference in days 3426 var diff = end.diff(start, 'days'); 3427 $('#start_date').val(start.format('YYYY-MM-DD HH:mm')); 3428 $('#end_date').val(end.format('YYYY-MM-DD HH:mm')); 3429 // Set the cookies 3430 saveData("start_date", start.format('YYYY-MM-DD HH:mm')); 3431 saveData("end_date", end.format('YYYY-MM-DD HH:mm')); 3432 saveData("days", diff); 3433 }); 3434 $(".update-button").on("click", function() { 3435 var itemName = $(this).data("item-name"); 3436 var type = $(this).data("type"); 3437 var inputValue = $("#input-" + itemName); 3438 if (inputValue.is('select')) { 3439 var value = $('#input-'+itemName+' option[value="'+inputValue.val()+'"]').text(); 3440 } else { 3441 var value = inputValue.val(); 3442 } 3443 $.ajax({ 3444 url: "/myaccount/setting/update", // replace with your endpoint url 3445 type: "POST", 3446 headers: { 3447 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') 3448 }, 3449 data: { 3450 key: itemName, 3451 type: type, 3452 value: inputValue.val(), 3453 user: "" 3454 }, 3455 success: function(response) { 3456 if(response.status === true){ 3457 closeExpand(itemName); 3458 $(".data-name-"+itemName).html(value); 3459 toast("success",response.message,3000); 3460 }else{ 3461 toast("error",response.message,3000); 3462 } 3463 }, 3464 error: function(xhr, status, error) { 3465 toast("error","[1020] Ocorreu algum erro",3000); 3466 } 3467 }).fail(function(jqXHR, textStatus, errorThrown) { 3468 if (jqXHR.status == 419) { 3469 // CSRF token expired 3470 window.location.reload(); 3471 } 3472 }); 3473 }); 3474 $('.checkbox-setting').change(function() { 3475 var isChecked = $(this).is(':checked'); 3476 var dataToggle = $(this).data('toggle'); 3477 var type = $(this).data('type'); 3478 // Send AJAX request 3479 $.ajax({ 3480 url: "/myaccount/setting/update", // replace with your endpoint url 3481 type: "POST", 3482 headers: { 3483 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') 3484 }, 3485 data: { 3486 key: dataToggle, 3487 type: type, 3488 value: isChecked, 3489 user: "" 3490 }, 3491 success: function(response) { 3492 if(response.status === true){ 3493 toast("success",response.message,3000); 3494 }else{ 3495 toast("error",response.message,3000); 3496 } 3497 }, 3498 error: function(xhr, status, error) { 3499 toast("error",'[1020] Ocorreu algum erro',3000); 3500 } 3501 }).fail(function(jqXHR, textStatus, errorThrown) { 3502 if (jqXHR.status == 419) { 3503 // CSRF token expired 3504 window.location.reload(); 3505 } 3506 }); 3507 }); 3508 // Handle the feedback button clicks 3509 $("[data-feedback]").on('click', function (e) { 3510 e.preventDefault(); 3511 let feedbackType = $(this).data('feedback'); 3512 let feedbackArticleId = $(this).data('feedback-article'); 3513 $.ajax({ 3514 url: "/help/feedback", // specify the URL where you'll handle the feedback 3515 method: "POST", 3516 data: { 3517 feedback: feedbackType, 3518 article_id: feedbackArticleId, 3519 _token: $('meta[name="csrf-token"]').attr('content') // Laravel CSRF Token for security 3520 }, 3521 success: function (response) { 3522 if (response.success) { 3523 // Save the article ID in local storage 3524 localStorage.setItem("feedback_" + feedbackArticleId, feedbackType); 3525 // Show the thanks-for-feedback div 3526 3527 $(".rate").hide(); 3528 $(".feedback-loading").show(); 3529 setTimeout(() => { 3530 $(".feedback-loading").hide(); 3531 $(".thanks-for-feedback").show(); 3532 toast("success","Obrigado pelo seu feedback. à sempre muito importante para nós!",4000) 3533 }, 1000); 3534 3535 } else { 3536 toast("error","[1020] Ocorreu algum erro",4000) 3537 } 3538 } 3539 }).fail(function(jqXHR, textStatus, errorThrown) { 3540 if (jqXHR.status == 419) { 3541 // CSRF token expired 3542 window.location.reload(); 3543 } 3544 }); 3545 }); 3546 // Like Function 3547 $('.like-btn').on('click', function() { 3548 var itemId = $(this).data('id'); 3549 var itemType = $(this).data('type'); 3550 var itemUrl = $(this).data('url'); 3551 var itemOrigin = $(this).data('origin'); 3552 $.ajax({ 3553 url: '/common/set/like', 3554 type: 'POST', 3555 data: { 3556 '_token': $('meta[name="csrf-token"]').attr('content'), 3557 id: itemId, 3558 type: itemType, 3559 url: itemUrl 3560 }, 3561 success: function(response) { 3562 // Toggle the button appearance based on the response 3563 var icon = $('.like-btn-id-'+itemId+' i'); 3564 if (response.status == 'liked') { 3565 icon.removeClass('bi-heart'); 3566 icon.addClass('bi-heart-fill text-red-500'); 3567 toast("success","site.cart.item-added-to-favorites-list",3
3567000) 3568 } else { 3569 if(itemOrigin == "wishlist"){ 3570 // Decreate value 3571 var count = $("#wishlist-count").text($("#wishlist-count").text() - 1); 3572 if($("#wishlist-count").text() == 0){ 3573 $("#wishlist-empty").removeClass("hidden"); 3574 } 3575 3576 $(".item-"+itemId).remove(); 3577 } 3578 icon.removeClass('bi-heart-fill text-red-500'); 3579 icon.addClass('bi-heart'); 3580 toast("error","site.cart.item-removed-from-favorites-list",3000) 3581 } 3582 } 3583 }).fail(function(jqXHR, textStatus, errorThrown) { 3584 if (jqXHR.status == 419) { 3585 // CSRF token expired 3586 window.location.reload(); 3587 } 3588 }); 3589 }); 3590 $("#submitReviewButton").click(function(e) { 3591 var reviewId = $(this).data("id"); 3592 var reviewPage = $(this).data("page"); 3593 e.preventDefault(); 3594 if (!validateReview()) { 3595 return; 3596 } 3597 app.preloader.show(); 3598 $.ajax({ 3599 url: '/review/submit', 3600 method: 'POST', 3601 headers: { 3602 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') 3603 }, 3604 data: { 3605 review: $("#review_text").val(), 3606 id: reviewId, 3607 origin: reviewPage, 3608 rate: $("input[name='rate']:checked").val() 3609 }, 3610 3611 success: function(response) { 3612 toast("success", response?.message, 3000); 3613 closeModal("review"); 3614 feedbackSuccess("Enviado com sucesso!"); 3615 setTimeout(() => { 3616 let currentUrl = new URL(window.location.href); 3617 currentUrl.searchParams.delete('review'); 3618 window.location.href = currentUrl.toString(); 3619 }, 2000); 3620 }, 3621 error: function(jqXHR, textStatus, errorThrown) { 3622 console.error(textStatus, errorThrown); 3623 } 3624 }).fail(function(jqXHR, textStatus, errorThrown) { 3625 if (jqXHR.status == 419) { 3626 // CSRF token expired 3627 window.location.reload(); 3628 } 3629 }); 3630 }); 3631 $("#submitCommentButton").click(function(e) { 3632 var commentId = $(this).data("id"); 3633 var commentPage = $(this).data("page"); 3634 3635 e.preventDefault(); 3636 if (!validateComment()) { 3637 return; 3638 } 3639 $.ajax({ 3640 url: '/review/submit', 3641 method: 'POST', 3642 headers: { 3643 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') 3644 }, 3645 data: { 3646 review: $("#review_text").val(), 3647 id: commentId, 3648 origin: commentPage, 3649 }, 3650 success: function(response) { 3651 if(response?.success == true){ 3652 toast("success","Enviado com sucesso!",3000); 3653 closeModal("review"); 3654 feedbackSuccess("Enviado com sucesso!"); 3655 setTimeout(() => { 3656 window.location.reload(); 3657 }, 2000); 3658 } 3659 3660 }, 3661 error: function(jqXHR, textStatus, errorThrown) { 3662 console.error(textStatus, errorThrown); 3663 } 3664 }).fail(function(jqXHR, textStatus, errorThrown) { 3665 if (jqXHR.status == 419) { 3666 // CSRF token expired 3667 window.location.reload(); 3668 } 3669 }); 3670 }); 3671 3672 3673 3674 3675 3676 3677 // Função para diminuir o valor 3678 $('.option-stepper-button-minus').click(function() { 3679 let input = $(this).siblings('.stepper-input-wrap').find('input'); 3680 let currentValue = parseInt(input.val(), 10); 3681 let minValue = parseInt(input.attr('min'), 10) || 0; 3682 let plusButton = $(this).siblings('.option-stepper-button-plus'); // Botão de aumentar 3683 3684 // Diminui o valor se for maior que o mÃnimo 3685 if (currentValue > minValue) { 3686 input.val(currentValue - 1).change(); // Dispara o evento change 3687 plusButton.prop('disabled', false); // Reabilitar o botão "plus" se estiver desabilitado 3688 } 3689 }); 3690 3691 // Função para aumentar o valor 3692 $('.option-stepper-button-plus').click(function() { 3693 let input = $(this).siblings('.stepper-input-wrap').find('input'); 3694 let currentValue = parseInt(input.val(), 10); 3695 let stock = $(this).data('stock'); // Obter o limite de estoque 3696 let minusButton = $(this).siblings('.option-stepper-button-minus'); // Botão de diminuir 3697 3698 // Verifica se o valor atual é menor que o estoque 3699 if (currentValue < stock) { 3700 input.val(currentValue + 1).change(); // Dispara o evento change 3701 minusButton.prop('disabled', false); // Reabilitar o botão "minus" se estiver desabilitado 3702 } 3703 3704 // Desabilita o botão "plus" se o valor atingir o estoque máximo 3705 if (currentValue + 1 >= stock) { 3706 $(this).prop('disabled', true); 3707 toast('error','You have reached the maximum available stock!',3000); 3708 } 3709 }); 3710 3711 function getGroupSelectedCount(selectedOptions, groupUuid) { 3712 const selectedGroup = selectedOptions?.[groupUuid]; 3713 if (!selectedGroup || !selectedGroup.options) return 0; 3714 3715 return Object.values(selectedGroup.options).reduce((sum, opt) => { 3716 return sum + (parseInt(opt.quantity, 10) || 0); 3717 }, 0); 3718 } 3719 3720 function scrollToNextRequiredGroup($popup, productId, currentGroupUuid = null) { 3721 const groups = $popup.find('.option-group-' + productId); 3722 if (!groups.length) return false;
3723 3724 const $scrollContainer = $popup.find('.page-content').first(); 3725 3726 const selectedOptions = selectedOptionsMap[productId] || {}; 3727 let startSearching = currentGroupUuid === null; 3728 3729 for (let i = 0; i < groups.length; i++) { 3730 const $group = $(groups[i]); 3731 const groupUuid = $group.data('group-uuid'); 3732 3733 if (!startSearching) { 3734 if (groupUuid === currentGroupUuid) { 3735 startSearching = true; 3736 } 3737 continue; 3738 } 3739 3740 const groupMin = parseInt($group.data('group-min'), 10) || 0; 3741 if (!groupMin) continue; 3742 3743 const selectedCount = getGroupSelectedCount(selectedOptions, groupUuid); 3744 if (selectedCount < groupMin) { 3745 if ($scrollContainer.length) { 3746 const targetTop = $group.position().top + $scrollContainer.scrollTop() - 100; 3747 $scrollContainer.stop(true).animate({ scrollTop: targetTop }, 420); 3748 } else if (typeof smoothScrollToElement === 'function') { 3749 smoothScrollToElement($group[0], 450, 120); 3750 } else if ($group[0] && typeof $group[0].scrollIntoView === 'function') { 3751 $group[0].scrollIntoView({ behavior: 'smooth', block: 'start' }); 3752 } 3753 3754 const $title = $group.find('.group-title').first(); 3755 $title.addClass('text-blue-600'); 3756 setTimeout(() => $title.removeClass('text-blue-600'), 1400); 3757 3758 $group.find('.group-input').first().focus(); 3759 return true; 3760 } 3761 } 3762 3763 return false; 3764 } 3765 3766 3767 3768 3769 // Delegated para suportar modais renderizados dinamicamente (ex.: navegação AJAX entre categorias) 3770 $(document).off('change.sqvOption').on('change.sqvOption', '.option-checkbox, .option-stepper', function () { 3771 3772 const $group = $(this).closest('ul'); 3773 const groupName = $group.data('group-name'); 3774 const groupUuid = $group.data('group-uuid'); 3775 const groupExtra = $group.data('group-extra'); 3776 const optionUuid = $(this).data('option-uuid'); 3777 const optionProductId = $(this).data('option-product-id'); 3778 const optionName = $(this).data('option-name'); 3779 const optionPrice = $(this).data('price'); 3780 const price = parseFloat((optionPrice !== "undefined" ? optionPrice : 0)); 3781 3782 let quantity; 3783 if ($(this).hasClass('option-checkbox')) { 3784 quantity = $(this).is(":checked") ? 1 : 0; 3785 } else if ($(this).hasClass('option-stepper')) { 3786 quantity = parseInt($(this).val()); 3787 } 3788 const $popup = $(this).closest('.popup'); 3789 const productId = $popup.attr('id').replace('popup-', ''); 3790 let selectedOptions = selectedOptionsMap[productId] || {}; 3791 if (!selectedOptions[groupUuid]) { 3792 selectedOptions[groupUuid] = { 3793 uuid: groupUuid, 3794 name: groupName, 3795 extra: groupExtra, 3796 options: {}, 3797 subtotal: 0 3798 }; 3799 } 3800 selectedOptions[groupUuid].options[optionUuid] = { 3801 uuid: optionUuid, 3802 product_id: optionProductId ? String(optionProductId) : null, 3803 name: optionName, 3804 price: price, 3805 quantity: quantity, 3806 subtotal: price * quantity 3807 }; 3808 3809 // Iterar sobre as opções e remover aquelas com quantidade zero 3810Object.keys(selectedOptions[groupUuid].options).forEach(key => { 3811 if (selectedOptions[groupUuid].options[key].quantity === 0) { 3812 // Ocultar o span antes de deletar a opção 3813 const $extraInfoSpan = $(`.extra-group-${groupUuid}.extra-option-${key}`); 3814 $extraInfoSpan.find('.extra-subtotal').text(''); // Limpar o texto 3815 $extraInfoSpan.addClass('hidden'); // Ocultar o span 3816 3817 // Log para depuração 3818 console.log("Tentando remover do textarea:", key); 3819 3820 // Remove a opção do JSON do textarea 3821 const $textarea = $(`textarea[data-product-id="${productId}"]`); 3822 let textareaData = $textarea.val(); // Pega o valor atual do textarea 3823 3824 // Verifica se o JSON do textarea não está vazio e faz o parse 3825 if (textareaData) { 3826 let parsedData; 3827 try { 3828 parsedData = JSON.parse(textareaData); // Converte para objeto JSON 3829 } catch (error) { 3830 console.error("Erro ao fazer o parse do JSON no textarea:", error); 3831 return; // Sai da função se houver erro no parse 3832 } 3833 3834 // Verifica se o grupo e a opção realmente existem 3835 if (parsedData[groupUuid] && parsedData[groupUuid].options[key]) { 3836 delete parsedData[groupUuid].options[key]; // Remove a opção do JSON 3837 console.log("Opção removida do textarea:", key); 3838 3839 // Remove o grupo do JSON se não houver mais opções 3840 if (Object.keys(parsedData[groupUuid].options).length === 0) { 3841 delete parsedData[groupUuid]; // Remove o grupo se estiver vazio 3842 console.log("Grupo removido do textarea:", groupUuid); 3843 } 3844 3845 // Atualiza o textarea com o novo JSON 3846 $textarea.val(JSON.stringify(parsedData)); 3847 console.log("Textarea atualizado com sucesso."); 3848 } else { 3849 console.log("Opção ou grupo não encontrados no JSON do textarea."); 3850 } 3851 } else { 3852 console.log("JSON vazio no textarea."); 3853 } 3854 3855 // Remove a opção de selectedOptions 3856 delete selectedOptions[groupUuid].options[key]; 3857 console.log("Opção removida de selectedOptions:", key); 3858 } 3859}); 3860 3861 3862// Extra Show Value
3863Object.entries(selectedOptions).forEach(([groupUuid, group]) => { 3864 Object.entries(group.options).forEach(([optionUuid, option]) => { 3865 console.log(option) 3866 const $extraInfoSpan = $(`.extra-group-${groupUuid}.extra-option-${optionUuid}`); 3867 3868 if (option.subtotal !== 0) { 3869 // Exibe o valor do subtotal e mostra o span 3870 $extraInfoSpan.find('.extra-subtotal').text(currency.format(option.subtotal)); 3871 $extraInfoSpan.removeClass('hidden'); 3872 } else { 3873 // Limpa o texto e oculta o span quando a quantidade é 0 3874 $extraInfoSpan.find('.extra-subtotal').text(''); // Limpar o conteúdo do span 3875 $extraInfoSpan.addClass('hidden'); 3876 } 3877 }); 3878}); 3879 3880 3881 // Re-calculate Subtotal for the Group 3882 selectedOptions[groupUuid].subtotal = Object.values(selectedOptions[groupUuid].options).reduce((sum, option) => sum + option.subtotal, 0); 3883 // Max Value Validation 3884 const groupMax = parseInt($group.data('group-max')); 3885 const groupQuantity = Object.values(selectedOptions[groupUuid].options).reduce((sum, option) => sum + option.quantity, 0); 3886 if (groupQuantity >= groupMax) { 3887 toast("success", `Limite do grupo atingido. Remova o atual se desejar escolher um novo`, 3000); 3888 if ($(this).hasClass('option-checkbox')) { 3889 quantity = $(this).is(":checked") ? 1 : 0; 3890 if(quantity === 1) { 3891 $popup.find('.option-checkbox[data-group="' + groupUuid + '"]').not(this).not(':checked').prop('disabled', true); 3892 } 3893 } 3894 if ($(this).hasClass('option-stepper')) { 3895 quantity = parseInt($(this).val()); 3896 $group.find('.option-checkbox[data-group="'+groupUuid+'"], .stepper-button-plus[data-group="'+groupUuid+'"]').prop('disabled', true); 3897 } 3898 //updateDataAndUI(this, groupUuid, optionUuid, optionName, price, productId); 3899 // ð ï¸ Aqui está a correção que mantém tudo atualizado 3900 updateDataAndUI(this, groupUuid, optionUuid, optionName, price, productId); 3901 selectedOptionsMap[productId] = selectedOptions; 3902 showSelectedOptions(productId); 3903 showTotals(productId); 3904 3905 const groupMin = parseInt($group.data('group-min'), 10) || 0; 3906 const currentSelectedCount = getGroupSelectedCount(selectedOptionsMap[productId], groupUuid); 3907 if (groupMin > 0 && currentSelectedCount >= groupMin) { 3908 setTimeout(() => scrollToNextRequiredGroup($popup, productId, groupUuid), 50); 3909 } 3910 3911 return; 3912 }else{ 3913 $group.find('.stepper-button-plus[data-group="'+groupUuid+'"]').prop('disabled', false); 3914 if ($(this).hasClass('option-checkbox')) { 3915 quantity = $(this).is(":checked") ? 1 : 0; 3916 if(quantity === 0) { 3917 $popup.find('.option-checkbox[data-group="' + groupUuid + '"]').prop('disabled', false); 3918 } 3919 } 3920 } 3921 selectedOptionsMap[productId] = selectedOptions; 3922 // Update Visible Data 3923 updateDataAndUI(this, groupUuid, optionUuid, optionName, price, productId); 3924 showSelectedOptions(productId); 3925 showTotals(productId); 3926 3927 const groupMin = parseInt($group.data('group-min'), 10) || 0; 3928 const currentSelectedCount = getGroupSelectedCount(selectedOptionsMap[productId], groupUuid); 3929 if (groupMin > 0 && currentSelectedCount >= groupMin) { 3930 setTimeout(() => scrollToNextRequiredGroup($popup, productId, groupUuid), 50); 3931 } 3932 }); 3933 3934 3935 // Função para habilitar/desabilitar botões com base na quantidade 3936 function checkStockLimit(productId, qty, productStock) { 3937 if (qty >= productStock) { 3938 $('#product-plus-' + productId).prop('disabled', true); // Desabilita o botão de incremento 3939 toast('error','You have reached the maximum available stock!',3000); // Exibe alerta 3940 } else { 3941 $('#product-plus-' + productId).prop('disabled', false); // Habilita o botão de incremento 3942 } 3943 } 3944 3945 // P11: Event delegation para suportar modais renderizados dinamicamente 3946 $(document).on('click', '.product-qty-plus', function() { 3947 let productId = $(this).data('product'); 3948 let $stepper = $(this).closest('.stepper'); 3949 let input = $stepper.find('input[id^="qty-"]').first(); 3950 3951 if (!input.length) { 3952 input = $('#qty-' + productId).first(); 3953 } 3954 3955 let qty = parseInt(input.val(), 10); 3956 if (isNaN(qty) || qty < 1) qty = 1; 3957 3958 qty += 1; 3959 input.val(qty).attr('value', qty); 3960 3961 // Sincroniza qualquer outro campo do mesmo produto (ex: instâncias duplicadas em blocos diferentes) 3962 $('#qty-' + productId).val(qty).attr('value', qty); 3963 3964 showTotals(productId); 3965 updateCart(); 3966}); 3967 3968 3969 3970$(document).on('click', '.product-qty-minus', function() { 3971 let productId = $(this).data('product'); 3972 let $stepper = $(this).closest('.stepper'); 3973 let input = $stepper.find('input[id^="qty-"]').first(); 3974 3975 if (!input.length) { 3976 input = $('#qty-' + productId).first(); 3977 } 3978 3979 let qty = parseInt(input.val(), 10); 3980 if (isNaN(qty) || qty <= 1) return; 3981 3982 qty -= 1; 3983 input.val(qty).attr('value', qty); 3984 3985 // Sincroniza qualquer outro campo do mesmo produto (ex: instâncias duplicadas em blocos diferentes) 3986 $('#qty-' + productId).val(qty).attr('value', qty); 3987 3988 showTotals(productId); 3989 checkStockLimit(productId, qty, $(this).data('stock')); 3990}); 3991 3992 3993 3994 3995 3996 $(document).on('click', '.add-to-cart', function () { 3997 // P4: Anti-duplo-clique 3998 const $btn = $(this); 3999 if ($btn.data('adding')) return; 4000 $btn.data('adding', true).css('opacity', '0.6').css('pointer-events', 'n
4000one'); 4001 setTimeout(() => { $btn.data('adding', false).css('opacity', '').css('pointer-events', ''); }, 1500); 4002 4003 const productId = $(this).data("product-uuid"); 4004 const productName = $(this).data("product-name"); 4005 const productImg = $(this).data("product-img"); 4006 const producTotal = $(this).data("product-total"); 4007 const storeId = $(this).data("store-uuid"); 4008 const storeName = $(this).data("store-name"); 4009 const storeURL = $(this).data("store-url"); 4010 const storeImg = $(this).data("store-img"); 4011 const storeSlug = $(this).data("store-slug"); 4012 const type = $(this).data("type"); 4013 const $popup = $(this).closest('.popup'); 4014 4015 let selectedOptions = selectedOptionsMap[productId] || {}; 4016 4017 let isValid = true; 4018 4019 // ð¡ Validação de grupos obrigatórios 4020 if (type == 2) { 4021 $popup.find('.option-group-' + productId).each(function () { 4022 const $group = $(this); 4023 const groupName = $group.data('group-name'); 4024 const minOptions = parseInt($group.data('group-min'), 10); 4025 const groupUuid = $group.data('group-uuid'); 4026 4027 const selectedGroup = selectedOptions[groupUuid]; 4028 const selectedCount = selectedGroup 4029 ? Object.values(selectedGroup.options || {}).reduce((sum, opt) => sum + (opt.quantity || 0), 0) 4030 : 0; 4031 4032 if (minOptions && selectedCount < minOptions) { 4033 isValid = false; 4034 $group.find('.group-title').addClass('text-red-500'); 4035 toast("error", `MÃnimo ${minOptions} opção(ões) obrigatória(s) para ${groupName} é ${minOptions}`, 3000); 4036 // P6: Scroll automático até ao grupo inválido 4037 if (typeof smoothScrollToElement === 'function') { 4038 smoothScrollToElement($group[0], 400, 120); 4039 } 4040 $group.find('.group-input').first().focus(); 4041 console.log(`Erro: grupo "${groupName}" com UUID ${groupUuid} tem apenas ${selectedCount} selecionadas`); 4042 return false; // interrompe o .each 4043 } else { 4044 $group.find('.group-title').removeClass('text-red-500'); 4045 } 4046 }); 4047 } 4048 4049 if (!isValid) return; 4050 4051 // â Remoção segura de opções com quantidade 0 após a validação 4052 Object.keys(selectedOptions).forEach(groupUuid => { 4053 const groupOptions = selectedOptions[groupUuid].options; 4054 Object.keys(groupOptions).forEach(optionUuid => { 4055 if (groupOptions[optionUuid].quantity === 0) { 4056 delete selectedOptions[groupUuid].options[optionUuid]; 4057 } 4058 }); 4059 4060 if (Object.keys(selectedOptions[groupUuid].options).length === 0) { 4061 delete selectedOptions[groupUuid]; 4062 } 4063 }); 4064 4065 // ð¦ Preparar item para o carrinho 4066 let cart = JSON.parse(localStorage.getItem('cart')) || []; 4067 let total = JSON.parse($('#total-' + productId).val() || "{}"); 4068 4069 // Se estiver vazio ou inválido, recalcula antes de continuar 4070 if (!total?.total || !total?.unit_price) { 4071 showTotals(productId); 4072 total = JSON.parse($('#total-' + productId).val() || "{}"); 4073 } 4074 const note = $('#note-' + productId).val(); 4075 const qty = parseInt($('#qty-' + productId).val(), 10) || 1; 4076 4077 const first_item = cart[0]; 4078 if (first_item && first_item.store_id !== storeId) { 4079 cart = []; // limpa o carrinho se for de outra loja 4080 localStorage.setItem('upsell', null); // limpa upsell 4081 } 4082 4083 // Multiplicar quantidades das opções pelo qty do produto 4084 const cartOptions = JSON.parse(JSON.stringify(selectedOptions)); 4085 if (qty > 1) { 4086 Object.values(cartOptions).forEach(group => { 4087 if (group.options) { 4088 Object.values(group.options).forEach(option => { 4089 option.quantity = option.quantity * qty; 4090 option.subtotal = option.price * option.quantity; 4091 }); 4092 group.subtotal = Object.values(group.options).reduce((sum, opt) => sum + opt.subtotal, 0); 4093 } 4094 }); 4095 } 4096 4097 const newItem = { 4098 cart_id: generateUniqueId(), 4099 store_id: storeId, 4100 store_name: storeName, 4101 store_url: storeURL, 4102 store_img: storeImg, 4103 id: productId, 4104 name: productName, 4105 img: productImg,
4106 note: note, 4107 option: cartOptions, 4108 qty: qty, 4109 price: total.unit_price, 4110 discount: total.discount, 4111 subtotal_without_discount: qty * total.unit_price, 4112 subtotal: qty * total.unit_price 4113 }; 4114 4115 // ð¯ Se for item normal, remove ofertas (caso existam) 4116if (selectedOptions.name !== "offer") { 4117 const hadOffer = cart.some(item => item.option.name === "offer"); 4118 if (hadOffer) { 4119 cart = cart.filter(item => item.option.name !== "offer"); 4120 toast("info", "Oferta removida ao adicionar novo item ao carrinho", 3000); 4121 } 4122} 4123 4124 4125 cart.push(newItem); 4126 localStorage.setItem('cart', JSON.stringify(cart)); 4127 4128 // ð¯â FACEBOOK PIXEL "AddToCart" 4129 if (window.fbPixelIsActive === true && typeof fbq !== 'undefined') { 4130 fbq('track', 'AddToCart', { 4131 content_name: productName, 4132 content_ids: [productId], 4133 content_type: 'product', 4134 content_qty: qty, 4135 value: newItem.subtotal, // total correto já considerando quantidade e opções 4136 currency: 'EUR', 4137 eventID: newItem.cart_id // ð Garantir deduplicação com CAPI 4138 4139 }); 4140 4141 // Server-side CAPI AddToCart 4142 const userId = window.user.id || null; 4143 4144 fetch('/capi/add-to-cart', { 4145 method: 'POST', 4146 headers: { 4147 'Content-Type': 'application/json', 4148 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content 4149 }, 4150 body: JSON.stringify({ 4151 content_name: productName, 4152 content_id: productId, 4153 content_qty: qty, 4154 value: newItem.subtotal, 4155 event_id: newItem.cart_id, 4156 event_source_url: window.location.href, 4157 fbp: localStorage.getItem('fbp'), 4158 fbc: localStorage.getItem('fbc'), 4159 4160 // ð§ Dados do usuário 4161 external_id: userId, 4162 email: window.user.email || null, 4163 phone: window.user.phone || null, 4164 first_name: window.user.first_name || null, 4165 last_name: window.user.last_name || null, 4166 city: window.user.city || null 4167 }) 4168 }).then(res => { 4169 if (!res.ok) { 4170 console.warn("Erro ao enviar AddToCart CAPI:", res.status); 4171 } 4172 }).catch(err => { 4173 console.error("Erro de rede ao enviar AddToCart CAPI:", err); 4174 }); 4175 4176 } 4177 4178 4179 // ð§ â GOOGLE ANALYTICS 4 "add_to_cart" 4180 if (typeof gtag === "function") { 4181 gtag("event", "add_to_cart", { 4182 currency: "EUR", 4183 value: newItem.subtotal, 4184 items: [{ 4185 item_id: productId, 4186 item_name: productName, 4187 quantity: qty, 4188 price: total.unit_price 4189 }] 4190 }); 4191 } 4192 4193 // â GOOGLE ADS "add_to_cart" 4194 if (typeof gtag === "function" && window.googleAdsIsActive === true && window.googleAdsConversionLabel) { 4195 gtag('event', 'conversion', { 4196 send_to: window.googleAdsConversionId + '/' + window.googleAdsConversionLabel, 4197 value: newItem.subtotal, 4198 currency: 'EUR', 4199 items: [ 4200 { 4201 id: productId, 4202 name: productName, 4203 quantity: qty, 4204 price: total.unit_price 4205 } 4206 ] 4207 }); 4208 4209 if (window.debugPixel === true) { 4210 console.log("[Google Ads] add_to_cart", { 4211 send_to: window.googleAdsConversionId + '/' + window.googleAdsConversionLabel, 4212 value: newItem.subtotal, 4213 currency: 'EUR' 4214 }); 4215 } 4216 } 4217 4218 // ð§ Construir array de opções personalizadas (caso existam) 4219 const itemCustomization = []; 4220 Object.values(selectedOptions).forEach(group => { 4221 Object.values(group.options).forEach(opt => { 4222 if (opt.quantity > 0) { 4223 itemCustomization.push({ name: opt.name, qty: opt.quantity }); 4224 } 4225 }); 4226 }); 4227 4228 // â GOOGLE TAG MANAGER: Evento via dataLayer para add_to_cart 4229 if (typeof dataLayer !== 'undefined') { 4230 const item = { 4231 item_id: productId, 4232 item_name: productName, 4233 quantity: qty, 4234 price: total.unit_price, 4235 currency: "EUR", 4236 //item_variant: "Pack 50", // ou outro valor real se aplicável 4237 //item_category: "Quitutes da Tia", // â ajustar dinamicamente 4238 //item_category2: "", 4239 //item_category3: "" 4240 }; 4241 4242 if (itemCustomization.length > 0) { 4243 item.item_customization = itemCustomization; 4244 } 4245 4246 dataLayer.push({ 4247 event: "add_to_cart", 4248 gtmparams: { 4249 pagetype: "product", 4250 product: { 4251 id: productId, 4252 name: productName 4253 } 4254 }, 4255 ecommerce: { 4256 currency: "EUR", 4257 value: newItem.subtotal, 4258 items: [item] 4259 }, 4260 ecomm_prodid: productId, 4261 ecomm_pagetype: "product", 4262 ecomm_totalvalue: newItem.subtotal, 4263 product_ids: productId, 4264 page_type: encodeURIComponent(productName), 4265 total_value: newItem.subtotal, 4266 currency: "EUR", 4267 value: newItem.subtotal 4268 }); 4269 4270 if (window.debugPixel === true) { 4271 console.log("[GTM] add_to_cart", { 4272 value: newItem.subtotal, 4273 currency: "EUR", 4274 items: [item] 4275 }); 4276 } 4277 } 4278 4279 4280 4281 4282 // ð Feedback 4283 app.popup.close('.modal-product-' + productId); 4284 const currentPath = window.location.pathname; 4285 const isMenuPage = /^\/menu\/[^\/]+$/.test(currentPath); 4286 4287 if (isMenuPage) { 4288 navigateUrl(currentPath); 4289 } else { 4290 navigateUrl('/store/' + storeSlug); 4291 } 4292 4293 //navigateUrl('/store/' + storeSlug); 4294 updateCart(true); 4295 firstItemCart(); 4296 feedbackSuccess(`Adicionado ${productName} à lista`); 4297 4298 if (cart?.length == 1) { 4299 setTimeout(() => { 4300 $(".cart-navbar").trigger("click"); 4301 }, 1500); 4302 } 4303 }); 4304 4305 4306 4307 4308 4309} 4310 4311 4312 4313 4314 4315 4316 4317 function initSearchScript() { 4318 4319 // window.location.href="/?" 4320 if(!isDesktop){ 4321 $("#search-sidebar-filter").addClass("panel panel-left panel-floating panel-resizable panel-init dark:bg-black"); 4322 $("#search-sidebar-filter-content").addClass("page-content pt-2.5"); 4323 $("#search-sidebar-filter-list").addClass("list links-list"); 4324 }else{ 4325 $("#search-sidebar-filter").removeClass("panel panel-left panel-floating panel-resizable panel-init dark:bg-black"); 4326 $("#search-sidebar-filter-content").removeClass("page-content pt-2.5"); 4327 $("#search-sidebar-filter-list").removeClass("list links-list"); 4328 } 4329 4330 4331 const updateFilter = (filterType, feature = false) => { 4332 let filterValues = ''; 4333 let selectorPrefix = feature ? 'input[data-feature-filter=' : 'input[data-filter='; 4334 4335 $(`${selectorPrefix}${filterType}]:checked`).each(function() { 4336 filterValues += $(this).attr(feature ? 'data' : 'name') + ','; 4337 }); 4338 4339 // Remove trailing comma 4340 filterValues = filterValues.slice(0, -1); 4341 4342 // Update the corresponding input field 4343 $(`input[type='text'][data-filter=${filterType}]`).val(filterValues ? `${filterType}:${filterValues}` : ""); 4344 4345 // Construct the new URL 4346 let currentUrl = new URL(window.location.href); 4347 let filterParam = ''; 4348 let filters = [ 4349 'category', 4350 'diet', 4351 'price_interval', 4352 ]; 4353
4354 filters.forEach((filter) => { 4355 let filterValue = $(`input[type='text'][data-filter=${filter}]`).val(); 4356 // Checking if filterValue has a value after the colon (:) 4357 if(filterValue && filterValue.includes(':') && filterValue.split(':')[1] !== '') { 4358 filterParam += (filterParam ? '|' : '') + filterValue; 4359 } 4360 }); 4361 4362 // Set the filter query param 4363 if(filterParam) { 4364 currentUrl.searchParams.set('filter', filterParam); 4365 } else { 4366 currentUrl.searchParams.delete('filter'); 4367 } 4368 4369 // Update the URL without refreshing the page 4370 window.location.href = currentUrl; 4371 } 4372 4373 4374 $("input[data-filter='category']").on('change', function() { 4375 updateFilter('category'); 4376 }); 4377 $("input[data-feature-filter='category']").on('change', function() { 4378 updateFilter('category',true); 4379 }); 4380 $("input[data-filter='diet']").on('change', function() { 4381 updateFilter('diet'); 4382 }); 4383 $("input[data-feature-filter='diet']").on('change', function() { 4384 updateFilter('diet',true); 4385 }); 4386 $("input[data-filter='price_interval']").on('change', function() { 4387 updateFilter('price_interval'); 4388 }); 4389 $("input[data-feature-filter='price_interval']").on('change', function() { 4390 updateFilter('price_interval',true); 4391 }); 4392 4393 4394 4395 } 4396 function homeScript(){ 4397 var locations = [{"name":"Aveiro","address":"Aveiro","country":"Portugal","lat":40.641185,"lng":-8.653617},{"name":"ALGARVE","address":"Parque Das Cidades, 8135 Faro","country":"Portugal","lat":37.088399,"lng":-7.975527},{"name":"Porto","address":"Porto","country":"Portugal","lat":41.150153,"lng":-8.610318},{"name":"Lisboa","address":"Lisboa","country":"Portugal","lat":38.707008,"lng":-9.135641}]; 4398 var lat = 41.8483; 4399 var lng = -87.6517; 4400 setTimeout(() => { 4401 showMap('map', lat, lng, locations, true, 6); 4402 }, 1000); 4403 4404 } 4405 function initAccountScript(){ 4406 let dropzone = new Dropzone('#dropzoneavatar', { 4407 url: '/common/storage/upload/amazon_s3', // replace with your upload URL 4408 paramName: 'file', 4409 method: 'post', 4410 headers: { 4411 'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content 4412 }, 4413 maxFilesize: 2.5, // in MB 4414 maxFiles: 1, 4415 acceptedFiles: 'image/*', 4416 addRemoveLinks: true, 4417 clickable: true, 4418 dictRemoveFile: '', 4419 previewsContainer: '#previewavatar', // define where to append the previews 4420 previewTemplate: ` 4421 <div class="dz-preview dz-file-preview w-full relative"> 4422 <div class="dz-image bg-cover bg-center w-full h-32"> 4423 <img data-dz-thumbnail /> 4424 </div> 4425 <div class="dz-details"> 4426 <div class="dz-size"><span data-dz-size></span></div> 4427 <div class="dz-filename"><span data-dz-name></span></div> 4428 </div> 4429 <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> 4430 <div class="dz-error-message"><span data-dz-errormessage></span></div> 4431 <a href="#!" class="dz-remove -mt-4" data-dz-remove><i class="bi bi-x-circle-fill absolute -right-2 top-2 -mt-5 text-red-500 text-2xl"></i></a> 4432 </div>`, 4433 init: function() { 4434 this.on('addedfile', function(file) { 4435 if (file.type.match(/image.*/)) { 4436 this.createThumbnailFromUrl(file, URL.createObjectURL(file)); 4437 } 4438 }); 4439 this.on('maxfilesexceeded', function(file) { 4440 toast("error", '[520] Sem Mais Arquivos, Por Favor!', 3000); 4441 this.removeFile(file); // remove file after alert 4442 }); 4443 this.on('error', function(file, errorMessage) { 4444 if (file.size > this.options.maxFilesize * 1024 * 1024) { 4445 toast("error", '[530] Tamanho do Arquivo Excedido', 3000); 4446 this.removeFile(file); 4447 } else { 4448 toast("error", errorMessage, 3000); 4449 } 4450 }); 4451 this.on('removedfile', function(file) { 4452 if (file.xhr) { 4453 let fileResponse = JSON.parse(file.xhr.response); 4454 let fileUrl = fileResponse; // the url of the removed file 4455 let dataArray = JSON.parse($("#avatar").val()); // current array of files 4456 // Loop through the dataArray in reverse 4457 for (let i = dataArray.length - 1; i >= 0; i--) { 4458 // if the current array item matches the fileUrl, remove it 4459 if (dataArray[i].url.original == fileUrl.url.original) { 4460 dataArray.splice(i, 1); 4461 } 4462 } 4463 // Overwrite the old dataArray with the updated one 4464 $("#avatar").val(JSON.stringify(dataArray)).trigger('change'); 4465 } 4466 }); 4467 this.on("sending", function() { 4468 $('.upload-loading-avatar').removeClass("hidden"); 4469 $('.upload-icon-avatar').addClass("hidden"); 4470 $('.upload-text-avatar').text("Loading..."); 4471 }); 4472 this.on("success", function() { 4473 $('.upload-loading-avatar').addClass("hidden"); 4474 $('.upload-icon-avatar').removeClass("hidden"); 4475 $('.upload-text-avatar').text("Drag the files here or click to upload."); 4476 }); 4477 this.on('error', function(file, response) { 4478 console.log(response); 4479 $('.upload-loading-avatar').addClass("hidden"); 4480 $('.upload-icon-avatar').removeClass("hidden"); 4481 $('.upload-text-avatar').text("Drag the files here or click to upload."); 4482 }); 4483 }, 4484 success: function(file, response) { 4485 // Get the textarea element by its ID 4486 let textarea = $("#avatar"); 4487 let dataArray = []; 4488 // Check if the textarea is not empty 4489 if (textarea.val().trim() !== "") { 4490 try { 4491 // Parse the existing textarea value as JSON 4492 let parsedData = JSON.parse(textarea.val()); 4493 // Check if parsedData is an array or an object 4494 if (Array.isArray(parsedData)) { 4495 dataArray = parsedData; 4496 } else if (typeof parsedData === 'object') { 4497 dataArray = [parsedData]; 4498 } else { 4499 console.error('Parsed data is neither an array nor an object:', parsedData); 4500 } 4501 } catch (error) { 4502 console.error('Invalid JSON:', textarea.val()); 4503 } 4504 } 4505 // Push the response data to the dataArray if it's an array 4506 if (Array.isArray(dataArray)) { 4507 let responseData = response; 4508 dataArray.push(responseData); 4509 // Update the textarea with the updated dataArray 4510 textarea.val(JSON.stringify(dataArray)).trigger('change'); 4511 } else { 4512 console.error('dataArray is not an array:', dataArray); 4513 } 4514 }, 4515 error: function(file, response) { 4516 console.log(response); 4517 } 4518 }); 4519 window.myDropzone = dropzone; 4520 4521 4522 } 4523 function initReservationsScript(){ 4524 const CSRF = $('meta[name="csrf-token"]').attr('content'); 4525 let rescheduleId = null; 4526 4527 $('.reservation-tab[data-tab="upcoming"]').addClass('active'); 4528 4529 $('.reservation-tab').off('click').on('click', function() { 4530 const tab = $(this).data('tab'); 4531 $('.reservation-tab').removeClass('active'); 4532 $(this).addClass('active'); 4533 $('.reservation-panel').addClass('hidden'); 4534 $('.reservation-panel[data-panel="' + tab + '"]').removeClass('hidden'); 4535 }); 4536 4537 function feedback(message, isError) { 4538 $('#reservationFeedback') 4539 .removeClass('hidden bg-red-50 text-red-600 bg-green-50 text-green-700') 4540 .addClass(isError ? 'bg-red-50 text-red-600' : 'bg-green-50 text-green-700') 4541 .text(message); 4542 } 4543 4544 // âââ Cancelar âââââââââââââââââââââââââââââââââââââââââââ 4545 $('.btn-cancel-reservation').off('click').on('click', function() { 4546 if (!confirm('Tem a certeza que pretende cancelar esta reserva?')) return; 4547 4548 const id = $(this).data('id'); 4549 $.ajax({ 4550 url: '/myaccount/reservations/' + id + '/cancel', 4551 method: 'POST', 4552 headers: { 'X-CSRF-TOKEN': CSRF }, 4553 success: function(res) { 4554 feedback(res.message, false); 4555 location.reload(); 4556 }, 4557 error: function(xhr) { 4558 feedback((xhr.responseJSON && xhr.responseJSON.error) || 'Não foi possÃvel cancelar.', true); 4559 } 4560 }); 4561 }); 4562 4563 // âââ Remarcar âââââââââââââââââââââââââââââââââââââââââââ 4564 $('.btn-reschedule').off('click').on('click', function() { 4565 rescheduleId = $(this).data('id'); 4566 const storeId = $(this).data('store'); 4567 4568 $('#rescheduleError').addClass('hidden').text(''); 4569 $('#reschedulePeople').val($(this).data('people')); 4570 $('#rescheduleDate').html('<option>A carregar...</option>'); 4571 $('#rescheduleTime').html(''); 4572 $('#rescheduleOverlay').addClass('active').removeClass('hidden'); 4573 4574 $.get('/reservations/' + storeId + '/days', function(data) { 4575 const days = data.days || []; 4576 if (!days.length) { 4577 $('#rescheduleDate').html('<option value="">Sem datas disponÃveis</option>'); 4578 return; 4579 } 4580 $('#rescheduleDate').html(days.map(d => '<option value="' + d + '">' + d + '</option>').join('')); 4581 loadTimes(storeId, days[0]); 4582 }); 4583 4584 $('#rescheduleDate').off('change').on('change', function() { 4585 loadTimes(storeId, $(this).val()); 4586 }); 4587 }); 4588 4589 function loadTimes(storeId, date) { 4590 if (!date) return; 4591 $('#rescheduleTime').html('<option>A carregar...</option>'); 4592 $.get('/reservations/' + storeId + '/slots', { date: date }, function(data) { 4593 const slots = data.slots || []; 4594 $('#rescheduleTime').html(slots.length 4595 ? slots.map(s => '<option value="' + s + '">' + s + '</option>').join('') 4596 : '<option value="">Sem horários disponÃveis</option>'); 4597 }); 4598 } 4599 4600 $('#btnCloseReschedule').off('click').on('click', function() { 4601 $('#rescheduleOverlay').removeClass('active').addClass('hidden'); 4602 }); 4603 4604 $('#btnConfirmReschedule').off('click').on('click', function() { 4605 $.ajax({ 4606 url: '/myaccount/reservations/' + rescheduleId + '/reschedule', 4607 method: 'POST', 4608 headers: { 'X-CSRF-TOKEN': CSRF }, 4609 data: { 4610 date: $('#rescheduleDate').val(), 4611 time: $('#rescheduleTime').val(), 4612 people: $('#reschedulePeople').val(), 4613 }, 4614 success: function() { 4615 location.reload(); 4616 }, 4617 error: function(xhr) { 4618 $('#rescheduleError').removeClass('hidden') 4619 .text((xhr.responseJSON && xhr.responseJSON.error) || 'Não foi possÃvel remarcar.'); 4620 } 4621 }); 4622 }); 4623
4624 // âââ Avaliar ââââââââââââââââââââââââââââââââââââââââââââ 4625 $('.review-star').off('click').on('click', function() { 4626 const value = parseInt($(this).data('value'), 10); 4627 const $wrap = $(this).closest('.review-stars'); 4628 $wrap.attr('data-rating', value); 4629 $wrap.find('.review-star').each(function() { 4630 const starValue = parseInt($(this).data('value'), 10); 4631 $(this).toggleClass('bi-star-fill', starValue <= value).toggleClass('bi-star', starValue > value); 4632 }); 4633 }); 4634 4635 $('.btn-save-review').off('click').on('click', function() { 4636 const id = $(this).data('id'); 4637 const $block = $('[data-review-for="' + id + '"]'); 4638 const rating = parseInt($block.find('.review-stars').attr('data-rating'), 10); 4639 4640 if (!rating) { 4641 feedback('Escolha uma classificação de 1 a 5 estrelas.', true); 4642 return; 4643 } 4644 4645 $.ajax({ 4646 url: '/myaccount/reservations/' + id + '/review', 4647 method: 'POST', 4648 headers: { 'X-CSRF-TOKEN': CSRF }, 4649 data: { rating: rating, comment: $block.find('.review-comment').val() }, 4650 success: function(res) { 4651 feedback(res.message, false); 4652 }, 4653 error: function(xhr) { 4654 feedback((xhr.responseJSON && xhr.responseJSON.error) || 'Não foi possÃvel guardar a avaliação.', true); 4655 } 4656 }); 4657 }); 4658 4659 // âââ Remover favorito âââââââââââââââââââââââââââââââââââ 4660 $('.btn-remove-favourite').off('click').on('click', function() { 4661 const $card = $(this).closest('[data-favourite]'); 4662 $.ajax({ 4663 url: '/common/set/like', 4664 method: 'POST', 4665 headers: { 'X-CSRF-TOKEN': CSRF }, 4666 data: { id: $(this).data('id'), type: 'store', url: $(this).data('url') }, 4667 success: function() { 4668 $card.remove(); 4669 } 4670 }); 4671 }); 4672 } 4673 function updatePersonValue(id, increment) { 4674 const input = document.getElementById(id); 4675 const currentValue = Number(input.value); 4676 const newValue = Math.max(0, Math.min(30, currentValue + increment)); 4677 input.value = newValue; 4678 4679 saveData(id,newValue); 4680 4681 updateButtonText(); 4682 } 4683 function updateButtonText() { 4684 const adults = parseInt($('#adults').val()) || 0; 4685 const children = parseInt($('#children').val()) || 0; 4686 const rooms = parseInt($('#rooms').val()) || 0; 4687 $('#person-dropdown').html(`<div class="truncate"> ${adults} Adulto(s), ${children} Criança(s), ${rooms} Quarto(s) </div>`); 4688 } 4689 4690 4691 // function removeFromCart(cart_id) { 4692 // // Retrieve the existing cart from localStorage 4693 // var shoppingCart = JSON.parse(localStorage.getItem('cart')); 4694 // // If the cart doesn't exist yet or is empty, do nothing 4695 // if (shoppingCart === null || shoppingCart.length === 0) { 4696 // return; 4697 // } 4698 // // Find the index of the item in the shopping cart 4699 // var itemIndex = shoppingCart.findIndex(item => item.cart_id === cart_id); 4700 // // If the item was found, remove it from the shopping cart 4701 // if (itemIndex !== -1) { 4702 // shoppingCart.splice(itemIndex, 1); 4703 // } 4704 // // Save the updated cart to localStorage 4705 // localStorage.setItem('cart', JSON.stringify(shoppingCart)); 4706 // // Update the cart display 4707 // updateCart(); 4708 4709 4710 4711 // if(shoppingCart.length == 0){ 4712 // // Handle the empty or non-existing cart scenario 4713 // $('.cart-badge').addClass("opacity-0"); 4714 // $('.cart-icon').removeClass("bi-cart-check-fill").addClass("bi-cart"); 4715 // $('.checkout-btn').addClass("hidden"); 4716 // $('.anti-checkout-btn').removeClass("hidden"); 4717 // $('.checkout-btn-total').addClass("hidden"); 4718 // localStorage.setItem('checkout-total', 0); 4719 // } 4720 // firstItemCart(); 4721 // toast("error","Removido",2000); 4722 4723 // // â Google Tag Manager: Evento de remove_from_cart 4724 // if (typeof dataLayer !== 'undefined') { 4725 // dataLayer.push({ 4726 // event: "remove_from_cart", 4727 // gtmparams: { pagetype: "cart" }, 4728 // ecommerce: { 4729 // items: [ 4730 // { 4731 // item_id: removedItem.id, 4732 // item_name: removedItem.name, 4733 // price: removedItem.price, 4734 // quantity: removedItem.qty, 4735 // item_variant: removedItem.option?.name || "" 4736 // } 4737 // ] 4738 // } 4739 // }); 4740 4741 // if (window.debugPixel === true) { 4742 // console.log("[GTM] remove_from_cart:", removedItem); 4743 // } 4744 // } 4745 // } 4746 4747 function removeFromCart(cart_id) { 4748 var shoppingCart = JSON.parse(localStorage.getItem('cart')); 4749 if (!shoppingCart || shoppingCart.length === 0) return; 4750 4751 var itemIndex = shoppingCart.findIndex(item => item.cart_id === cart_id); 4752 if (itemIndex === -1) return; 4753 4754 // ð¥ CAPTURA os dados antes de apagar 4755 var removedItem = shoppingCart[itemIndex]; 4756 4757 // â Só depois remove do array 4758 shoppingCart.splice(itemIndex, 1); 4759 4760 // Atualiza localStorage e UI 4761 localStorage.setItem('cart', JSON.stringify(shoppingCart)); 4762 updateCart(); 4763 4764 if (shoppingCart.length === 0) { 4765 $('.cart-badge').addClass("opacity-0"); 4766 $('.cart-icon').removeClass("bi-cart-check-fill").addClass("bi-cart"); 4767 $('.checkout-btn').addClass("hidden"); 4768 $('.anti-checkout-btn').removeClass("hidden"); 4769 $('.checkout-btn-total').addClass("hidden"); 4770 localStorage.setItem('checkout-total', 0); 4771 } 4772 4773 firstItemCart(); 4774 toast("error", "Removido", 2000); 4775 4776 // â Google Tag Manager: Evento de remove_from_cart 4777 if (typeof dataLayer !== 'undefined') { 4778 dataLayer.push({ 4779 event: "remove_from_cart", 4780 gtmparams: { pagetype: "cart" }, 4781 ecommerce: { 4782 items: [ 4783 { 4784 item_id: removedItem.id, 4785 item_name: removedItem.name, 4786 price: removedItem.price, 4787 quantity: removedItem.qty, 4788 item_variant: removedItem.option?.name || "" 4789 } 4790 ] 4791 } 4792 }); 4793 4794 if (window.debugPixel === true) { 4795 console.log("[GTM] remove_from_cart:", removedItem); 4796 } 4797 } 4798 4799 // â Se o item removido NÃO for uma oferta, remova também a oferta (caso exista) 4800 if (removedItem.option.name !== "offer") { 4801 const hadOffer = shoppingCart.some(item => item.option.name === "offer"); 4802 if (hadOffer) { 4803 shoppingCart = shoppingCart.filter(item => item.option.name !== "offer"); 4804 localStorage.setItem('cart', JSON.stringify(shoppingCart)); 4805 updateCart(); 4806 toast("info", "Oferta removida ao alterar o carrinho", 3000); 4807 } 4808 } 4809 4810 } 4811 4812 function validateReview() { 4813 // Reset any error highlights 4814 $('.error-highlight').removeClass('error-highlight'); 4815 4816 if ($("#review_text").val().trim() === "") { 4817 toast("error", "[450] Campos Obrigatórios", 3000); 4818 $("#review_text").focus(); 4819 //smoothScrollTo("#review_text"); 4820 return false;
4821 } 4822 4823 let isAllChecked = true; 4824 const categories = ["rate"]; 4825 const categoriesName = ["Avaliação"]; 4826 for (let i = 0; i < categories.length; i++) { 4827 if (!$(`input[name=${categories[i]}]:checked`).val()) { 4828 toast("error", categoriesName[i]+": [450] Campos Obrigatórios", 3000); 4829 let errorElement = $(`input[name=${categories[i]}]`).closest('tr'); // Get the entire table row 4830 errorElement.addClass('error-highlight'); // Highlight the entire row 4831 isAllChecked = false; 4832 break; 4833 } 4834 } 4835 4836 return isAllChecked; 4837 } 4838 function validateComment() { 4839 $('.error-highlight').removeClass('error-highlight'); 4840 if ($("#review_text").val().trim() === "") { 4841 toast("error", "[450] Campos Obrigatórios", 3000); 4842 $("#review_text").focus(); 4843 return false; 4844 } 4845 return true; 4846 } 4847 // Object to hold local address data AIzaSyBfFYFwmiDI1__TWJyHZfg1vev1uT4TAVY 4848 let localAddressData = JSON.parse(localStorage.getItem('addresses')) || {}; 4849 function autocomplete(inputId, api) { 4850 // General levels 4851 const levels = { 4852 'default': { 4853 'google': null, 4854 'tomtom': 'search', 4855 'bing': 'Address', 4856 'openstreetmap': null, 4857 'mapbox': 'place,locality,neighborhood,address,poi' 4858 }, 4859 'address': { 4860 'google': 'address', 4861 'tomtom': 'Street', 4862 'bing': 'Address', 4863 'openstreetmap': null, 4864 'mapbox': 'address' 4865 }, 4866 'city': { 4867 'google': '(cities)', 4868 'tomtom': 'municipality', 4869 'bing': 'PopulatedPlace', 4870 'openstreetmap': null, 4871 'mapbox': 'place,locality' 4872 }, 4873 'state': { 4874 'google': '(regions)', 4875 'tomtom': 'macroregion', 4876 'bing': 'AdminDivision1', 4877 'openstreetmap': null, 4878 'mapbox': 'region' 4879 }, 4880 'country': { 4881 'google': '(regions)', 4882 'tomtom': 'Country', 4883 'bing': 'CountryRegion', 4884 'openstreetmap': null, 4885 'mapbox': 'country' 4886 } 4887 }; 4888 const currentLevel = 'address'; // Set the current level here 4889 // Google Places API 4890 if (api === 'google') { 4891 const autocompleteService = new google.maps.places.AutocompleteService(); 4892 const googleLevel = levels[currentLevel]['google']; 4893 const inputEl = $(`#${inputId}`); 4894 const currentLat = parseFloat(inputEl.data('current-lat')) || null; 4895 const currentLng = parseFloat(inputEl.data('current-lng')) || null; 4896 4897 inputEl.on('input', function() { 4898 let query = $(this).val(); 4899 if (query.length > 0) { 4900 const request = { input: query }; 4901 4902 if (googleLevel) { 4903 request.types = [googleLevel]; 4904 } 4905 if (currentLat && currentLng) { 4906 // If we have the user's location, prioritize nearby places 4907 request.location = new google.maps.LatLng(currentLat, currentLng); 4908 request.radius = '2000'; // prioritize locations within 2km, adjust as per need 4909 } 4910 4911 autocompleteService.getPlacePredictions(request, function(predictions, status) { 4912 if (status == google.maps.places.PlacesServiceStatus.OK) { 4913 const results = predictions.map(prediction => { 4914 return { 4915 formatted_address: prediction.description, 4916 // Placeholder para outros campos. Detalhes adicionais podem exigir uma chamada adicional à API. 4917 place_id: prediction.place_id, // incluir place_id aqui 4918 lat: null, 4919 lng: null, 4920 street: null, 4921 city: null, 4922 state: null, 4923 country: null, 4924 zip: null, 4925 }; 4926 }); 4927 showSuggestions(inputId, results, api); 4928 } 4929 }); 4930 } 4931 }); 4932 } 4933 4934 // TomTom Search API 4935 else if (api === 'tomtom') { 4936 const tomtomApiKey = 'Kn09fHvoCZdGKtl7qqR94cM5Ylbuu8OE'; 4937 const tomtomLevel = levels[currentLevel]['tomtom']; 4938 4939 $(`#${inputId}`).on('input', function() { 4940 let query = $(this).val(); 4941 4942 if (query.length > 0) { 4943 let categorySet; 4944 4945 if (tomtomLevel === 'city') { 4946 categorySet = '7316'; // for city or town halls 4947 } else if (tomtomLevel === 'country') { 4948 categorySet = '7322'; // for embassies or consulates 4949 } 4950 // add more category sets if needed 4951 4952 let tomtomApiUrl = `https://api.tomtom.com/search/2/search/${encodeURIComponent(query)}.json?key=${tomtomApiKey}`; 4953 4954 if (categorySet) { 4955 tomtomApiUrl += `&categorySet=${categorySet}`; 4956 } 4957 4958 $.ajax({ 4959 url: tomtomApiUrl, 4960 type: 'GET', 4961 success: function (data) { 4962 if (data.results) { 4963 const results = data.results.map(result => { 4964 return { 4965 formatted_address: result.address.freeformAddress, 4966 lat: result.position.lat, 4967 lng: result.position.lon, 4968 street: result.address.streetName || "", 4969 street_number: result.address.streetNumber || "", 4970 city: result.address.municipality || "", 4971 state: result.address.countrySubdivision || "", 4972 country: result.address.country || "", 4973 zip: result.address.postalCode || "", 4974 }; 4975 }); 4976 showSuggestions(inputId, results, api); 4977 } 4978 } 4979 }); 4980 } 4981 }); 4982 } 4983 4984 else if (api === 'openstreetmap') { 4985 const openStreetMapLevel = levels[currentLevel]['openstreetmap']; 4986 4987 $(`#${inputId}`).on('input', function() { 4988 let query = $(this).val(); 4989 4990 if (query.length > 0) { 4991 // Include the addressdetails parameter in your request 4992 const openStreetMapApiUrl = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}&addressdetails=1`; 4993 4994 $.ajax({ 4995 url: openStreetMapApiUrl, 4996 type: 'GET', 4997 dataType: 'json', 4998 success: function (data) { 4999 if (data.length) { 5000 const results = data.map(result => { 5001 // Check the level of detail in the result 5002 switch (currentLevel) { 5003 case 'address': 5004 if (!result.address.house_number) { 5005 return null; 5006 } 5007 break; 5008 case 'city': 5009 if (!result.address.city) { 5010 return null; 5011 } 5012 break; 5013 case 'country': 5014 if (!result.address.country) { 5015 return null; 5016 } 5017 break; 5018 default: 5019 break; 5020 } 5021 5022 return { 5023 formatted_address: result.display_name, 5024 lat: result.lat, 5025 lng: result.lon, 5026 country: result.address ? result.address.country : null 5027 }; 5028 }).filter(item => item); // Remove null results 5029 5030 showSuggestions(inputId, results); 5031 } 5032 } 5033 }); 5034 } 5035 }); 5036 } 5037 // Other APIs would follow a similar pattern 5038 else { 5039 // Implementations for other APIs 5040 } 5041 } 5042 5043 5044 5045 // Event listener for link clicks 5046 $(document).on('click', 'a', function(e) { 5047 var href = $(this).attr('href'); 5048 var top = $(this).data('scroll-top'); 5049 // Check if href starts with '#' (anchor link) 5050 if (href && href.startsWith('#')) { 5051 e.preventDefault(); // Prevent default jump to anchor behavior 5052 // Invoke the smooth scroll function 5053 smoothScrollToElement(href,200,top); 5054 } 5055 }); 5056 5057 5058 5059 5060 5061 function validateFieldById(fieldId, fieldName) { 5062 let fieldValue = $(`#${fieldId}`).val(); 5063 if (!fieldValue.trim()) { 5064 elementShake(`#${fieldId}`,`#${fieldId}`,380,3) 5065 toast("error", `Campo ${fieldName} é obrigatório`, 3000); 5066 return false;
5067 } else { 5068 $(`#${fieldId}`).removeClass('border-red-500'); 5069 return true; 5070 } 5071 } 5072 5073 let pendingProductModal = null; 5074 5075 // Variável global mutável â atualizada por sqvUpdateStoreState após agendamento/modo 5076 window.sqvStoreIsOpen = true; 5077 5078 function abrirModalProdutoComVerificacao(productId, maiorIdade) { 5079 const modalSelector = `.modal-product-${productId}`; 5080 5081 if (!window.sqvStoreIsOpen) { 5082 pendingProductModal = modalSelector; 5083 app.popup.open('.modal-loja-fechada'); 5084 return; 5085 } 5086 5087 if (maiorIdade === 1) { 5088 const confirmacao = getCookie('maior_idade_confirmado'); 5089 5090 if (confirmacao === 'sim') { 5091 app.popup.open(modalSelector); 5092 } else if (confirmacao === 'nao') { 5093 app.popup.open('.modal-acesso-negado'); 5094 } else { 5095 pendingProductModal = modalSelector; 5096 app.popup.open('.modal-maior-idade'); 5097 } 5098 } else { 5099 app.popup.open(modalSelector); 5100 } 5101 } 5102 5103 let pendingSimpleProduct = null; 5104 5105 function verificarProdutoSimplesEAdicionar(productId, maiorIdade, el) { 5106 if (!window.sqvStoreIsOpen) { 5107 pendingSimpleProduct = { productId, el }; 5108 app.popup.open('.modal-loja-fechada'); 5109 return; 5110 } 5111 5112 if (maiorIdade === 1) { 5113 const confirmacao = getCookie('maior_idade_confirmado'); 5114 5115 if (confirmacao === 'sim') { 5116 adicionarProdutoSimples(productId, el); 5117 } else if (confirmacao === 'nao') { 5118 app.popup.open('.modal-acesso-negado'); 5119 } else { 5120 pendingSimpleProduct = { productId, el }; 5121 app.popup.open('.modal-maior-idade'); 5122 } 5123 } else { 5124 adicionarProdutoSimples(productId, el); 5125 } 5126 } 5127 5128 5129 5130 5131 5132 5133 5134 // Botões da modal de idade 5135 $('#idade-nao').on('click', function () { 5136 setCookie('maior_idade_confirmado', 'nao', 30); // expira em 30 dias 5137 app.popup.close('.modal-maior-idade'); 5138 setTimeout(() => { 5139 app.popup.open('.modal-acesso-negado'); 5140 }, 300); 5141 }); 5142 5143 $('#idade-sim').on('click', function () { 5144 setCookie('maior_idade_confirmado', 'sim', 30); // expira em 30 dias 5145 app.popup.close('.modal-maior-idade'); 5146 if (pendingProductModal) { 5147 app.popup.open(pendingProductModal); 5148 pendingProductModal = null; 5149 } 5150 }); 5151 5152 5153// Funciina bem para uma loja 5154// $('.close-acesso-negado').on('click', function () { 5155// app.popup.close('.modal-acesso-negado'); 5156// }); 5157 5158// Funciona bem para site com uma loja 5159 // $("#btn-agendar-por-fecho").on("click", function () { 5160 // app.popup.close('.modal-loja-fechada'); 5161 5162 // setTimeout(() => { 5163 // app.popup.open('.modal-schedule'); 5164 5165 // setTimeout(() => { 5166 // // Simula clique no primeiro botão de dia 5167 // const firstDay = $('.modal-schedule .day-selector.first-day'); 5168 // if (firstDay.length) { 5169 // firstDay.trigger('click'); 5170 // } 5171 // }, 300); // tempo para garantir que a modal carregou por completo 5172 // }, 300); 5173// }); 5174 5175 5176 // Funciona bem para site com duas ou mais lojas 5177 $(document).on('click', '.close-acesso-negado', function () { 5178 app.popup.close('.modal-acesso-negado'); 5179 }); 5180 5181 5182 // Funciona bem para site com duas ou mais lojas 5183 $("#btn-agendar-por-fecho").on("click", function () { 5184 app.popup.close('.modal-loja-fechada'); 5185 5186 // ð Salva a modal do produto que estava pendente 5187 if (pendingProductModal) { 5188 localStorage.setItem('reabrir_modal_produto', pendingProductModal); 5189 } 5190 5191 // ð Abre a modal de agendamento normalmente 5192 setTimeout(() => { 5193 app.popup.open('.modal-schedule'); 5194 5195 setTimeout(() => { 5196 const firstDay = $('.modal-schedule .day-selector.first-day'); 5197 if (firstDay.length) { 5198 firstDay.trigger('click'); 5199 } 5200 }, 300); 5201 }, 300); 5202 }); 5203 5204 5205 // Verifica após reload se deve reabrir modal do produto 5206 const produtoParaReabrir = localStorage.getItem('reabrir_modal_produto'); 5207 if (produtoParaReabrir) { 5208 setTimeout(() => { 5209 app.popup.open(produtoParaReabrir); 5210 localStorage.removeItem('reabrir_modal_produto'); 5211 }, 800); 5212 } 5213 5214 5215 5216 5217// $('#rever-idade').on('click', function () { 5218// deleteCookie('maior_idade_confirmado'); 5219// toast('success', 'Preferência apagada. A idade será verificada no próximo produto alcoólico.', 3000);
5220// app.popup.open('.modal-maior-idade'); 5221// }); 5222 5223 function adicionarProdutoSimples(productId, el) { 5224 // Verifica se a loja está fechada 5225 if (!window.sqvStoreIsOpen) { 5226 app.popup.open('.modal-loja-fechada'); 5227 return; 5228 } 5229 5230 const $el = $(el); 5231 const productName = $el.data("product-name"); 5232 const productImg = $el.data("product-img"); 5233 const storeId = $el.data("store-uuid"); 5234 const storeName = $el.data("store-name"); 5235 const storeURL = $el.data("store-url"); 5236 const storeImg = $el.data("store-img"); 5237 const storeSlug = $el.data("store-slug"); 5238 5239 let qty = parseInt($('#card-qty-' + productId).val(), 10); 5240 if (isNaN(qty) || qty < 0) qty = 0; 5241 qty += 1; 5242 $('#card-qty-' + productId).val(qty); 5243 5244 $('#card-qty-label-' + productId).text(qty > 0 ? qty : 'Adicionar'); 5245 5246 5247 // ð§¾ Garante que os totais estão atualizados 5248 let total = JSON.parse($('#total-' + productId).val() || "{}"); 5249 5250 if (!total?.unit_price || total?.unit_price === 0) { 5251 // Força o cálculo e tenta novamente 5252 showTotals(productId); // <â certifica-se de que isso existe no seu projeto 5253 total = JSON.parse($('#total-' + productId).val() || "{}"); 5254 5255 // Se mesmo assim estiver incompleto, cancela 5256 if (!total?.unit_price || total?.unit_price === 0) { 5257 console.warn(`Total inválido para o produto ${productId}`, total); 5258 toast("error", "Não foi possÃvel adicionar o produto. Tente novamente.", 3000); 5259 return; 5260 } 5261 } 5262 5263 const note = $('#note-' + productId).val() || ''; 5264 let selectedOptions = {}; 5265 5266 let cart = JSON.parse(localStorage.getItem('cart')) || []; 5267 const first_item = cart[0]; 5268 if (first_item && first_item.store_id !== storeId) { 5269 cart = []; 5270 localStorage.setItem('upsell', null); 5271 } 5272 5273 const existingIndex = cart.findIndex(item => item.id === productId); 5274 if (existingIndex !== -1) { 5275 cart[existingIndex].qty += 1; 5276 cart[existingIndex].subtotal = cart[existingIndex].qty * total.unit_price; 5277 cart[existingIndex].subtotal_without_discount = cart[existingIndex].subtotal; 5278 } else { 5279 const newItem = { 5280 cart_id: generateUniqueId(), 5281 store_id: storeId, 5282 store_name: storeName, 5283 store_url: storeURL, 5284 store_img: storeImg, 5285 id: productId, 5286 name: productName, 5287 img: productImg, 5288 note: note, 5289 option: selectedOptions, 5290 qty: 1, 5291 price: total.unit_price, 5292 discount: total.discount, 5293 subtotal_without_discount: total.unit_price, 5294 subtotal: total.unit_price 5295 }; 5296 cart.push(newItem); 5297 } 5298 5299 // ð¯ Se for item normal, remove ofertas (caso existam) 5300 if (selectedOptions.name !== "offer") { 5301 const hadOffer = cart.some(item => item.option.name === "offer"); 5302 if (hadOffer) { 5303 cart = cart.filter(item => item.option.name !== "offer"); 5304 toast("info", "Oferta removida ao adicionar novo item ao carrinho", 3000); 5305 } 5306 } 5307 5308 localStorage.setItem('cart', JSON.stringify(cart)); 5309 5310 updateCart(true); 5311 feedbackSuccess(`Adicionado ${productName} à lista`); 5312 5313 if (cart.length === 1) { 5314 setTimeout(() => $(".cart-navbar").trigger("click"), 1200); 5315 } 5316 } 5317 5318 function removerProdutoSimples(productId) { 5319 // Lê a quantidade atual do input 5320 let qty = parseInt($('#card-qty-' + productId).val(), 10); 5321 if (isNaN(qty) || qty <= 0) return; 5322 5323 qty -= 1; 5324 $('#card-qty-' + productId).val(qty); // atualiza input 5325 5326 $('#card-qty-label-' + productId).text(qty > 0 ? qty : 'Adicionar'); 5327 5328 5329 let cart = JSON.parse(localStorage.getItem('cart')) || []; 5330 5331 const itemIndex = cart.findIndex(item => item.id === productId); 5332 if (itemIndex === -1) return; // item não encontrado 5333 5334 if (cart[itemIndex].qty > 1) { 5335 cart[itemIndex].qty -= 1; 5336 cart[itemIndex].subtotal = cart[itemIndex].qty * cart[itemIndex].price; 5337 cart[itemIndex].subtotal_without_discount = cart[itemIndex].subtotal; 5338 } else { 5339 cart.splice(itemIndex, 1); // remove item completamente 5340 } 5341 5342 localStorage.setItem('cart', JSON.stringify(cart)); 5343 5344 updateCart(true); 5345 5346 // P8: Feedback diferenciado para remoção 5347 toast("info", "Produto removido do carrinho", 2000); 5348 } 5349 5350 </script>
5350</body> 5351</html> 5352 5353 5354
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.