Spaces:
Running
Running
| <html lang="es"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Super Selectos - Tu supermercado de confianza</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| /* Estilos personalizados adicionales */ | |
| .fade-in { | |
| animation: fadeIn 0.5s ease-in-out; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .sidebar { | |
| transition: all 0.3s ease; | |
| } | |
| .sidebar-hidden { | |
| transform: translateX(-100%); | |
| } | |
| .product-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 10px 20px rgba(0, 100, 0, 0.1); | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-green-50 font-sans"> | |
| <!-- Barra de navegaci贸n --> | |
| <nav class="bg-green-800 text-white shadow-lg"> | |
| <div class="container mx-auto px-4 py-3 flex justify-between items-center"> | |
| <div class="flex items-center space-x-4"> | |
| <button id="menu-toggle" class="md:hidden text-xl focus:outline-none"> | |
| <i class="fas fa-bars"></i> | |
| </button> | |
| <div class="flex items-center"> | |
| <i class="fas fa-shopping-basket text-2xl mr-2"></i> | |
| <h1 class="text-xl font-bold">Super Selectos</h1> | |
| </div> | |
| </div> | |
| <div class="hidden md:flex space-x-6"> | |
| <a href="#" class="nav-link active" data-section="products">Productos</a> | |
| <a href="#" class="nav-link" data-section="add-product">Agregar Producto</a> | |
| <a href="#" class="nav-link" data-section="manage-products">Administrar</a> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <div class="relative"> | |
| <input type="text" placeholder="Buscar..." class="bg-green-700 text-white px-4 py-1 rounded-full focus:outline-none focus:ring-2 focus:ring-green-300 placeholder-green-300"> | |
| <i class="fas fa-search absolute right-3 top-1/2 transform -translate-y-1/2 text-green-300"></i> | |
| </div> | |
| </div> | |
| </div> | |
| </nav> | |
| <!-- Hero Section --> | |
| <div class="relative bg-green-800 text-white overflow-hidden"> | |
| <div class="absolute inset-0 bg-black opacity-40"></div> | |
| <img src="https://images.unsplash.com/photo-1550581190-9c1c47d2167c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80" | |
| alt="Supermercado" class="w-full h-full object-cover absolute"> | |
| <div class="container mx-auto px-4 py-24 relative z-10"> | |
| <div class="max-w-2xl"> | |
| <h1 class="text-5xl font-bold mb-6">Bienvenido a Super Selectos</h1> | |
| <p class="text-xl mb-8">Tu supermercado de confianza con los mejores precios y calidad garantizada.</p> | |
| <div class="bg-white bg-opacity-20 backdrop-blur-sm p-6 rounded-xl"> | |
| <h3 class="text-2xl font-bold mb-3">Horario de atenci贸n</h3> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div> | |
| <p class="font-medium">Lunes a Viernes</p> | |
| <p>8:00 AM - 8:00 PM</p> | |
| </div> | |
| <div> | |
| <p class="font-medium">S谩bados y Domingos</p> | |
| <p>9:00 AM - 6:00 PM</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Sidebar m贸vil --> | |
| <div id="sidebar" class="sidebar sidebar-hidden fixed inset-y-0 left-0 z-50 w-64 bg-green-900 text-white shadow-lg md:hidden"> | |
| <div class="p-4"> | |
| <h2 class="text-xl font-bold mb-6 flex items-center"> | |
| <i class="fas fa-shopping-basket mr-2"></i> Super Selectos | |
| </h2> | |
| <ul class="space-y-3"> | |
| <li><a href="#" class="block px-4 py-2 rounded hover:bg-green-800 nav-link-mobile active" data-section="products"><i class="fas fa-box-open mr-2"></i> Productos</a></li> | |
| <li><a href="#" class="block px-4 py-2 rounded hover:bg-green-800 nav-link-mobile" data-section="add-product"><i class="fas fa-plus-circle mr-2"></i> Agregar Producto</a></li> | |
| <li><a href="#" class="block px-4 py-2 rounded hover:bg-green-800 nav-link-mobile" data-section="manage-products"><i class="fas fa-tasks mr-2"></i> Administrar</a></li> | |
| </ul> | |
| </div> | |
| </div> | |
| <!-- Contenido principal --> | |
| <div class="container mx-auto px-4 py-6 md:ml-0 transition-all duration-300"> | |
| <!-- Secci贸n de Productos --> | |
| <section id="products-section" class="section-content fade-in"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h2 class="text-2xl font-bold text-green-900">Nuestros Productos</h2> | |
| <div class="flex space-x-2"> | |
| <button id="sort-price" class="bg-green-600 text-white px-3 py-1 rounded hover:bg-green-700 flex items-center"> | |
| <span>Precio</span> | |
| <i class="fas fa-sort ml-1"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div id="products-container" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"> | |
| <!-- Los productos se cargar谩n aqu铆 din谩micamente --> | |
| </div> | |
| </section> | |
| <!-- Secci贸n para Agregar Producto --> | |
| <section id="add-product-section" class="section-content hidden fade-in"> | |
| <h2 class="text-2xl font-bold text-green-900 mb-6">Agregar Nuevo Producto</h2> | |
| <div class="bg-white rounded-lg shadow-md p-6 max-w-2xl mx-auto"> | |
| <form id="add-product-form" class="space-y-4"> | |
| <div> | |
| <label for="product-name" class="block text-green-800 font-medium mb-1">Nombre del Producto</label> | |
| <input type="text" id="product-name" class="w-full px-4 py-2 border border-green-300 rounded focus:outline-none focus:ring-2 focus:ring-green-500" required> | |
| </div> | |
| <div> | |
| <label for="product-price" class="block text-green-800 font-medium mb-1">Precio ($)</label> | |
| <input type="number" id="product-price" min="0" step="0.01" class="w-full px-4 py-2 border border-green-300 rounded focus:outline-none focus:ring-2 focus:ring-green-500" required> | |
| </div> | |
| <div> | |
| <label for="product-image" class="block text-green-800 font-medium mb-1">Imagen del Producto (URL)</label> | |
| <input type="text" id="product-image" class="w-full px-4 py-2 border border-green-300 rounded focus:outline-none focus:ring-2 focus:ring-green-500" placeholder="https://ejemplo.com/imagen.jpg"> | |
| </div> | |
| <div> | |
| <label for="product-expiration" class="block text-green-800 font-medium mb-1">Fecha de Vencimiento (opcional)</label> | |
| <input type="date" id="product-expiration" class="w-full px-4 py-2 border border-green-300 rounded focus:outline-none focus:ring-2 focus:ring-green-500"> | |
| </div> | |
| <div class="pt-2"> | |
| <button type="submit" class="bg-green-600 text-white px-6 py-2 rounded hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 transition"> | |
| <i class="fas fa-save mr-2"></i> Guardar Producto | |
| </button> | |
| </div> | |
| </form> | |
| </div> | |
| </section> | |
| <!-- Secci贸n para Administrar Productos --> | |
| <section id="manage-products-section" class="section-content hidden fade-in"> | |
| <h2 class="text-2xl font-bold text-green-900 mb-6">Administrar Productos</h2> | |
| <div class="bg-white rounded-lg shadow-md overflow-hidden"> | |
| <div class="overflow-x-auto"> | |
| <table class="min-w-full divide-y divide-green-200"> | |
| <thead class="bg-green-100"> | |
| <tr> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-green-800 uppercase tracking-wider">Nombre</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-green-800 uppercase tracking-wider">Precio</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-green-800 uppercase tracking-wider">Vencimiento</th> | |
| <th class="px-6 py-3 text-left text-xs font-medium text-green-800 uppercase tracking-wider">Acciones</th> | |
| </tr> | |
| </thead> | |
| <tbody id="manage-products-body" class="bg-white divide-y divide-green-200"> | |
| <!-- Los productos para administrar se cargar谩n aqu铆 din谩micamente --> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </section> | |
| </div> | |
| <!-- Modal de confirmaci贸n --> | |
| <div id="confirm-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden"> | |
| <div class="bg-white rounded-lg shadow-xl p-6 max-w-md w-full"> | |
| <div class="flex justify-between items-start mb-4"> | |
| <h3 class="text-lg font-bold text-green-900">Confirmar Eliminaci贸n</h3> | |
| <button id="close-modal" class="text-gray-500 hover:text-gray-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <p class="mb-6">驴Est谩s seguro que deseas eliminar este producto? Esta acci贸n no se puede deshacer.</p> | |
| <div class="flex justify-end space-x-3"> | |
| <button id="cancel-delete" class="px-4 py-2 border border-green-300 text-green-700 rounded hover:bg-green-50">Cancelar</button> | |
| <button id="confirm-delete" class="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700">Eliminar</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Notificaci贸n --> | |
| <div id="notification" class="fixed bottom-4 right-4 bg-green-600 text-white px-6 py-3 rounded-lg shadow-lg flex items-center hidden"> | |
| <i class="fas fa-check-circle mr-2"></i> | |
| <span id="notification-message">Operaci贸n realizada con 茅xito</span> | |
| </div> | |
| <script> | |
| // Base de datos de productos (simulada) | |
| let products = [ | |
| { id: 1, name: "Leche Entera", price: 1.50, category: "L谩cteos", expiration: "2023-12-15", discount: 20 }, | |
| { id: 2, name: "Pan Integral", price: 3.00, category: "Alimentos", expiration: "2023-11-20", discount: 15 }, | |
| { id: 3, name: "Agua Mineral", price: 0.80, category: "Bebidas", expiration: "2024-10-01" }, | |
| { id: 4, name: "Jab贸n L铆quido", price: 3.75, category: "Limpieza" }, | |
| { id: 5, name: "Arroz Blanco", price: 1.80, category: "Alimentos", expiration: "2024-05-30" }, | |
| { id: 6, name: "Cereal de Avena", price: 4.20, category: "Alimentos", expiration: "2023-12-01", discount: 10 }, | |
| { id: 7, name: "Jugo de Naranja", price: 2.30, category: "Bebidas", expiration: "2023-11-25" }, | |
| { id: 8, name: "Detergente", price: 5.40, category: "Limpieza", discount: 5 } | |
| ]; | |
| // Variables de estado | |
| let currentProductId = null; | |
| let sortAscending = true; | |
| let selectedCategory = 'all'; | |
| // DOM Elements | |
| const menuToggle = document.getElementById('menu-toggle'); | |
| const sidebar = document.getElementById('sidebar'); | |
| const navLinks = document.querySelectorAll('.nav-link'); | |
| const navLinksMobile = document.querySelectorAll('.nav-link-mobile'); | |
| const sections = document.querySelectorAll('.section-content'); | |
| const productsContainer = document.getElementById('products-container'); | |
| const manageProductsBody = document.getElementById('manage-products-body'); | |
| const categoryFilter = document.getElementById('category-filter'); | |
| const sortPriceBtn = document.getElementById('sort-price'); | |
| const productCategory = document.getElementById('product-category'); | |
| const expirationContainer = document.getElementById('expiration-container'); | |
| const addProductForm = document.getElementById('add-product-form'); | |
| const confirmModal = document.getElementById('confirm-modal'); | |
| const closeModal = document.getElementById('close-modal'); | |
| const cancelDelete = document.getElementById('cancel-delete'); | |
| const confirmDelete = document.getElementById('confirm-delete'); | |
| const notification = document.getElementById('notification'); | |
| // Event Listeners | |
| document.addEventListener('DOMContentLoaded', () => { | |
| renderProducts(); | |
| renderManageProducts(); | |
| }); | |
| menuToggle.addEventListener('click', () => { | |
| sidebar.classList.toggle('sidebar-hidden'); | |
| }); | |
| navLinks.forEach(link => { | |
| link.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| showSection(link.dataset.section); | |
| // Actualizar clase activa | |
| navLinks.forEach(l => l.classList.remove('active')); | |
| link.classList.add('active'); | |
| // Actualizar tambi茅n en m贸vil | |
| navLinksMobile.forEach(l => { | |
| if (l.dataset.section === link.dataset.section) { | |
| l.classList.add('active'); | |
| } else { | |
| l.classList.remove('active'); | |
| } | |
| }); | |
| }); | |
| }); | |
| navLinksMobile.forEach(link => { | |
| link.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| showSection(link.dataset.section); | |
| sidebar.classList.add('sidebar-hidden'); | |
| // Actualizar clase activa | |
| navLinksMobile.forEach(l => l.classList.remove('active')); | |
| link.classList.add('active'); | |
| // Actualizar tambi茅n en desktop | |
| navLinks.forEach(l => { | |
| if (l.dataset.section === link.dataset.section) { | |
| l.classList.add('active'); | |
| } else { | |
| l.classList.remove('active'); | |
| } | |
| }); | |
| }); | |
| }); | |
| categoryFilter.addEventListener('change', () => { | |
| renderProducts(); | |
| }); | |
| sortPriceBtn.addEventListener('click', () => { | |
| sortAscending = !sortAscending; | |
| renderProducts(); | |
| // Actualizar icono | |
| const icon = sortPriceBtn.querySelector('i'); | |
| icon.className = sortAscending ? 'fas fa-sort-amount-up-alt ml-1' : 'fas fa-sort-amount-down ml-1'; | |
| }); | |
| // Agregar event listeners a las categor铆as | |
| document.querySelectorAll('.category-card').forEach(card => { | |
| card.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| selectedCategory = card.querySelector('h3').textContent.toLowerCase(); | |
| if (selectedCategory === 'otros') selectedCategory = 'otros'; | |
| renderProducts(); | |
| // Resaltar categor铆a seleccionada | |
| document.querySelectorAll('.category-card').forEach(c => { | |
| c.classList.remove('ring-2', 'ring-green-600'); | |
| }); | |
| card.classList.add('ring-2', 'ring-green-600'); | |
| }); | |
| }); | |
| addProductForm.addEventListener('submit', (e) => { | |
| e.preventDefault(); | |
| const name = document.getElementById('product-name').value; | |
| const price = parseFloat(document.getElementById('product-price').value); | |
| const image = document.getElementById('product-image').value; | |
| const expiration = document.getElementById('product-expiration').value; | |
| // Generar nuevo ID | |
| const newId = products.length > 0 ? Math.max(...products.map(p => p.id)) + 1 : 1; | |
| // Crear nuevo producto | |
| const newProduct = { | |
| id: newId, | |
| name, | |
| price, | |
| image | |
| }; | |
| if (expiration) { | |
| newProduct.expiration = expiration; | |
| } | |
| // Agregar a la lista | |
| products.push(newProduct); | |
| // Resetear formulario | |
| addProductForm.reset(); | |
| expirationContainer.classList.add('hidden'); | |
| // Actualizar vistas | |
| renderProducts(); | |
| renderManageProducts(); | |
| // Mostrar notificaci贸n | |
| showNotification('Producto agregado correctamente'); | |
| // Mostrar secci贸n de productos | |
| showSection('products'); | |
| updateActiveNav('products'); | |
| }); | |
| closeModal.addEventListener('click', () => { | |
| confirmModal.classList.add('hidden'); | |
| }); | |
| cancelDelete.addEventListener('click', () => { | |
| confirmModal.classList.add('hidden'); | |
| }); | |
| confirmDelete.addEventListener('click', () => { | |
| if (currentProductId) { | |
| // Eliminar producto | |
| products = products.filter(p => p.id !== currentProductId); | |
| // Actualizar vistas | |
| renderProducts(); | |
| renderManageProducts(); | |
| // Ocultar modal | |
| confirmModal.classList.add('hidden'); | |
| // Mostrar notificaci贸n | |
| showNotification('Producto eliminado correctamente'); | |
| // Resetear ID | |
| currentProductId = null; | |
| } | |
| }); | |
| // Funciones | |
| function showSection(sectionId) { | |
| sections.forEach(section => { | |
| if (section.id === `${sectionId}-section`) { | |
| section.classList.remove('hidden'); | |
| section.classList.add('fade-in'); | |
| } else { | |
| section.classList.add('hidden'); | |
| } | |
| }); | |
| } | |
| function updateActiveNav(sectionId) { | |
| navLinks.forEach(link => { | |
| if (link.dataset.section === sectionId) { | |
| link.classList.add('active'); | |
| } else { | |
| link.classList.remove('active'); | |
| } | |
| }); | |
| navLinksMobile.forEach(link => { | |
| if (link.dataset.section === sectionId) { | |
| link.classList.add('active'); | |
| } else { | |
| link.classList.remove('active'); | |
| } | |
| }); | |
| } | |
| function renderProducts() { | |
| // Ordenar por precio | |
| const filteredProducts = [...products].sort((a, b) => { | |
| return sortAscending ? a.price - b.price : b.price - a.price; | |
| }); | |
| // Generar HTML | |
| let html = ''; | |
| if (filteredProducts.length === 0) { | |
| html = ` | |
| <div class="col-span-full text-center py-10"> | |
| <i class="fas fa-box-open text-4xl text-green-300 mb-3"></i> | |
| <p class="text-green-700">No hay productos disponibles en esta categor铆a</p> | |
| </div> | |
| `; | |
| } else { | |
| filteredProducts.forEach(product => { | |
| html += ` | |
| <div class="product-card bg-white rounded-lg shadow-md overflow-hidden transition duration-300 hover:shadow-lg"> | |
| ${product.discount ? ` | |
| <div class="absolute top-2 right-2 bg-red-600 text-white text-xs font-bold px-2 py-1 rounded-full"> | |
| ${product.discount}% OFF | |
| </div> | |
| ` : ''} | |
| <img src="${product.image || 'https://via.placeholder.com/300x200?text='+encodeURIComponent(product.name)}" alt="${product.name}" class="w-full h-40 object-cover"> | |
| <div class="p-4"> | |
| <h3 class="font-bold text-green-900 text-lg truncate mb-2">${product.name}</h3> | |
| <p class="text-green-600 font-bold text-xl mb-3"> | |
| ${product.price.toFixed(2)} | |
| </p> | |
| ${product.expiration ? ` | |
| <div class="flex items-center text-sm text-gray-600"> | |
| <i class="fas fa-calendar-alt mr-2"></i> | |
| <span>Vence: ${formatDate(product.expiration)}</span> | |
| </div> | |
| ` : ''} | |
| </div> | |
| </div> | |
| `; | |
| }); | |
| } | |
| productsContainer.innerHTML = html; | |
| } | |
| function renderManageProducts() { | |
| let html = ''; | |
| products.forEach(product => { | |
| html += ` | |
| <tr> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-green-900">${product.name}</td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-green-700">${product.category}</td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-green-700">$${product.price.toFixed(2)}</td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-green-700">${product.expiration ? formatDate(product.expiration) : 'N/A'}</td> | |
| <td class="px-6 py-4 whitespace-nowrap text-sm text-green-700"> | |
| <button class="edit-product text-blue-600 hover:text-blue-800 mr-3" data-id="${product.id}"> | |
| <i class="fas fa-edit"></i> | |
| </button> | |
| <button class="delete-product text-red-600 hover:text-red-800" data-id="${product.id}"> | |
| <i class="fas fa-trash-alt"></i> | |
| </button> | |
| </td> | |
| </tr> | |
| `; | |
| }); | |
| manageProductsBody.innerHTML = html; | |
| // Agregar event listeners a los botones | |
| document.querySelectorAll('.delete-product').forEach(btn => { | |
| btn.addEventListener('click', (e) => { | |
| currentProductId = parseInt(e.currentTarget.dataset.id); | |
| confirmModal.classList.remove('hidden'); | |
| }); | |
| }); | |
| document.querySelectorAll('.edit-product').forEach(btn => { | |
| btn.addEventListener('click', (e) => { | |
| const productId = parseInt(e.currentTarget.dataset.id); | |
| const product = products.find(p => p.id === productId); | |
| if (product) { | |
| // Llenar el formulario con los datos del producto | |
| document.getElementById('product-name').value = product.name; | |
| document.getElementById('product-price').value = product.price; | |
| document.getElementById('product-category').value = product.category; | |
| if (product.expiration) { | |
| document.getElementById('product-expiration').value = product.expiration; | |
| expirationContainer.classList.remove('hidden'); | |
| } else { | |
| expirationContainer.classList.add('hidden'); | |
| } | |
| // Mostrar secci贸n de agregar producto | |
| showSection('add-product'); | |
| updateActiveNav('add-product'); | |
| // Actualizar el ID actual para saber que estamos editando | |
| currentProductId = productId; | |
| } | |
| }); | |
| }); | |
| } | |
| function formatDate(dateString) { | |
| const options = { year: 'numeric', month: 'short', day: 'numeric' }; | |
| return new Date(dateString).toLocaleDateString('es-ES', options); | |
| } | |
| function showNotification(message) { | |
| const notificationMessage = document.getElementById('notification-message'); | |
| notificationMessage.textContent = message; | |
| notification.classList.remove('hidden'); | |
| setTimeout(() => { | |
| notification.classList.add('hidden'); | |
| }, 3000); | |
| } | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://deepsite.hf.co/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://deepsite.hf.co" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 馃К <a href="https://deepsite.hf.co?remix=PTRNL0/super-selectos" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |