{"id":1976,"date":"2025-10-08T12:43:28","date_gmt":"2025-10-08T10:43:28","guid":{"rendered":"https:\/\/teetimespain.com\/carrito\/"},"modified":"2025-10-15T12:30:36","modified_gmt":"2025-10-15T10:30:36","slug":"carrito","status":"publish","type":"page","link":"https:\/\/teetimespain.com\/es\/carrito\/","title":{"rendered":"Carrito"},"content":{"rendered":"<div data-elementor-type=\"wp-page\" data-elementor-id=\"1976\" class=\"elementor elementor-1976\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-7b0351c3 e-flex e-con-boxed e-con e-parent\" data-id=\"7b0351c3\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-97097a7 elementor-widget elementor-widget-shortcode\" data-id=\"97097a7\" data-element_type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\">  <style>\n    :root { --tt-accent: #0a8855; --tt-accent-hover: #086b44; --tt-muted: rgba(0,0,0,.08); }\n    #tt-cart-root, #tt-cart-root * { box-sizing: border-box; font: inherit; }\n    #tt-cart-root { display:block; margin: 0; color: inherit; }\n    #tt-cart-root h2 { margin: 0 0 12px; font-weight: 700; }\n    #tt-cart-root h3 { margin: 18px 0 10px; font-weight: 700; }\n    #tt-cart-root .tt-cart-table { border-radius: 16px; border: 1px solid var(--tt-muted); overflow: hidden; background: #fff; }\n    #tt-cart-root table { width: 100%; border-collapse: collapse; }\n    #tt-cart-root thead th { background: #f6faf8; text-align: left; padding: 12px; font-weight: 700; border-bottom: 1px solid var(--tt-muted); }\n    #tt-cart-root tbody td { padding: 12px; border-bottom: 1px solid var(--tt-muted); vertical-align: top; }\n    #tt-cart-root tbody tr:last-child td { border-bottom: 0; }\n    #tt-cart-root .tt-cart-sub { margin-top: 8px; font-weight: 700; }\n    #tt-cart-root #tt-cart-grand { margin-top: 14px; font-weight: 800; font-size: 1.05rem; }\n    #tt-cart-root #tt-cart-warning { margin-top: 14px; }\n    #tt-cart-root .tt-cart-alert { margin-top: 8px; padding: 12px 14px; border-radius: 12px; border: 1px solid #e63946; background: rgba(230,57,70,.08); color: #b42318; font-weight: 700; }\n    #tt-cart-root .tt-cart-item-alert { color: #b42318; font-weight: 700; }\n    #tt-cart-root .tt-actions { margin-top: 16px; display: flex; gap: 10px; flex-wrap: wrap; }\n    #tt-cart-root .tt-btn { display: inline-flex; align-items: center; justify-content: center; padding: 10px 16px; border-radius: 9999px; border: 1px solid var(--tt-accent); background: transparent; color: var(--tt-accent); cursor: pointer; text-decoration: none; transition: background .15s ease, color .15s ease, border-color .15s ease, box-shadow .15s ease; }\n    #tt-cart-root .tt-btn:hover { background: var(--tt-accent); color: #fff; border-color: var(--tt-accent); }\n    #tt-cart-root .tt-btn-primary { background: var(--tt-accent); color: #fff; }\n    #tt-cart-root .tt-btn-primary:hover { background: var(--tt-accent-hover); }\n    #tt-cart-root .tt-btn-ghost { background: transparent; }\n    #tt-cart-root .tt-btn-link { border: 0; background: transparent; color: var(--tt-accent); padding: 6px 10px; border-radius: 12px; }\n    #tt-cart-root .tt-btn-link:hover { background: rgba(10,136,85,.08); color: var(--tt-accent); }\n    #tt-cart-root .tt-btn-remove{ background:#0a8855; color:#fff; border:1px solid #0a8855; }\n    #tt-cart-root .tt-btn-remove:hover{ background:#cc0000; border-color:#cc0000; color:#fff; }\n    #tt-login-modal { display:none; position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:9999; align-items:center; justify-content:center; padding: 16px; }\n    #tt-login-modal .tt-card { background:#fff; border-radius:16px; padding:20px; max-width:480px; width:100%; box-shadow:0 10px 30px rgba(0,0,0,.18); border: 1px solid var(--tt-muted); }\n    #tt-login-modal h3 { margin: 0 0 14px; font-weight: 800; color: inherit; }\n    #tt-login-modal form p { margin: 0 0 12px; }\n    #tt-login-modal label { display:block; margin-bottom:6px; font-weight:600; }\n    #tt-login-modal input[type=\"text\"], #tt-login-modal input[type=\"password\"]{ width:100%; padding:10px 12px; border:1px solid #e2e8f0; border-radius:12px; background:#fff; transition:border-color .15s ease, box-shadow .15s ease; }\n    #tt-login-modal input[type=\"text\"]:focus, #tt-login-modal input[type=\"password\"]:focus{ outline:none; border-color: var(--tt-accent); box-shadow: 0 0 0 2px rgba(10,136,85,.2); }\n    #tt-login-modal .button, #tt-login-modal #tt-login-close{ display:inline-flex; align-items:center; justify-content:center; padding:10px 16px; border-radius:9999px; border:1px solid var(--tt-accent); background: transparent; color: var(--tt-accent); cursor:pointer; transition: background .15s ease, color .15s ease, border-color .15s ease; }\n    #tt-login-modal .button:hover, #tt-login-modal #tt-login-close:hover{ background: var(--tt-accent); color:#fff; }\n    #tt-login-modal .tt-modal-actions{ text-align:right; margin-top:12px; display:flex; gap:10px; justify-content:flex-end; flex-wrap:wrap; }\n    #tt-login-modal .tt-pass-wrap { position: relative; }\n    #tt-login-modal input[type=\"password\"].tt-has-eye { padding-right: 42px; }\n    #tt-login-modal .tt-eye { position:absolute; right:10px; top:50%; transform:translateY(-50%); border:0; background:transparent; padding:6px; cursor:pointer; opacity:.7; }\n    #tt-login-modal .tt-eye:hover { opacity:1; }\n    #tt-login-modal .tt-eye svg { width:20px; height:20px; display:block; }\n    #tt-login-modal .tt-eye.on { opacity:1; }\n    @media (max-width: 600px){\n      #tt-cart-root thead { display:none; }\n      #tt-cart-root table, #tt-cart-root tbody, #tt-cart-root tr, #tt-cart-root td { display:block; width:100%; }\n      #tt-cart-root tbody td { border-bottom: 0; padding: 10px 12px; }\n      #tt-cart-root tbody tr { border:1px solid var(--tt-muted); border-radius:12px; margin-bottom:10px; overflow:hidden; }\n      #tt-cart-root .tt-cart-table { border:0; }\n    }\n  <\/style>\n\n  <div id=\"tt-cart-root\">\n    <h2>Carrito<\/h2>\n    <div id=\"tt-cart-empty\" style=\"display:none;\">Tu Carrito esta vac\u00edo.<\/div>\n    <div id=\"tt-cart-groups\"><\/div>\n    <div id=\"tt-cart-grand\"><\/div>\n    <div id=\"tt-cart-warning\"><\/div>\n    <div class=\"tt-actions\">\n      <button id=\"tt-cart-checkout\" type=\"button\" class=\"tt-btn tt-btn-primary\">Pagar<\/button>\n      <button id=\"tt-cart-clear\" type=\"button\" class=\"tt-btn tt-btn-ghost\">Vaciar Carrito<\/button>\n    <\/div>\n  <\/div>\n\n    <div id=\"tt-login-modal\">\n    <div class=\"tt-card\">\n      <h3>Requiere Iniciar Sesi\u00f3n<\/h3>\n      <form name=\"loginform\" id=\"loginform\" action=\"https:\/\/teetimespain.com\/wp-login.php\" method=\"post\"><p class=\"login-username\">\n\t\t\t\t<label for=\"user_login\">Nombre de usuario o correo electr\u00f3nico<\/label>\n\t\t\t\t<input type=\"text\" name=\"log\" id=\"user_login\" autocomplete=\"username\" class=\"input\" value=\"\" size=\"20\" \/>\n\t\t\t<\/p><p class=\"login-password\">\n\t\t\t\t<label for=\"user_pass\">Contrase\u00f1a<\/label>\n\t\t\t\t<input type=\"password\" name=\"pwd\" id=\"user_pass\" autocomplete=\"current-password\" spellcheck=\"false\" class=\"input\" value=\"\" size=\"20\" \/>\n\t\t\t<\/p><p class=\"login-remember\"><label><input name=\"rememberme\" type=\"checkbox\" id=\"rememberme\" value=\"forever\" \/> Recu\u00e9rdame<\/label><\/p><p class=\"login-submit\">\n\t\t\t\t<input type=\"submit\" name=\"wp-submit\" id=\"wp-submit\" class=\"button button-primary\" value=\"Iniciar Sesi\u00f3n\" \/>\n\t\t\t\t<input type=\"hidden\" name=\"redirect_to\" value=\"https:\/\/teetimespain.com\/es\/carrito\/\" \/>\n\t\t\t<\/p><\/form>      <div class=\"tt-modal-actions\">\n        <button id=\"tt-login-close\" type=\"button\">Cerrar<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <script>\n  (function(){\n    const GROUPS = document.getElementById('tt-cart-groups');\n    const EMPTY  = document.getElementById('tt-cart-empty');\n    const GRAND  = document.getElementById('tt-cart-grand');\n    const WARN   = document.getElementById('tt-cart-warning');\n    const BTN_CH = document.getElementById('tt-cart-checkout');\n    const BTN_CL = document.getElementById('tt-cart-clear');\n    const MODAL  = document.getElementById('tt-login-modal');\n    const BTN_MC = document.getElementById('tt-login-close');\n    const LOGGED = false;\n\n    function loadCart(){ try{ return JSON.parse(localStorage.getItem('ttCartItems')||'[]'); }catch(e){ return []; } }\n    function saveCart(a){ localStorage.setItem('ttCartItems', JSON.stringify(a||[])); }\n    function money(n){ const x=(typeof n==='number'&&!Number.isNaN(n))?n:0; return x.toFixed(2)+' \u20ac'; }\n    function extrasToText(c){\n      if(!c||typeof c!=='object') return '';\n      const m=[['buggy','Buggy'],['carro_manual','Trolley'],['carro_electrico','Electric Trolley'],['palos_zurdo','Left-handed clubs'],['palos_diestro','Right-handed clubs'],['special_2p_buggy','Special 2P + Buggy'],['holes9','9 Holes'],];\n      const parts=[]; for(const [k,l] of m){ const q=Number(c[k]||0); if(q>0) parts.push(l+' x'+q); } return parts.join(', ');\n    }\n    function groupByCourse(items){\n      const map=new Map();\n      for(const it of items){\n        const id=(it.campo&&it.campo.id)?it.campo.id:'unknown';\n        const nom=(it.campo&&it.campo.nombre)?it.campo.nombre:'\u2014';\n        if(!map.has(id)) map.set(id,{id,nombre:nom,items:[],subtotal:0});\n        const g=map.get(id); g.items.push(it); if(typeof it.total==='number') g.subtotal+=it.total;\n      }\n      return Array.from(map.values());\n    }\n\n    function setupPasswordToggle(){\n      const pass = MODAL.querySelector('input[type=\"password\"]');\n      if (!pass || pass.dataset.ttEye) return;\n      pass.classList.add('tt-has-eye');\n      pass.dataset.ttEye = '1';\n      const wrap = document.createElement('div');\n      wrap.className = 'tt-pass-wrap';\n      pass.parentNode.insertBefore(wrap, pass);\n      wrap.appendChild(pass);\n      const btn = document.createElement('button');\n      btn.type = 'button';\n      btn.className = 'tt-eye';\n      btn.setAttribute('aria-label', 'Mostrar contrase\u00f1a');\n      btn.innerHTML = `<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M12 5c-5 0-9 4.5-10 7 1 2.5 5 7 10 7s9-4.5 10-7c-1-2.5-5-7-10-7zm0 12a5 5 0 1 1 0-10 5 5 0 0 1 0 10z\"><\/path><\/svg>`;\n      wrap.appendChild(btn);\n      btn.addEventListener('click', ()=>{\n        const isText = pass.type === 'text';\n        pass.type = isText ? 'password' : 'text';\n        btn.classList.toggle('on', !isText);\n        btn.setAttribute('aria-label', isText ? 'Mostrar contrase\u00f1a' : 'Ocultar contrase\u00f1a');\n      });\n    }\n\n    function render(){\n      const items=loadCart();\n      if(!items.length){ EMPTY.style.display=''; GROUPS.innerHTML=''; GRAND.textContent=''; WARN.innerHTML=''; return; }\n      EMPTY.style.display='none';\n      const groups=groupByCourse(items);\n      let html=''; let grand=0; let hasPendingPayment=false;\n\n      for(const g of groups){\n        grand+=g.subtotal;\n        html+='<section class=\"tt-cart-group\" style=\"margin:18px 0;\">';\n        html+='<h3>'+(g.nombre||'\u2014')+'<\/h3>';\n        html+='<div class=\"tt-cart-table\"><table>';\n        html+='<thead><tr>';\n        html+='<th>Date<\/th><th>Hour<\/th><th>Players<\/th><th>Extras<\/th><th>Total<\/th><th style=\"width:1%; white-space:nowrap;\"><\/th>';\n        html+='<\/tr><\/thead><tbody>';\n\n        for(const it of g.items){\n          const ex=extrasToText(it.cantidades);\n          const pending = Array.isArray(it.pendingItems) ? it.pendingItems : [];\n          html+='<tr>';\n          html+='<td>'+(it.fecha||'')+'<\/td>';\n          html+='<td>'+(it.hora||'')+'<\/td>';\n          html+='<td>'+(it.jugadores||'')+'<\/td>';\n          html+='<td>'+(ex||'\u2014')+'<\/td>';\n          html+='<td>'+(it.totalTexto||(typeof it.total==='number'?money(it.total):''))+'<\/td>';\n          html+='<td style=\"text-align:right;\"><button type=\"button\" class=\"tt-btn tt-btn-remove tt-cart-del\" data-id=\"'+it.id+'\">Remove<\/button><\/td>';\n          html+='<\/tr>';\n          if (pending.length){\n            hasPendingPayment = true;\n            html+='<tr><td colspan=\"6\" style=\"background:#fff5f5; padding:10px 14px; font-size:14px; line-height:1.5em;\">'\n                 + '<span class=\"tt-cart-item-alert\">Pending payment: ' + pending.join(', ') + '. These products are not included in the amount paid now. Their price will be confirmed later and charged separately.<\/span>'\n                 + '<\/td><\/tr>';\n          }\n  \/\/ === Mostrar detalles de hotel o experiencia ===\nif(it.detalles){\n  html+='<tr><td colspan=\"6\" style=\"background:#fafafa; padding:10px 14px; font-size:14px; line-height:1.5em;\">'\n       + it.detalles +\n       '<\/td><\/tr>';\n}\n\n        }\n\n        html+='<\/tbody><\/table><\/div>';\n        html+='<div class=\"tt-cart-sub\">Subtotal ('+(g.nombre||'\u2014')+'): '+money(g.subtotal)+'<\/div>';\n        html+='<\/section>';\n      }\n\n      GROUPS.innerHTML=html;\n      GRAND.textContent='Total cart: '+money(grand);\n      WARN.innerHTML = hasPendingPayment\n        ? '<div class=\"tt-cart-alert\">Warning: there are products with pending payment in your cart. They are not included in the amount paid now because their availability must be confirmed first. We will claim that amount later once availability have been confirmed by the golf course.<\/div>'\n        : '';\n\n      GROUPS.querySelectorAll('.tt-cart-del').forEach(btn=>{\n        btn.addEventListener('click', ()=>{\n          const id=btn.getAttribute('data-id');\n          const rest=loadCart().filter(x=>String(x.id)!==String(id));\n          saveCart(rest); render();\n        });\n      });\n    }\n\n    BTN_CL.addEventListener('click', ()=>{\n      if(confirm('Empty cart?')){ saveCart([]); render(); }\n    });\n\nBTN_CH.addEventListener('click', ()=>{\n      const items=loadCart();\n      if(!items.length){ alert('Your cart is empty.'); return; }\n      if(!LOGGED){ MODAL.style.display='flex'; setupPasswordToggle(); return; }\n      const groups=groupByCourse(items); const grand=groups.reduce((s,g)=>s+g.subtotal,0);\n      document.dispatchEvent(new CustomEvent('tt:checkout:ready',{ detail:{ items, groups, grandTotal:grand } }));\n    });\n\n    BTN_MC.addEventListener('click', ()=>{ MODAL.style.display='none'; });\n\n    render();\n  })();\n  \n\/\/ === Listener real de checkout \u2192 crea sesi\u00f3n y redirige a Stripe ===\nconst TT_AJAX_URL = 'https:\/\/teetimespain.com\/wp-admin\/admin-ajax.php';\ndocument.addEventListener('tt:checkout:ready', async function(){\n  \/\/ Definimos el bot\u00f3n y los textos\n  const payButton = document.getElementById('tt-cart-checkout');\n  const originalText = 'Pay';\n  const loadingText = 'Processing...';\n\n  try{\n    \/\/ --- A\u00d1ADIDO: Mostrar estado de carga ---\n    if (payButton) {\n      payButton.disabled = true;\n      payButton.textContent = loadingText;\n    }\n    \/\/ --- FIN A\u00d1ADIDO ---\n\n    const items = JSON.parse(localStorage.getItem('ttCartItems')||'[]');\n    if(!items.length){\n      alert('Your cart is empty.');\n      \/\/ --- A\u00d1ADIDO: Resetear bot\u00f3n si hay error ---\n      if (payButton) {\n        payButton.disabled = false;\n        payButton.textContent = originalText;\n      }\n      \/\/ --- FIN A\u00d1ADIDO ---\n      return;\n    }\n    let total = 0;\n    items.forEach(i=>{ if(typeof i.total==='number') total += i.total; });\n\n    const payload = { items, total };\n\nconst res = await fetch(TT_AJAX_URL, {\n  method:'POST',\n  headers:{ 'Content-Type':'application\/x-www-form-urlencoded' },\n  credentials: 'same-origin', \/\/ <-- \u00a1ESTA ES LA CORRECCI\u00d3N!\n  body:'action=tt_create_checkout&payload=' + encodeURIComponent(JSON.stringify(payload))\n});\n    const data = await res.json();\n\n    if(!data || !data.success || !data.data || !data.data.url){\n      alert((data && data.data && data.data.msg) ? data.data.msg : 'Stripe error \/ Error con Stripe.');\n      \/\/ --- A\u00d1ADIDO: Resetear bot\u00f3n si hay error ---\n      if (payButton) {\n        payButton.disabled = false;\n        payButton.textContent = originalText;\n      }\n      \/\/ --- FIN A\u00d1ADIDO ---\n      return;\n    }\n\n    \/\/ Si todo va bien, redirige (no hace falta resetear el bot\u00f3n)\n    window.location.href = data.data.url;\n\n  }catch(e){\n    alert('Unexpected error \/ Error inesperado.');\n    \/\/ --- A\u00d1ADIDO: Resetear bot\u00f3n si hay error (en catch) ---\n    if (payButton) {\n      payButton.disabled = false;\n      payButton.textContent = originalText;\n    }\n    \/\/ --- FIN A\u00d1ADIDO ---\n  }\n});\n<\/script>\n  <\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-71e771d e-flex e-con-boxed e-con e-parent\" data-id=\"71e771d\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-7c9f061 elementor-widget elementor-widget-spacer\" data-id=\"7c9f061\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-1976","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/teetimespain.com\/es\/wp-json\/wp\/v2\/pages\/1976","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/teetimespain.com\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/teetimespain.com\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/teetimespain.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/teetimespain.com\/es\/wp-json\/wp\/v2\/comments?post=1976"}],"version-history":[{"count":44,"href":"https:\/\/teetimespain.com\/es\/wp-json\/wp\/v2\/pages\/1976\/revisions"}],"predecessor-version":[{"id":2370,"href":"https:\/\/teetimespain.com\/es\/wp-json\/wp\/v2\/pages\/1976\/revisions\/2370"}],"wp:attachment":[{"href":"https:\/\/teetimespain.com\/es\/wp-json\/wp\/v2\/media?parent=1976"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/teetimespain.com\/es\/wp-json\/wp\/v2\/categories?post=1976"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/teetimespain.com\/es\/wp-json\/wp\/v2\/tags?post=1976"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}