{"id":1278,"date":"2025-03-26T19:09:38","date_gmt":"2025-03-26T18:09:38","guid":{"rendered":"https:\/\/zabalimp.es\/?page_id=1278"},"modified":"2025-04-01T11:16:07","modified_gmt":"2025-04-01T10:16:07","slug":"makeorder","status":"publish","type":"page","link":"https:\/\/zabalimp.es\/en\/makeorder\/","title":{"rendered":"MakeOrder"},"content":{"rendered":"<div data-elementor-type=\"wp-page\" data-elementor-id=\"1278\" class=\"elementor elementor-1278\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-d7c3c2a e-flex e-con-boxed e-con e-parent\" data-id=\"d7c3c2a\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-dceae92 elementor-widget__width-initial elementor-widget elementor-widget-html\" data-id=\"dceae92\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div id=\"resumen-seleccionado\" class=\"resumen-servicio\"><\/div>\r\n\r\n<div id=\"step-container\">\r\n  <h2>Selecciona un servicio<\/h2>\r\n  <div id=\"step-content\" class=\"grid\"><\/div>\r\n<\/div>\r\n<div id=\"form-field-dinamico\"><\/div>\r\n<div id=\"option_price\"><\/div>\r\n<div class=\"elementor-field-group\">\r\n  <button id=\"atras\" type=\"button\" class=\"elementor-button elementor-size-sm\">\r\n    Atras\r\n  <\/button>\r\n<\/div>\r\n\r\n<div id=\"pedir-wrapper\" style=\"display: none; text-align: center; margin-top: 20px;\">\r\n  <button id=\"btn-pedir\" class=\"btn-pedir-custom\">\ud83d\uded2 Order<\/button>\r\n<\/div>\r\n\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-236d8c8 elementor-widget elementor-widget-html\" data-id=\"236d8c8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script> \r\nlet selected = {};\r\n\r\ndocument.addEventListener(\"DOMContentLoaded\", function () {\r\n  const container = document.getElementById(\"step-container\");\r\n  const btnAtras = document.getElementById(\"atras\");\r\n  let currentStep = \"servicio\";\r\n\r\n  loadOptions(\"servicio\");\r\n\r\n  btnAtras.addEventListener(\"click\", function () {\r\n    const dinamico = document.getElementById(\"form-field-dinamico\");\r\n    const precioField = document.getElementById(\"option_price\");\r\n    const resumen = document.getElementById(\"resumen-seleccionado\");\r\n\r\n    if (currentStep === \"parametros\") {\r\n      currentStep = \"servicio\";\r\n      loadOptions(\"servicio\");\r\n      selected = {};\r\n      document.getElementById(\"pedir-wrapper\").style.display = \"none\";\r\n      btnAtras.textContent = \"Atr\u00e1s\";\r\n      if (dinamico) dinamico.innerHTML = \"\";\r\n      if (resumen) resumen.innerHTML = \"\";\r\n      if (precioField) precioField.textContent = \"\";\r\n\r\n    } else if (currentStep === \"categoria\") {\r\n      currentStep = \"subservicio\";\r\n      loadOptions(\"subservicio\", selected.servicio.id);\r\n\r\n    } else if (currentStep === \"subservicio\") {\r\n      currentStep = \"servicio\";\r\n      loadOptions(\"servicio\");\r\n    }\r\n  });\r\n\r\n  function loadOptions(step, parentId = null) {\r\n    if (btnAtras) {\r\n      btnAtras.classList.toggle(\"hide\", step === \"servicio\");\r\n      btnAtras.classList.toggle(\"show\", step !== \"servicio\");\r\n    }\r\n\r\n    let url;\r\n    if (step === \"servicio\") {\r\n      container.querySelector(\"h2\").textContent = \"Selecciona un servicio\";\r\n      url = \"\/wp-json\/miapi\/v1\/servicios\";\r\n    } else if (step === \"subservicio\") {\r\n      container.querySelector(\"h2\").textContent = \"Selecciona una subservicios\";\r\n      url = `\/wp-json\/miapi\/v1\/subservicios?servicio=${parentId}`;\r\n    }\r\n\r\n    fetch(url)\r\n      .then(res => res.json())\r\n      .then(data => {\r\n        transitionCards(data, item => handleClick(step, item));\r\n      });\r\n  }\r\n\r\n    function handleClick(step, item) {\r\n      if (step === \"servicio\") {\r\n        selected.servicio = item;\r\n        currentStep = \"subservicio\";\r\n        loadOptions(\"subservicio\", item.id);\r\n    \r\n      } else if (step === \"subservicio\") {\r\n        selected.subservicio = item;\r\n        currentStep = \"parametros\";\r\n        cargarParametros(item.id); \/\/ \u2b05\ufe0f \u0431\u0435\u0437 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438\r\n      }\r\n\r\n\r\n  }\r\n\r\n  function transitionCards(items, onClickHandler) {\r\n    const content = document.getElementById(\"step-content\");\r\n    if (!content) return;\r\n\r\n    const oldCards = content.querySelectorAll(\".card-option\");\r\n    oldCards.forEach(card => {\r\n      card.classList.remove(\"fade-in\");\r\n      card.classList.add(\"fade-out\");\r\n      setTimeout(() => card.remove(), 300);\r\n    });\r\n\r\n    setTimeout(() => {\r\n      items.forEach(item => {\r\n        const fileName = normalizeFileName(item.name);\r\n        const div = document.createElement(\"div\");\r\n        div.className = \"card-option fade-in\";\r\n        div.innerHTML = `<img decoding=\"async\" src=\"https:\/\/zabalimp.es\/wp-content\/uploads\/2025\/03\/${fileName}.png\" alt=\"${item.name}\" \/>`;\r\n        div.addEventListener(\"click\", () => onClickHandler(item));\r\n        content.appendChild(div);\r\n      });\r\n    content.scrollIntoView({ behavior: 'smooth', block: 'start' });\r\n    }, 300);\r\n  }\r\n\r\n  function normalizeFileName(name) {\r\n    const map = {\r\n      '\u00e1': 'a', '\u00e9': 'e', '\u00ed': 'i', '\u00f3': 'o',\r\n      '\u00fa': 'u', '\u00fc': 'u', '\u00f1': 'n',\r\n      '\u00c1': 'A', '\u00c9': 'E', '\u00cd': 'I', '\u00d3': 'O',\r\n      '\u00da': 'U', '\u00dc': 'U', '\u00d1': 'N'\r\n    };\r\n\r\n    return name\r\n      .split('').map(c => map[c] || c)\r\n      .join('').replace(\/\\s+\/g, '-').replace(\/[^\\w\\-]\/g, '');\r\n  }\r\n});\r\n\r\nfunction cargarParametros(catId) {\r\n    document.getElementById(\"pedir-wrapper\").style.display = \"block\";\r\n\r\n  const dinamico = document.getElementById(\"form-field-dinamico\");\r\n  const precioField = document.getElementById(\"option_price\");\r\n  const container = document.getElementById(\"step-content\");\r\n  const btnAtras = document.getElementById(\"atras\");\r\n\r\n  container.innerHTML = \"\";\r\n\r\n  fetch(`\/wp-json\/miapi\/v1\/parametros?subservicio=${selected.subservicio.id}`)\r\n\r\n    .then(res => res.json())\r\n    .then(async data => {\r\n      dinamico.innerHTML = \"\";\r\n      precioField.textContent = \"\";\r\n      if (btnAtras) btnAtras.textContent = \"Cancelar\";\r\n\r\n      for (const item of data) {\r\n        const inputName = \"campo_\" + item.id;\r\n        const priceData = await fetch(`\/wp-json\/miapi\/v1\/option-price?id=${item.id}`)\r\n          .then(r => r.json())\r\n          .catch(() => null);\r\n\r\n        const base = parseFloat(priceData?.base_price || 0);\r\n        const unit = priceData?.unit || \"servicio\";\r\n\r\n        const group = document.createElement(\"div\");\r\n        group.className = \"parametro-group\";\r\n\r\n        const baseWrapper = document.createElement(\"label\");\r\n        baseWrapper.className = \"checkbox-wrapper\";\r\n\r\n        const baseCheckbox = document.createElement(\"input\");\r\n        baseCheckbox.type = \"checkbox\";\r\n        baseCheckbox.name = `${inputName}_base`;\r\n        baseCheckbox.dataset.baseValue = base;\r\n        baseCheckbox.addEventListener(\"change\", updatePrecioYResumen);\r\n\r\n        const baseText = document.createElement(\"span\");\r\n\r\n        if (base > 0) {\r\n          baseText.textContent = `${item.name} (base: ${base.toFixed(2)} \u20ac \/ ${unit})`;\r\n        } else if (parseFloat(priceData?.price_per_unit || 0) > 0) {\r\n          baseText.textContent = `${item.name} (precio por ${unit}: ${priceData.price_per_unit} \u20ac)`;\r\n        } else {\r\n          baseText.textContent = item.name;\r\n        }\r\n\r\n        baseWrapper.appendChild(baseCheckbox);\r\n        baseWrapper.appendChild(baseText);\r\n        group.appendChild(baseWrapper);\r\n\r\n        const modContainer = document.createElement(\"div\");\r\n        modContainer.className = \"mod-container\";\r\n        modContainer.style.marginLeft = \"16px\";\r\n        modContainer.style.display = \"none\";\r\n\r\n        const modifiers = (priceData?.value_modifier || \"\")\r\n          .split(\";\")\r\n          .map(s => s.trim().split(\":\"))\r\n          .filter(([key, val]) => key && val !== undefined && key.toLowerCase() !== \"no\" && parseFloat(val) !== 0);\r\n\r\n        if (modifiers.length > 2) {\r\n          const select = document.createElement(\"select\");\r\n          select.name = `${inputName}_select`;\r\n          modifiers.forEach(([labelText, modValue]) => {\r\n            const mod = parseFloat(modValue);\r\n            const opt = document.createElement(\"option\");\r\n            opt.value = labelText;\r\n            opt.text = `${labelText} (+${mod.toFixed(2)} \u20ac)`;\r\n            select.appendChild(opt);\r\n          });\r\n          select.addEventListener(\"change\", updatePrecioYResumen);\r\n          modContainer.appendChild(select);\r\n        } else {\r\n          modifiers.forEach(([labelText, modValue], i) => {\r\n            const wrapper = document.createElement(\"label\");\r\n            wrapper.className = \"checkbox-wrapper\";\r\n            const checkbox = document.createElement(\"input\");\r\n            checkbox.type = \"checkbox\";\r\n            checkbox.name = `${inputName}_mod_${i}`;\r\n            checkbox.dataset.modifierValue = parseFloat(modValue);\r\n            checkbox.addEventListener(\"change\", updatePrecioYResumen);\r\n            const span = document.createElement(\"span\");\r\n            span.textContent = `${labelText} (+${parseFloat(modValue).toFixed(2)} \u20ac)`;\r\n            wrapper.appendChild(checkbox);\r\n            wrapper.appendChild(span);\r\n            modContainer.appendChild(wrapper);\r\n          });\r\n        }\r\n        if (!priceData?.value_modifier && priceData?.price_per_unit > 0) {\r\n          const inputNum = document.createElement(\"input\");\r\n          inputNum.type = \"number\";\r\n          inputNum.name = inputName;\r\n          inputNum.min = \"0\";\r\n          inputNum.step = \"1\";\r\n          inputNum.placeholder = `Cantidad en ${unit}`;\r\n        \r\n          inputNum.addEventListener(\"input\", updatePrecioYResumen);\r\n          inputNum.addEventListener(\"change\", updatePrecioYResumen);\r\n        \r\n          group.appendChild(inputNum);\r\n        }\r\n\r\n        group.appendChild(modContainer);\r\n        dinamico.appendChild(group);\r\n\r\n        baseCheckbox.addEventListener(\"change\", () => {\r\n          modContainer.style.display = baseCheckbox.checked ? \"block\" : \"none\";\r\n        });\r\n      }\r\n\r\n      updatePrecioYResumen();\r\n    });\r\n}\r\n\r\nfunction updatePrecioYResumen() {\r\n  const inputs = document.querySelectorAll(\"#form-field-dinamico input, #form-field-dinamico select\");\r\n  const resumen = document.getElementById(\"resumen-seleccionado\");\r\n  const precioField = document.getElementById(\"option_price\");\r\n\r\n  let total = 0;\r\n  const partes = [];\r\n  const detalles = [];\r\n\r\n  let html = \"<h4>\ud83d\udcdd Tu selecci\u00f3n:<\/h4><ul>\";\r\n  if (selected.servicio) html += `<li><strong>Servicio:<\/strong> ${selected.servicio.name}<\/li>`;\r\n  if (selected.subservicio) html += `<li><strong>Subservicio:<\/strong> ${selected.subservicio.name}<\/li>`;\r\n\r\n  const promesas = Array.from(inputs).map(el => {\r\n    const name = el.name;\r\n\r\n    if (name.includes(\"_base\")) {\r\n      if (el.checked) {\r\n        const baseVal = parseFloat(el.dataset.baseValue || 0);\r\n        partes.push(baseVal.toFixed(2));\r\n        if (baseVal > 0) {\r\n          const label = el.closest(\".parametro-group\")?.querySelector(\"label\")?.innerText?.split(\"(\")[0].trim() || name;\r\n          detalles.push(`${label} (base: ${baseVal.toFixed(2)} \u20ac)`);\r\n        }\r\n\r\n        total += baseVal;\r\n      }\r\n      return 0;\r\n    }\r\n\r\n    if (name.includes(\"_mod_\")) {\r\n      const relatedBase = document.querySelector(`[name^=\"${name.split(\"_mod_\")[0]}_base\"]`);\r\n      if (!relatedBase?.checked) return 0;\r\n      if (el.checked && el.dataset.modifierValue !== undefined) {\r\n        const val = parseFloat(el.dataset.modifierValue || 0);\r\n        partes.push(val.toFixed(2));\r\n        const label = el.closest(\".parametro-group\")?.querySelector(\"label\")?.innerText?.split(\"(\")[0].trim() || name;\r\n            detalles.push(`${label} \u2013 ${el.value || ''} (+${val.toFixed(2)} \u20ac)`);\r\n\r\n        total += val;\r\n      }\r\n      return 0;\r\n    }\r\n\r\n    if (name.includes(\"_select\")) {\r\n      const relatedBase = document.querySelector(`[name^=\"${name.split(\"_select\")[0]}_base\"]`);\r\n      if (!relatedBase?.checked) return 0;\r\n\r\n      const value = el.value;\r\n      const id = parseInt(name.replace(\"campo_\", \"\").split(\"_\")[0]);\r\n      return fetch(`\/wp-json\/miapi\/v1\/option-price?id=${id}`)\r\n        .then(r => r.json())\r\n        .then(p => {\r\n          const base = parseFloat(p.base_price || 0);\r\n          const mod = parseModifier(p.value_modifier, value);\r\n          const suma = base + mod;\r\n          partes.push(suma.toFixed(2));\r\n            let detalle = `${value}`;\r\n            if (base > 0 || mod !== 0) {\r\n              const partesTexto = [];\r\n              if (base > 0) partesTexto.push(`${base.toFixed(2)} \u20ac base`);\r\n              if (mod !== 0) partesTexto.push(`${mod.toFixed(2)} \u20ac extra`);\r\n              detalle += ` (${partesTexto.join(\" + \")} = ${suma.toFixed(2)} \u20ac)`;\r\n            }\r\n            detalles.push(detalle);\r\n\r\n          total += suma;\r\n        })\r\n        .catch(() => 0);\r\n    }\r\n\r\n        if (el.type === \"number\") {\r\n          const id = parseInt(name.replace(\"campo_\", \"\").split(\"_\")[0]);\r\n          const cantidad = parseFloat(el.value || 0);\r\n          if (isNaN(cantidad) || cantidad <= 0) return 0;\r\n        \r\n          return fetch(`\/wp-json\/miapi\/v1\/option-price?id=${id}`)\r\n            .then(r => r.json())\r\n            .then(p => {\r\n              if (!p.value_modifier && p.price_per_unit > 0) {\r\n                const precio = cantidad * parseFloat(p.price_per_unit);\r\n                partes.push(precio.toFixed(2));\r\n            const label = el.closest(\".parametro-group\")?.querySelector(\"label\")?.innerText?.split(\"(\")[0].trim() || name;\r\n            detalles.push(`${label}: ${cantidad} \u00d7 ${p.price_per_unit} \u20ac = ${precio.toFixed(2)} \u20ac`);\r\n\r\n                total += precio;\r\n                return precio;\r\n              }\r\n              return 0;\r\n            })\r\n            .catch(() => 0);\r\n        }\r\n\r\n    return 0;\r\n  }\r\n  );\r\n\r\n  Promise.all(promesas).then(() => {\r\n    const desglose = partes.filter(p => parseFloat(p) > 0).join(\" + \");\r\n    if (precioField) precioField.textContent = `\ud83d\udfe9 Total: ${desglose} = ${total.toFixed(2)} \u20ac`;\r\n\r\n    if (resumen) {\r\n      if (detalles.length) {\r\n        html += \"<\/ul><h4>\ud83e\udd70 Opciones:<\/h4><ul>\";\r\n        detalles.forEach(d => html += `<li>${d}<\/li>`);\r\n      }\r\n      html += `<\/ul><div class=\"total\"  id=\"resumen-total\">\ud83d\udfe9 Total: ${total.toFixed(2)} \u20ac<\/div>`;\r\n      resumen.innerHTML = html;\r\n    const resumenBox = document.getElementById(\"resumen-seleccionado\");\r\n    const totalElement = document.getElementById(\"resumen-total\");\r\n    \r\n        if (resumenBox && totalElement) {\r\n          resumenBox.scrollTo({\r\n            top: resumenBox.scrollHeight,\r\n            behavior: \"smooth\"\r\n          });\r\n        \r\n          \/\/ \ud83d\udd25 \u041f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0430\r\n          totalElement.classList.add(\"highlight\");\r\n          setTimeout(() => {\r\n            totalElement.classList.remove(\"highlight\");\r\n          }, 1500);\r\n        }\r\n\r\n    }\r\n  });\r\n}\r\n\r\nfunction parseModifier(modifiers, value) {\r\n  if (!modifiers) return 0;\r\n  const pairs = modifiers.split(\";\").map(s => s.trim().split(\":\"));\r\n  const found = pairs.find(([val]) => val === value);\r\n  return found ? parseFloat(found[1] || 0) : 0;\r\n}\r\n\r\n<\/script>\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1fee46b elementor-widget elementor-widget-html\" data-id=\"1fee46b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\r\ndocument.getElementById(\"btn-pedir\").addEventListener(\"click\", function () {\r\n  const resumen = document.getElementById(\"resumen-seleccionado\");\r\n  const precioField = document.getElementById(\"option_price\");\r\n\r\n  if (!selected.servicio || !selected.subservicio) {\r\n    alert(\"Por favor, completa tu selecci\u00f3n.\");\r\n    return;\r\n  }\r\n\r\n  const imagen = `https:\/\/zabalimp.es\/wp-content\/uploads\/2025\/03\/${normalizeFileName(selected.subservicio.name)}.png`;\r\n\r\n  const descripcion = resumen.innerText;\r\n  const precioTexto = precioField.textContent.match(\/([\\d\\.]+) \u20ac$\/);\r\n  const precio = precioTexto ? parseFloat(precioTexto[1]) : 0;\r\n\r\n  const datosPedido = {\r\n    nombre: `${selected.servicio.name} \u2013 ${selected.subservicio.name}`,\r\n    descripcion: descripcion,\r\n    precio: precio,\r\n    imagen: imagen\r\n  };\r\n\r\n  fetch('\/wp-json\/miapi\/v1\/add-to-cart', {\r\n    method: 'POST',\r\n    headers: { 'Content-Type': 'application\/json' },\r\n    body: JSON.stringify(datosPedido)\r\n  })\r\n  .then(res => res.json())\r\n  .then(data => {\r\n    if (data.success) {\r\n      alert(\"\u2705 Producto a\u00f1adido al carrito\");\r\n      window.location.href = \"\/carrito\"; \r\n    } else {\r\n      alert(\"\u274c No se pudo a\u00f1adir al carrito\");\r\n    }\r\n  })\r\n  .catch(err => {\r\n    console.error(\"Error al a\u00f1adir al carrito:\", err);\r\n    alert(\"\u274c Error en el servidor\");\r\n  });\r\n});\r\n\r\nfunction normalizeFileName(name) {\r\n  const map = {\r\n    '\u00e1': 'a', '\u00e9': 'e', '\u00ed': 'i', '\u00f3': 'o',\r\n    '\u00fa': 'u', '\u00fc': 'u', '\u00f1': 'n',\r\n    '\u00c1': 'A', '\u00c9': 'E', '\u00cd': 'I', '\u00d3': 'O',\r\n    '\u00da': 'U', '\u00dc': 'U', '\u00d1': 'N'\r\n  };\r\n\r\n  return name\r\n    .split('')\r\n    .map(c => map[c] || c)\r\n    .join('')\r\n    .replace(\/\\s+\/g, '-')\r\n    .replace(\/[^\\w\\-]\/g, '');\r\n}\r\n<\/script>\r\n\t\t\t\t<\/div>\n\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":"<p>Selecciona un servicio Atras \ud83d\uded2 Pedir<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_joinchat":[],"footnotes":""},"class_list":["post-1278","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/zabalimp.es\/en\/wp-json\/wp\/v2\/pages\/1278","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zabalimp.es\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/zabalimp.es\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/zabalimp.es\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zabalimp.es\/en\/wp-json\/wp\/v2\/comments?post=1278"}],"version-history":[{"count":0,"href":"https:\/\/zabalimp.es\/en\/wp-json\/wp\/v2\/pages\/1278\/revisions"}],"wp:attachment":[{"href":"https:\/\/zabalimp.es\/en\/wp-json\/wp\/v2\/media?parent=1278"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}