|
@@ -12,7 +12,7 @@ let userName = "Cliente";
|
|
|
let userTable = null;
|
|
let userTable = null;
|
|
|
let userToken = null;
|
|
let userToken = null;
|
|
|
// --- Datos de Productos y Carrito ---
|
|
// --- Datos de Productos y Carrito ---
|
|
|
-let products = [];
|
|
|
|
|
|
|
+let Allproducts = [];
|
|
|
let cart = [];
|
|
let cart = [];
|
|
|
let itsEmpty = true;
|
|
let itsEmpty = true;
|
|
|
|
|
|
|
@@ -41,12 +41,14 @@ const chatSuggestionsElement = document.getElementById("chatSuggestions");
|
|
|
|
|
|
|
|
//#region --- Inicialización y Configuracion ---
|
|
//#region --- Inicialización y Configuracion ---
|
|
|
async function initializeApp() {
|
|
async function initializeApp() {
|
|
|
|
|
+ showGlobalLoader("Cargando productos...");
|
|
|
|
|
+ await initializeProducts();
|
|
|
|
|
+ await renderProducts(Allproducts);
|
|
|
|
|
+ setupSearchListener();
|
|
|
updateCartDisplay();
|
|
updateCartDisplay();
|
|
|
|
|
+ setupShoppingCart(userId, userToken, userName);
|
|
|
initializeChat();
|
|
initializeChat();
|
|
|
setupBasicListeners();
|
|
setupBasicListeners();
|
|
|
- showGlobalLoader("Cargando productos...");
|
|
|
|
|
- setupShoppingCart(userId, userToken,userName);
|
|
|
|
|
- await renderProducts();
|
|
|
|
|
showGUI();
|
|
showGUI();
|
|
|
hideGlobalLoader();
|
|
hideGlobalLoader();
|
|
|
|
|
|
|
@@ -58,7 +60,6 @@ async function initializeApp() {
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
function initializeLoginModal() {
|
|
function initializeLoginModal() {
|
|
|
const sessionModal = document.getElementById('sessionModal');
|
|
const sessionModal = document.getElementById('sessionModal');
|
|
|
const loginForm = document.getElementById('loginForm');
|
|
const loginForm = document.getElementById('loginForm');
|
|
@@ -77,8 +78,8 @@ function initializeLoginModal() {
|
|
|
showError("Por favor, completa todos los campos.");
|
|
showError("Por favor, completa todos los campos.");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- try{
|
|
|
|
|
- const {data} = await login(email, pin)
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ const { data } = await login(email, pin)
|
|
|
userToken = data.token;
|
|
userToken = data.token;
|
|
|
userName = data.name;
|
|
userName = data.name;
|
|
|
userId = data.id;
|
|
userId = data.id;
|
|
@@ -91,11 +92,11 @@ function initializeLoginModal() {
|
|
|
sessionModal.classList.add('hidden');
|
|
sessionModal.classList.add('hidden');
|
|
|
|
|
|
|
|
initializeApp();
|
|
initializeApp();
|
|
|
- }catch (error) {
|
|
|
|
|
|
|
+ } catch (error) {
|
|
|
console.error(error)
|
|
console.error(error)
|
|
|
- }
|
|
|
|
|
-})
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
function initializeChat() {
|
|
function initializeChat() {
|
|
|
if (!chatForm) return;
|
|
if (!chatForm) return;
|
|
|
chatForm.addEventListener("submit", (event) => {
|
|
chatForm.addEventListener("submit", (event) => {
|
|
@@ -112,12 +113,41 @@ function initializeChat() {
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
function setupBasicListeners() {
|
|
function setupBasicListeners() {
|
|
|
if (!checkoutButton) return;
|
|
if (!checkoutButton) return;
|
|
|
checkoutButton.addEventListener("click", processOrder);
|
|
checkoutButton.addEventListener("click", processOrder);
|
|
|
initializeRewards();
|
|
initializeRewards();
|
|
|
}
|
|
}
|
|
|
|
|
+function setupSearchListener() {
|
|
|
|
|
+ const searchInput = document.getElementById("searchInput");
|
|
|
|
|
+ if (!searchInput) return;
|
|
|
|
|
+
|
|
|
|
|
+ let debounceTimer;
|
|
|
|
|
+
|
|
|
|
|
+ searchInput.addEventListener("input", () => {
|
|
|
|
|
+ // Limpiar el timer anterior si existe
|
|
|
|
|
+ clearTimeout(debounceTimer);
|
|
|
|
|
+
|
|
|
|
|
+ // Agregar una clase de "buscando" para el feedback visual
|
|
|
|
|
+ productListElement.style.opacity = "0.7";
|
|
|
|
|
+ productListElement.style.transform = "scale(0.98)";
|
|
|
|
|
+ productListElement.style.transition = "opacity 0.2s ease, transform 0.2s ease";
|
|
|
|
|
+
|
|
|
|
|
+ // Debounce de 200ms para evitar muchas llamadas
|
|
|
|
|
+ debounceTimer = setTimeout(() => {
|
|
|
|
|
+ const searchTerm = searchInput.value.toLowerCase();
|
|
|
|
|
+ const finded = Allproducts.filter(product => {
|
|
|
|
|
+ return product.name.toLowerCase().includes(searchTerm) ||
|
|
|
|
|
+ product.description.toLowerCase().includes(searchTerm) ||
|
|
|
|
|
+ (product.type && product.type.toLowerCase().includes(searchTerm)) ||
|
|
|
|
|
+ (product.category && product.category.toLowerCase().includes(searchTerm));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // Renderizar con animación
|
|
|
|
|
+ renderProductsWithAnimation(finded);
|
|
|
|
|
+ }, 200);
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
//#endregion
|
|
//#endregion
|
|
|
//#region ===== Utilidad =====
|
|
//#region ===== Utilidad =====
|
|
|
|
|
|
|
@@ -129,45 +159,172 @@ function formatPrice(price) {
|
|
|
//#endregion
|
|
//#endregion
|
|
|
//#region ===== Productos =====
|
|
//#region ===== Productos =====
|
|
|
|
|
|
|
|
|
|
+async function initializeProducts() {
|
|
|
|
|
+ Allproducts = await getProducts(userToken);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async function createCategories(products) {
|
|
|
|
|
+ let categories = new Set(products.map(product => product.type || "Sin categoría"));
|
|
|
|
|
+ categories = Array.from(categories).sort((a, b) => a.localeCompare(b));
|
|
|
|
|
+
|
|
|
|
|
+ if (!productListElement) return;
|
|
|
|
|
+
|
|
|
|
|
+ const categoryContainers = categories.map(category => {
|
|
|
|
|
+ const container = document.createElement("div");
|
|
|
|
|
+ container.classList.add("category-container");
|
|
|
|
|
+ container.classList.add("mb-8", "p-4");
|
|
|
|
|
+ const title = document.createElement("h2");
|
|
|
|
|
+ title.classList.add("category-title", "text-3xl", "font-bold", "border-b-2", "pb-3", "mb-4");
|
|
|
|
|
+ let titleText = ["a", "e", "i", "o", "u"].includes(category.charAt(category.length - 1).toLowerCase()) ? "s" :
|
|
|
|
|
+ ["á", "é", "í", "ó", "ú"].includes(category.charAt(category.length - 1).toLowerCase()) ? "s" :
|
|
|
|
|
+ category.charAt(category.length - 1).toLowerCase() === "s" ? "" : "es";
|
|
|
|
|
+ title.textContent = category + titleText;
|
|
|
|
|
+ container.appendChild(title);
|
|
|
|
|
+ const productList = document.createElement("div");
|
|
|
|
|
+ productList.classList.add("product-list", "space-y-6");
|
|
|
|
|
+ productList.id = `productList-${category}`;
|
|
|
|
|
+ container.appendChild(productList);
|
|
|
|
|
+ productListElement.appendChild(container);
|
|
|
|
|
+
|
|
|
|
|
+ return { category, container: productList };
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ return categoryContainers;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-async function renderProducts() {
|
|
|
|
|
|
|
+async function renderProducts(products) {
|
|
|
if (!productListElement) return;
|
|
if (!productListElement) return;
|
|
|
|
|
|
|
|
const template = document.getElementById("product-card-template");
|
|
const template = document.getElementById("product-card-template");
|
|
|
if (!template) return;
|
|
if (!template) return;
|
|
|
|
|
|
|
|
productListElement.innerHTML = "";
|
|
productListElement.innerHTML = "";
|
|
|
- console.log("Cargando productos...");
|
|
|
|
|
- products = await getProducts(userToken);
|
|
|
|
|
|
|
|
|
|
- products.forEach(product => {
|
|
|
|
|
- const clone = template.content.cloneNode(true);
|
|
|
|
|
|
|
+ const categoryContainers = await createCategories(products);
|
|
|
|
|
|
|
|
- clone.querySelector(".product-type").textContent = product.type || "Sin categoría";
|
|
|
|
|
- clone.querySelector(".product-name").textContent = product.name;
|
|
|
|
|
- clone.querySelector(".product-description").textContent = product.description;
|
|
|
|
|
- clone.querySelector(".product-price").textContent = formatPrice(product.price);
|
|
|
|
|
- clone.querySelector(".product-image").style.backgroundImage = `url('${product.image}')`;
|
|
|
|
|
|
|
+ if (products.length === 0) {
|
|
|
|
|
+ const noProductsMessage = document.createElement("p");
|
|
|
|
|
+ noProductsMessage.textContent = "No hay productos disponibles.";
|
|
|
|
|
+ productListElement.appendChild(noProductsMessage);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- const addBtn = clone.querySelector(".add-to-cart-btn");
|
|
|
|
|
- addBtn.dataset.productId = product.id; // el listener usa esta info
|
|
|
|
|
|
|
+ for (const { category, container } of categoryContainers) {
|
|
|
|
|
+ let productsInCategory = products.filter(product => product.type === category);
|
|
|
|
|
|
|
|
- productListElement.appendChild(clone);
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ if (productsInCategory.length === 0) continue;
|
|
|
|
|
+
|
|
|
|
|
+ productsInCategory.forEach(product => {
|
|
|
|
|
+ const clone = template.content.cloneNode(true);
|
|
|
|
|
+
|
|
|
|
|
+ clone.querySelector(".product-type").textContent = product.type || "Sin categoría";
|
|
|
|
|
+ clone.querySelector(".product-name").textContent = product.name;
|
|
|
|
|
+ clone.querySelector(".product-description").textContent = product.description;
|
|
|
|
|
+ clone.querySelector(".product-price").textContent = formatPrice(product.price);
|
|
|
|
|
+ clone.querySelector(".product-image").style.backgroundImage = `url('${product.image}')`;
|
|
|
|
|
+
|
|
|
|
|
+ const addBtn = clone.querySelector(".add-to-cart-btn");
|
|
|
|
|
+ addBtn.dataset.productId = product.id; // el listener usa esta info
|
|
|
|
|
+ // Agregar event listener directamente al botón clonado
|
|
|
|
|
+ addBtn.addEventListener('click', (event) => {
|
|
|
|
|
+ const productId = parseInt(event.target.dataset.productId);
|
|
|
|
|
+ addToCart(productId, event.target);
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- document.querySelectorAll('.add-to-cart-btn').forEach(button => {
|
|
|
|
|
- button.addEventListener('click', (event) => {
|
|
|
|
|
- const productId = parseInt(event.target.dataset.productId);
|
|
|
|
|
- addToCart(productId, event.target);
|
|
|
|
|
|
|
+ container.appendChild(clone);
|
|
|
});
|
|
});
|
|
|
- });
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async function renderProductsWithAnimation(products) {
|
|
|
|
|
+ if (!productListElement) return;
|
|
|
|
|
+
|
|
|
|
|
+ const template = document.getElementById("product-card-template");
|
|
|
|
|
+ if (!template) return;
|
|
|
|
|
+
|
|
|
|
|
+ // Fade out actual content
|
|
|
|
|
+ productListElement.style.opacity = "0";
|
|
|
|
|
+ productListElement.style.transform = "scale(0.95)";
|
|
|
|
|
+
|
|
|
|
|
+ setTimeout(async () => {
|
|
|
|
|
+ productListElement.innerHTML = "";
|
|
|
|
|
+
|
|
|
|
|
+ const categoryContainers = await createCategories(products);
|
|
|
|
|
+
|
|
|
|
|
+ if (products.length === 0) {
|
|
|
|
|
+ const noProductsMessage = document.createElement("p");
|
|
|
|
|
+ noProductsMessage.textContent = "No hay productos disponibles.";
|
|
|
|
|
+ noProductsMessage.style.opacity = "0";
|
|
|
|
|
+ noProductsMessage.style.transform = "translateY(20px)";
|
|
|
|
|
+ noProductsMessage.style.transition = "opacity 0.3s ease, transform 0.3s ease";
|
|
|
|
|
+ productListElement.appendChild(noProductsMessage);
|
|
|
|
|
+
|
|
|
|
|
+ // Restore container
|
|
|
|
|
+ productListElement.style.opacity = "1";
|
|
|
|
|
+ productListElement.style.transform = "scale(1)";
|
|
|
|
|
+
|
|
|
|
|
+ // Animate message
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ noProductsMessage.style.opacity = "1";
|
|
|
|
|
+ noProductsMessage.style.transform = "translateY(0)";
|
|
|
|
|
+ }, 50);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let animationDelay = 0;
|
|
|
|
|
+ for (const { category, container } of categoryContainers) {
|
|
|
|
|
+ let productsInCategory = products.filter(product => product.type === category);
|
|
|
|
|
+
|
|
|
|
|
+ if (productsInCategory.length === 0) continue;
|
|
|
|
|
+
|
|
|
|
|
+ productsInCategory.forEach((product, index) => {
|
|
|
|
|
+ const clone = template.content.cloneNode(true);
|
|
|
|
|
+
|
|
|
|
|
+ clone.querySelector(".product-type").textContent = product.type || "Sin categoría";
|
|
|
|
|
+ clone.querySelector(".product-name").textContent = product.name;
|
|
|
|
|
+ clone.querySelector(".product-description").textContent = product.description;
|
|
|
|
|
+ clone.querySelector(".product-price").textContent = formatPrice(product.price);
|
|
|
|
|
+ clone.querySelector(".product-image").style.backgroundImage = `url('${product.image}')`;
|
|
|
|
|
+
|
|
|
|
|
+ const addBtn = clone.querySelector(".add-to-cart-btn");
|
|
|
|
|
+ addBtn.dataset.productId = product.id;
|
|
|
|
|
+ addBtn.addEventListener('click', (event) => {
|
|
|
|
|
+ const productId = parseInt(event.target.dataset.productId);
|
|
|
|
|
+ addToCart(productId, event.target);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // Get the first child (the product card element)
|
|
|
|
|
+ const productCard = clone.children[0];
|
|
|
|
|
+
|
|
|
|
|
+ // Set initial animation state
|
|
|
|
|
+ productCard.style.opacity = "0";
|
|
|
|
|
+ productCard.style.transform = "translateY(20px) scale(0.95)";
|
|
|
|
|
+ productCard.style.transition = "opacity 0.4s ease, transform 0.4s ease";
|
|
|
|
|
+
|
|
|
|
|
+ container.appendChild(clone);
|
|
|
|
|
+
|
|
|
|
|
+ // Animate in with staggered delay
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ productCard.style.opacity = "1";
|
|
|
|
|
+ productCard.style.transform = "translateY(0) scale(1)";
|
|
|
|
|
+ }, animationDelay);
|
|
|
|
|
+
|
|
|
|
|
+ animationDelay += 50; // 50ms delay between each product
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Restore container with smooth transition
|
|
|
|
|
+ productListElement.style.opacity = "1";
|
|
|
|
|
+ productListElement.style.transform = "scale(1)";
|
|
|
|
|
+
|
|
|
|
|
+ }, 150); // Wait for fade out to complete
|
|
|
}
|
|
}
|
|
|
//#endregion
|
|
//#endregion
|
|
|
//#region ===== Carrito =====
|
|
//#region ===== Carrito =====
|
|
|
|
|
|
|
|
|
|
|
|
|
-async function addToCart (productId, buttonElement = null) {
|
|
|
|
|
- const product = products.find(p => p.id === productId);
|
|
|
|
|
|
|
+async function addToCart(productId, buttonElement = null) {
|
|
|
|
|
+ const product = Allproducts.find(p => p.id === productId);
|
|
|
if (!product) return;
|
|
if (!product) return;
|
|
|
const cartItem = cart.find(item => item.id === productId);
|
|
const cartItem = cart.find(item => item.id === productId);
|
|
|
if (cartItem) {
|
|
if (cartItem) {
|
|
@@ -191,7 +348,7 @@ async function addToCart (productId, buttonElement = null) {
|
|
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-async function removeFromCart (productId, removeAll = false) {
|
|
|
|
|
|
|
+async function removeFromCart(productId, removeAll = false) {
|
|
|
const itemIndex = cart.findIndex(item => item.id === productId);
|
|
const itemIndex = cart.findIndex(item => item.id === productId);
|
|
|
if (itemIndex > -1) {
|
|
if (itemIndex > -1) {
|
|
|
if (removeAll || cart[itemIndex].quantity === 1) {
|
|
if (removeAll || cart[itemIndex].quantity === 1) {
|
|
@@ -306,11 +463,11 @@ async function processOrder() {
|
|
|
const orderData = {
|
|
const orderData = {
|
|
|
customerId: userId,
|
|
customerId: userId,
|
|
|
table: userTable,
|
|
table: userTable,
|
|
|
- items: cart.map(item => ({ id: item.id, price: item.price, quantity: item.quantity})),
|
|
|
|
|
|
|
+ items: cart.map(item => ({ id: item.id, price: item.price, quantity: item.quantity })),
|
|
|
totalAmount: cart.reduce((sum, item) => sum + item.price * item.quantity, 0),
|
|
totalAmount: cart.reduce((sum, item) => sum + item.price * item.quantity, 0),
|
|
|
orderDate: new Date().toLocaleString('sv-SE').replace(' ', 'T')
|
|
orderDate: new Date().toLocaleString('sv-SE').replace(' ', 'T')
|
|
|
};
|
|
};
|
|
|
- const data = await sendOrder(orderData,userToken);
|
|
|
|
|
|
|
+ const data = await sendOrder(orderData, userToken);
|
|
|
if (data && data.new_progress) {
|
|
if (data && data.new_progress) {
|
|
|
updateProgress(data.new_progress);
|
|
updateProgress(data.new_progress);
|
|
|
}
|
|
}
|
|
@@ -396,22 +553,22 @@ async function sendMessageToAI() {
|
|
|
|
|
|
|
|
//#endregion
|
|
//#endregion
|
|
|
//#region ===== Rewards =====
|
|
//#region ===== Rewards =====
|
|
|
- // Referencias a elementos del DOM
|
|
|
|
|
- const rewardBtn = document.getElementById('rewardBtn');
|
|
|
|
|
- const rewardModal = document.getElementById('rewardModal');
|
|
|
|
|
- const closeRewardModal = document.getElementById('closeRewardModal');
|
|
|
|
|
- const closeSuccessRewardModalButton = document.getElementById('closeSuccessRewardModal');
|
|
|
|
|
- const cancelRewardBtn = document.getElementById('cancelRewardBtn');
|
|
|
|
|
- const acceptTermsCheckbox = document.getElementById('acceptTermsCheckbox');
|
|
|
|
|
- const claimRewardBtn = document.getElementById('claimRewardBtn');
|
|
|
|
|
|
|
+// Referencias a elementos del DOM
|
|
|
|
|
+const rewardBtn = document.getElementById('rewardBtn');
|
|
|
|
|
+const rewardModal = document.getElementById('rewardModal');
|
|
|
|
|
+const closeRewardModal = document.getElementById('closeRewardModal');
|
|
|
|
|
+const closeSuccessRewardModalButton = document.getElementById('closeSuccessRewardModal');
|
|
|
|
|
+const cancelRewardBtn = document.getElementById('cancelRewardBtn');
|
|
|
|
|
+const acceptTermsCheckbox = document.getElementById('acceptTermsCheckbox');
|
|
|
|
|
+const claimRewardBtn = document.getElementById('claimRewardBtn');
|
|
|
|
|
|
|
|
|
|
|
|
|
- function initializeRewards() {
|
|
|
|
|
- // Abrir modal cuando se hace clic en el botón de recompensa
|
|
|
|
|
|
|
+function initializeRewards() {
|
|
|
|
|
+ // Abrir modal cuando se hace clic en el botón de recompensa
|
|
|
|
|
|
|
|
- closeSuccessRewardModalButton.addEventListener("click", closeSuccessRewardModal);
|
|
|
|
|
|
|
+ closeSuccessRewardModalButton.addEventListener("click", closeSuccessRewardModal);
|
|
|
|
|
|
|
|
- rewardBtn.addEventListener('click', function() {
|
|
|
|
|
|
|
+ rewardBtn.addEventListener('click', function () {
|
|
|
if (!rewardBtn.disabled) {
|
|
if (!rewardBtn.disabled) {
|
|
|
rewardModal.classList.remove('hidden');
|
|
rewardModal.classList.remove('hidden');
|
|
|
document.body.style.overflow = 'hidden'; // Evitar scroll del fondo
|
|
document.body.style.overflow = 'hidden'; // Evitar scroll del fondo
|
|
@@ -419,31 +576,31 @@ async function sendMessageToAI() {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// Cerrar modal - botón X
|
|
// Cerrar modal - botón X
|
|
|
- closeRewardModal.addEventListener('click', function() {
|
|
|
|
|
|
|
+ closeRewardModal.addEventListener('click', function () {
|
|
|
closeModal();
|
|
closeModal();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// Cerrar modal - botón Cancelar
|
|
// Cerrar modal - botón Cancelar
|
|
|
- cancelRewardBtn.addEventListener('click', function() {
|
|
|
|
|
|
|
+ cancelRewardBtn.addEventListener('click', function () {
|
|
|
closeModal();
|
|
closeModal();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// Cerrar modal haciendo clic fuera de él
|
|
// Cerrar modal haciendo clic fuera de él
|
|
|
- rewardModal.addEventListener('click', function(e) {
|
|
|
|
|
|
|
+ rewardModal.addEventListener('click', function (e) {
|
|
|
if (e.target === rewardModal) {
|
|
if (e.target === rewardModal) {
|
|
|
closeModal();
|
|
closeModal();
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// Cerrar modal con tecla Escape
|
|
// Cerrar modal con tecla Escape
|
|
|
- document.addEventListener('keydown', function(e) {
|
|
|
|
|
|
|
+ document.addEventListener('keydown', function (e) {
|
|
|
if (e.key === 'Escape' && !rewardModal.classList.contains('hidden')) {
|
|
if (e.key === 'Escape' && !rewardModal.classList.contains('hidden')) {
|
|
|
closeModal();
|
|
closeModal();
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- // Manejar el reclamo del premio
|
|
|
|
|
- claimRewardBtn.addEventListener('click', function() {
|
|
|
|
|
|
|
+ // Manejar el reclamo del premio
|
|
|
|
|
+ claimRewardBtn.addEventListener('click', function () {
|
|
|
if (!this.disabled && acceptTermsCheckbox.checked) {
|
|
if (!this.disabled && acceptTermsCheckbox.checked) {
|
|
|
// Generar código de premio (puedes cambiar esta lógica)
|
|
// Generar código de premio (puedes cambiar esta lógica)
|
|
|
|
|
|
|
@@ -455,84 +612,81 @@ async function sendMessageToAI() {
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function closeSuccessRewardModal() {
|
|
|
|
|
+ const successRewardModal = document.getElementById("successRewardModal");
|
|
|
|
|
+ successRewardModal.classList.add("hidden");
|
|
|
|
|
+ document.body.style.overflow = ''; // Restaurar scroll
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- // Generar más confetti dinámicamente
|
|
|
|
|
- console.log("Rewards initialized");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- function closeSuccessRewardModal() {
|
|
|
|
|
- const successRewardModal = document.getElementById("successRewardModal");
|
|
|
|
|
- successRewardModal.classList.add("hidden");
|
|
|
|
|
- document.body.style.overflow = ''; // Restaurar scroll
|
|
|
|
|
- }
|
|
|
|
|
|
|
+// Función para cerrar el modal
|
|
|
|
|
+function closeModal() {
|
|
|
|
|
+ rewardModal.classList.add('hidden');
|
|
|
|
|
+ document.body.style.overflow = ''; // Restaurar scroll
|
|
|
|
|
|
|
|
- // Función para cerrar el modal
|
|
|
|
|
- function closeModal() {
|
|
|
|
|
- rewardModal.classList.add('hidden');
|
|
|
|
|
- document.body.style.overflow = ''; // Restaurar scroll
|
|
|
|
|
-
|
|
|
|
|
- // Reset del formulario al cerrar
|
|
|
|
|
- acceptTermsCheckbox.checked = false;
|
|
|
|
|
|
|
+ // Reset del formulario al cerrar
|
|
|
|
|
+ acceptTermsCheckbox.checked = false;
|
|
|
|
|
+ claimRewardBtn.disabled = true;
|
|
|
|
|
+ claimRewardBtn.classList.add('opacity-50', 'cursor-not-allowed');
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Manejar el checkbox de términos y condiciones
|
|
|
|
|
+acceptTermsCheckbox.addEventListener('change', function () {
|
|
|
|
|
+ if (this.checked) {
|
|
|
|
|
+ // Habilitar botón de reclamar
|
|
|
|
|
+ claimRewardBtn.disabled = false;
|
|
|
|
|
+ claimRewardBtn.classList.remove('opacity-50', 'cursor-not-allowed');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // Deshabilitar botón de reclamar
|
|
|
claimRewardBtn.disabled = true;
|
|
claimRewardBtn.disabled = true;
|
|
|
claimRewardBtn.classList.add('opacity-50', 'cursor-not-allowed');
|
|
claimRewardBtn.classList.add('opacity-50', 'cursor-not-allowed');
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // Manejar el checkbox de términos y condiciones
|
|
|
|
|
- acceptTermsCheckbox.addEventListener('change', function() {
|
|
|
|
|
- if (this.checked) {
|
|
|
|
|
- // Habilitar botón de reclamar
|
|
|
|
|
- claimRewardBtn.disabled = false;
|
|
|
|
|
- claimRewardBtn.classList.remove('opacity-50', 'cursor-not-allowed');
|
|
|
|
|
- } else {
|
|
|
|
|
- // Deshabilitar botón de reclamar
|
|
|
|
|
- claimRewardBtn.disabled = true;
|
|
|
|
|
- claimRewardBtn.classList.add('opacity-50', 'cursor-not-allowed');
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- // Función para mostrar mensaje de éxito con el código
|
|
|
|
|
- function showRewardSuccess(code) {
|
|
|
|
|
- // Crear elemento de notificación de éxito
|
|
|
|
|
- const successToast = document.createElement('div');
|
|
|
|
|
- successToast.className = `
|
|
|
|
|
|
|
+// Función para mostrar mensaje de éxito con el código
|
|
|
|
|
+function showRewardSuccess(code) {
|
|
|
|
|
+ // Crear elemento de notificación de éxito
|
|
|
|
|
+ const successToast = document.createElement('div');
|
|
|
|
|
+ successToast.className = `
|
|
|
fixed top-4 left-1/2 transform -translate-x-1/2
|
|
fixed top-4 left-1/2 transform -translate-x-1/2
|
|
|
bg-green-500 text-white text-sm rounded-lg px-6 py-4
|
|
bg-green-500 text-white text-sm rounded-lg px-6 py-4
|
|
|
shadow-lg z-50 max-w-sm text-center
|
|
shadow-lg z-50 max-w-sm text-center
|
|
|
`;
|
|
`;
|
|
|
- successToast.innerHTML = `
|
|
|
|
|
|
|
+ successToast.innerHTML = `
|
|
|
<div class="font-bold mb-1">🎉 ¡Premio Reclamado!</div>
|
|
<div class="font-bold mb-1">🎉 ¡Premio Reclamado!</div>
|
|
|
<div class="text-xs opacity-90">Tu código: <strong>${code}</strong></div>
|
|
<div class="text-xs opacity-90">Tu código: <strong>${code}</strong></div>
|
|
|
<div class="text-xs mt-1 opacity-80">Muéstralo al mesero</div>
|
|
<div class="text-xs mt-1 opacity-80">Muéstralo al mesero</div>
|
|
|
`;
|
|
`;
|
|
|
-
|
|
|
|
|
- document.body.appendChild(successToast);
|
|
|
|
|
-
|
|
|
|
|
- // Remover después de 5 segundos
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- if (successToast.parentNode) {
|
|
|
|
|
- successToast.remove();
|
|
|
|
|
- }
|
|
|
|
|
- }, 5000);
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- // Función para resetear el progreso de recompensa
|
|
|
|
|
- function resetRewardProgress() {
|
|
|
|
|
- const progressBar = document.getElementById('progressBar');
|
|
|
|
|
- const progressText = document.getElementById('progressText');
|
|
|
|
|
- const rewardBtn = document.getElementById('rewardBtn');
|
|
|
|
|
-
|
|
|
|
|
- // Resetear a 0%
|
|
|
|
|
- progressBar.style.width = '0%';
|
|
|
|
|
- progressText.textContent = '0%';
|
|
|
|
|
-
|
|
|
|
|
- // Deshabilitar botón de recompensa
|
|
|
|
|
- rewardBtn.disabled = true;
|
|
|
|
|
- rewardBtn.classList.add('opacity-50', 'cursor-not-allowed');
|
|
|
|
|
- rewardBtn.classList.remove('bg-yellow-500', 'hover:bg-yellow-600');
|
|
|
|
|
- rewardBtn.textContent = '🎉 ¡Reclamar!';
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ document.body.appendChild(successToast);
|
|
|
|
|
+
|
|
|
|
|
+ // Remover después de 5 segundos
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ if (successToast.parentNode) {
|
|
|
|
|
+ successToast.remove();
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 5000);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Función para resetear el progreso de recompensa
|
|
|
|
|
+function resetRewardProgress() {
|
|
|
|
|
+ const progressBar = document.getElementById('progressBar');
|
|
|
|
|
+ const progressText = document.getElementById('progressText');
|
|
|
|
|
+ const rewardBtn = document.getElementById('rewardBtn');
|
|
|
|
|
+
|
|
|
|
|
+ // Resetear a 0%
|
|
|
|
|
+ progressBar.style.width = '0%';
|
|
|
|
|
+ progressText.textContent = '0%';
|
|
|
|
|
+
|
|
|
|
|
+ // Deshabilitar botón de recompensa
|
|
|
|
|
+ rewardBtn.disabled = true;
|
|
|
|
|
+ rewardBtn.classList.add('opacity-50', 'cursor-not-allowed');
|
|
|
|
|
+ rewardBtn.classList.remove('bg-yellow-500', 'hover:bg-yellow-600');
|
|
|
|
|
+ rewardBtn.textContent = '🎉 ¡Reclamar!';
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
//#endregion
|
|
//#endregion
|
|
|
// --- APP initialization ---
|
|
// --- APP initialization ---
|