// Lógica simple para el contador del carrito let itemCount = 0; const cartCountElement = document.getElementById('cartCount'); document.addEventListener('DOMContentLoaded', function() { // SECCION DE CALENDARIO const fp = flatpickr("#calendarioRango", { mode: "range", inline: true, locale: "es", minDate: "today", dateFormat: "Y-m-d" }); const hInicio = document.getElementById('hInicio'); const hFin = document.getElementById('hFin'); // 2. Llenar selectores con etiquetas AM/PM pero valores en 24h function llenarHoras() { for (let i = 0; i < 24; i++) { let valor24 = i.toString().padStart(2, '0') + ":00"; let ampm = i >= 12 ? 'PM' : 'AM'; let h12 = i % 12 || 12; let label = `${h12}:00 ${ampm}`; hInicio.innerHTML += ``; hFin.innerHTML += ``; } } llenarHoras(); // 3. Sugerencia de +8 horas hInicio.addEventListener('change', function() { let h = parseInt(this.value.split(':')[0]); let nuevaH = (h + 8) % 24; hFin.value = nuevaH.toString().padStart(2, '0') + ":00"; }); // 4. Confirmar y formatear para datetime-local document.getElementById('btnConfirmar').addEventListener('click', function() { const fechas = fp.selectedDates; if (fechas.length < 1) { lanzarAlerta("Please select two dates on the calendar.",'warning'); return; } /* if (fechas.length === 1) { const f1 = fechas[0].toLocaleDateString('sv-SE'); // sv-SE devuelve YYYY-MM-DD const f2 = fechas[0].toLocaleDateString('sv-SE'); // Los inputs datetime-local requieren el formato: YYYY-MM-DDTHH:mm document.getElementById('fechahorainicio').value = `${f1}T${hInicio.value}`; document.getElementById('fechahorafin').value = `${f2}T${hFin.value}`; } else{ // Formato ISO local: YYYY-MM-DD const f1 = fechas[0].toLocaleDateString('sv-SE'); // sv-SE devuelve YYYY-MM-DD const f2 = fechas[1].toLocaleDateString('sv-SE'); // Los inputs datetime-local requieren el formato: YYYY-MM-DDTHH:mm document.getElementById('fechahorainicio').value = `${f1}T${hInicio.value}`; document.getElementById('fechahorafin').value = `${f2}T${hFin.value}`; } */ bootstrap.Modal.getInstance(document.getElementById('modalReserva')).hide(); }); $(document).ready(function() { // 2. Al dar clic en el icono pequeño (Reabrir) $('#btnReabrirCalendario').on('click', function() { if ($('#contenedorCalendario').is(':visible')) { // Si está visible, lo oculta y muestra el resumen $('#contenedorCalendario').slideUp(400, function() { $('#resumenFecha').fadeIn(300); }); } else { // Si está oculto, muestra el calendario y oculta el resumen $('#resumenFecha').fadeOut(300, function() { $('#contenedorCalendario').slideDown(400); }); } }); // Quitar error del input al escribir $('#calendarioRango').on('change', function() { $(this).removeClass('is-invalid'); }); setearComponentesCabecera(); renderizarCarrito() // Opcional: Si cambian las horas después de seleccionar fecha, actualizar cabecera $('#hInicio, #hFin').on('change', function() { const fechaActual = $('#textoFechaRango').text(); const cOde = $('#CUPON').val(); const tYpe = $('#TIPOCUPON').val(); const vAl = $('#DESCUENTO').val(); if(fechaActual !== "-- / -- / --") { guardarCabecera(fechaActual, $('#hInicio').val(), $('#hFin').val(),cOde,tYpe,vAl); } }); var $target = $("#EmailMessage"); // Validamos si el ID existe en la página if ($target.length > 0) { $('html, body').animate({ scrollTop: $target.offset().top }, 800); } //pintarLogCarrito(); validarRangoFecha() }); // Valores iniciales hInicio.value = "08:00"; hInicio.dispatchEvent(new Event('change')); }); function cart_update(items){ let carrito = obtenerCarrito(); items.forEach(product => { //alert(product.id) const existe = carrito.find(item => item.id === product.id); if (existe) { existe.precio = product.precio; existe.existencia = product.existencia; } }); guardarCarrito(carrito); } const STORAGE_KEY = 'ds_jumper_cart'; // 1. LA BASE: Leer directamente del LocalStorage (Nivel 0) function obtenerDatosRaw() { const datos = localStorage.getItem(STORAGE_KEY); const estructuraInicial = { items: [], cabecera: { fecha: "", hInicio: "", hFin: "" }, cupon: { code:"", type:"", val:"" } // Estructura por defecto }; if (!datos) return estructuraInicial; try { const parsed = JSON.parse(datos); // Mezclamos con la estructura inicial para asegurar que cabecera exista return { ...estructuraInicial, ...parsed }; } catch (e) { return estructuraInicial; } } // 2. OBTENER ITEMS: Extrae solo el arreglo de productos function obtenerCarrito() { const data = obtenerDatosRaw(); return data.items || []; } // 3. OBTENER CABECERA: Extrae solo el objeto de fechas/horas function obtenerCabecera() { const data = obtenerDatosRaw(); return data.cabecera || { fecha: "", hInicio: "", hFin: "" }; } // 4. GUARDAR CARRITO (Actualiza solo productos, mantiene cabecera) function guardarCarrito(nuevosItems) { let data = obtenerDatosRaw(); data.items = nuevosItems; localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); renderizarCarrito(); // Solo llama a la UI //pintarLogCarrito(); } // 5. GUARDAR CABECERA (Actualiza periodo, mantiene productos) function guardarCabecera(fecha, hInicio, hFin) { let data = obtenerDatosRaw(); data.cabecera = { fecha: fecha, hInicio: hInicio, hFin: hFin }; localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); } function validar_cupon(){ const valor = $('#cupon').val().trim(); if (valor !=""){ const datos = { IdCupon: valor, }; $.ajax({ url: url_api+'validate_coupon', type: 'POST', contentType: 'application/json', data: JSON.stringify(datos), headers: { 'Authorization': 'Bearer ' + token, 'X-ID-CLIENT': id_client }, success: function(response) { if (response.status != 'error'){ lanzarAlerta(response.Message, 'success'); $('#CUPON').val(response.code); $('#TIPOCUPON').val(response.type); $('#DESCUENTO').val(response.val); guardarCupon(response.code,response.type,response.val) let STotal = $('#checkout_subtotal').text(); STotal = STotal.replace("$", ""); $('#chEtiquetaCupon').text("Descuento ( "+response.code+" )") let Descuento = $('#chDescuento').text(); Descuento = Descuento.replace("$", ""); if (response.type == 'amount'){ Descuento = response.val * 1; } else{ Descuento = STotal * ( response.val / 100 ); } $('#chDescuento').text(`$${Descuento.toFixed(2)}`) let TarjetaRegalo = $('#chTarjetaRegalo').text(); TarjetaRegalo = TarjetaRegalo.replace("$", ""); let Total = $('#checkout_total').text(); //Total = Total.replace("$", ""); Total = STotal - Descuento - TarjetaRegalo; $('#checkout_total').text(`$${Total.toFixed(2)}`) } else{ lanzarAlerta(response.Message, 'error'); } }, error: function(xhr, status, error) { lanzarAlerta(response.Message, 'error'); //console.error('Error:', error); //mostrarError('Error al revalidar el carrito'); } }); } else{ lanzarAlerta("A code is required", 'warning'); } } function guardarCupon(code,type,val) { let data = obtenerDatosRaw(); data.cupon = { code: code, type: type, val: val }; localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); animarCarritoConMensaje('Cupon '); renderizarCarrito(); //pintarLogCarrito(); } // --- 2. AGREGAR ELEMENTO --- function agregarAlCarrito(producto,cantidad) { let carrito = obtenerCarrito(); // Verificar si ya existe para solo sumar cantidad const existe = carrito.find(item => item.id === producto.id); if (existe) { existe.cantidad += cantidad; } else { producto.cantidad = cantidad; carrito.push(producto); } guardarCarrito(carrito); animarCarritoConMensaje('Producto') } function animarCarritoConMensaje(producto) { // Crear elemento de notificación const notificacion = document.createElement('div'); notificacion.textContent = `✓ ${producto} agregado !!`; notificacion.style.cssText = ` position: fixed; top: 20px; right: 20px; background: #ffffff; color: black; padding: 10px 20px; border-radius: 5px; z-index: 9999; opacity: 0; transform: translateY(-20px); transition: all 0.3s ease; `; document.body.appendChild(notificacion); // Animar entrada setTimeout(() => { notificacion.style.opacity = '1'; notificacion.style.transform = 'translateY(0)'; }, 100); // Animar el carrito const cartIcon = document.querySelector('#cartIcon i'); cartIcon.style.transform = 'scale(1.2)'; cartIcon.style.transition = 'transform 0.2s ease'; setTimeout(() => { cartIcon.style.transform = 'scale(1)'; }, 200); // Remover notificación setTimeout(() => { notificacion.style.opacity = '0'; notificacion.style.transform = 'translateY(-20px)'; setTimeout(() => { document.body.removeChild(notificacion); }, 300); }, 2000); } function agregarExtraAItem(itemId, itemRl,Name,Price,Image,Url) { const extra = { id: itemRl, // ID único de tu base de datos (MySQL) nombre: Name, precio: Price, imagen: Image, url: Url }; let carrito = obtenerCarrito(); const item = carrito.find(p => p.id === itemId); if (item) { if (!item.adicionales) item.adicionales = []; // Verificamos si ya tiene este extra específico para no duplicarlo const existeExtra = item.adicionales.find(a => a.id === extra.id); if (!existeExtra) { item.adicionales.push(extra); // GuardarCarrito ya se encarga de actualizar LocalStorage y refrescar la UI guardarCarrito(carrito); animarCarritoConMensaje('Producto') } else { console.log("Este extra ya está incluido en este producto."); } } } // --- 3. INCREMENTAR / DECREMENTAR --- function cambiarCantidad(id, delta) { let carrito = obtenerCarrito(); const item = carrito.find(p => p.id === id); if (item) { if (item.cantidad + delta > item.existencia) return; item.cantidad += delta; // Si la cantidad llega a 0, lo eliminamos if (item.cantidad <= 0) { eliminarDelCarrito(id); } else { guardarCarrito(carrito); } if (typeof actualID !== 'undefined') { MAX_STOCK += (delta * -1) ; $('#stock-val').html(MAX_STOCK); } } } // --- 4. ELIMINAR ELEMENTO --- function eliminarDelCarrito(id) { let carrito = obtenerCarrito(); carrito = carrito.filter(item => item.id !== id); guardarCarrito(carrito); } function eliminarAdicionalDeItem(itemId, adicionalId) { let carrito = obtenerCarrito(); // Buscamos el producto principal asegurando que los IDs coincidan como strings const item = carrito.find(p => String(p.id) === String(itemId)); if (item && item.adicionales) { // Filtramos comparando también como strings para mayor seguridad const totalAntes = item.adicionales.length; item.adicionales = item.adicionales.filter(a => String(a.id) !== String(adicionalId)); // Verificamos si realmente se borró algo antes de guardar if (item.adicionales.length !== totalAntes) { guardarCarrito(carrito); //console.log(`Extra ${adicionalId} eliminado del item ${itemId}`); } else { //console.warn("No se encontró el adicional con ID:", adicionalId); } } } // --- 5. CALCULAR TOTALES (Dinero y Cantidades) --- function obtenerTotales() { const carrito = obtenerCarrito(); const calculos = carrito.reduce((acc, item) => { let precioItem = item.precio; // Sumar precios de adicionales si existen if (item.adicionales) { precioItem += item.adicionales.reduce((sum, ad) => sum + (ad.precio*1), 0); } acc.subtotal += (precioItem * item.cantidad); acc.cantidadTotal += item.cantidad; return acc; }, { subtotal: 0, cantidadTotal: 0 }); return { subtotal: calculos.subtotal, total: calculos.subtotal, // Aquí puedes aplicar impuestos o descuentos si gustas cantidadTotal: calculos.cantidadTotal }; } function renderizarCarrito() { const carrito = obtenerCarrito(); const $contenedor = $('#modalReserva .px-3.pb-4'); // El div donde van los productos const totales = obtenerTotales(); let Descuento = 0; // Limpiar contenedor pero mantener el label $contenedor.html(''); if (carrito.length === 0) { $contenedor.append('
The cart is empty
'); } carrito.forEach(item => { let htmlListaExtras = ''; if (item.adicionales && item.adicionales.length > 0) { // Contenedor con fondo sutil para agrupar los extras del producto htmlListaExtras = 'SELECTED ADD-ONS
'; item.adicionales.forEach(extra => { // Si no tienes imagen para el extra, puedes usar un placeholder o un icono const imgExtra = extra.imagen ? extra.imagen : 'https://via.placeholder.com/35'; htmlListaExtras += `Incluye insumos
${item.existencia <= 0 ? 'Out of stock' : 'Includes supplies'}