🍽️ Vale&Vane Restaurante

Instalador automático del sitio web completo

📋 ¿Qué se instalará?

  • ✅ Página principal (index.html)
  • ✅ Páginas: Menú, Galería, Opiniones, Reservas, Contacto
  • ✅ Panel de administración con contraseña encriptada
  • ✅ Sistema de reservas (guardado en archivos .txt)
  • ✅ Sistema de opiniones con aprobación
  • ✅ Gestor de menú editable
  • ✅ Galería de imágenes editable

🔐 Acceso al Panel Admin

Contraseña por defecto: admin123

* El administrador puede cambiar la contraseña desde el panel

📁 Preparando instalación...
`, "menu.html": ` Menú | Vale&Vane

Nuestro Menú

`, "galeria.html": ` Galería | Vale&Vane

Galería de Imágenes

`, "opiniones.html": ` Opiniones | Vale&Vane

Opiniones de Nuestros Clientes

Deja tu opinión

`, "reservas.html": ` Reservas | Vale&Vane

Reservar Mesa

`, "contacto.html": ` Contacto | Vale&Vane

Contacto

Dirección

Ver mapa →

Teléfono

Llamar ahora

Horario

Envíanos un mensaje

`, "assets/css/style.css": `*{margin:0;padding:0;box-sizing:border-box}body{font-family:'Inter',sans-serif;background:#fefaf5;color:#2c2418}h1,h2,h3,.logo{font-family:'Playfair Display',serif}.container{max-width:1280px;margin:0 auto;padding:0 24px}.header{background:#1e2a2b;color:#f5e7d9;padding:16px 0;position:sticky;top:0;z-index:100}.header .container{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:16px}.logo h1{font-size:1.6rem}.logo p{font-size:0.75rem;opacity:0.8}.nav{display:flex;gap:24px;align-items:center}.nav a{color:#f5e7d9;text-decoration:none;font-weight:500}.nav a:hover,.nav a.active{color:#d4af7a}.admin-btn{background:#d4af7a;color:#1e2a2b!important;padding:6px 12px;border-radius:30px}.mobile-menu-btn{display:none;background:none;border:none;color:white;font-size:24px;cursor:pointer}.hero{background:linear-gradient(rgba(30,42,43,0.75),rgba(30,42,43,0.75)),url('https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=1600') center/cover;min-height:70vh;display:flex;align-items:center;text-align:center;color:white}.hero-content h2{font-size:2.8rem;margin-bottom:16px}.hero-content p{font-size:1.2rem;margin-bottom:32px}.btn-group{display:flex;gap:16px;justify-content:center;flex-wrap:wrap}.btn{display:inline-block;background:#d4af7a;color:#1e2a2b;padding:12px 32px;border-radius:40px;text-decoration:none;font-weight:600;border:none;cursor:pointer}.btn-outline{background:transparent;border:2px solid #d4af7a;color:#d4af7a}.btn-small{padding:6px 16px;background:#d4af7a;border-radius:30px;text-decoration:none;color:#1e2a2b;font-weight:600}.btn:hover,.btn-small:hover{background:#b88d4b;color:white}.section{padding:60px 0;border-bottom:1px solid #ede3d6}.section-title{text-align:center;font-size:2.2rem;margin-bottom:40px;color:#1e2a2b}.info-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:24px}.info-card{background:white;padding:24px;border-radius:20px;text-align:center;box-shadow:0 4px 12px rgba(0,0,0,0.05)}.info-card i{font-size:2rem;color:#d4af7a;margin-bottom:12px}.badge-list{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:12px}.badge{background:#f0e7dd;padding:4px 12px;border-radius:20px;font-size:0.8rem}.menu-item{background:white;border-radius:16px;overflow:hidden;display:flex;box-shadow:0 2px 8px rgba(0,0,0,0.05)}.menu-item-img{width:100px;height:100px;object-fit:cover}.menu-item-info{padding:12px;flex:1}.menu-item-price{color:#d4af7a;font-weight:bold;margin-top:8px}.menu-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:24px}.menu-category{margin-bottom:48px}.menu-category h3{font-size:1.6rem;margin-bottom:20px;border-left:4px solid #d4af7a;padding-left:16px}.gallery-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:20px}.gallery-grid img{width:100%;height:220px;object-fit:cover;border-radius:16px;cursor:pointer}.review-card{background:white;padding:20px;border-radius:16px;margin-bottom:20px;box-shadow:0 2px 8px rgba(0,0,0,0.05)}.stars{color:#ffb347;margin-bottom:8px}.review-img{width:60px;height:60px;object-fit:cover;border-radius:12px;margin-top:12px}.reviews-preview{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:24px}.form-group{margin-bottom:20px}input,textarea,select{width:100%;padding:14px;border:1px solid #ddd;border-radius:12px;font-family:inherit}.footer{background:#1e2a2b;color:#f5e7d9;padding:48px 0 24px}.footer-content{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:40px;margin-bottom:40px}.footer-bottom{text-align:center;padding-top:24px;border-top:1px solid rgba(245,231,217,0.2)}@media(max-width:768px){.hero-content h2{font-size:1.8rem}.mobile-menu-btn{display:block}.nav{display:none;width:100%;flex-direction:column;gap:16px;padding:16px 0}.nav.show{display:flex}.section{padding:40px 0}.section-title{font-size:1.8rem}.menu-item{flex-direction:column}.menu-item-img{width:100%;height:160px}}`, "assets/js/main.js": `function formatearFecha(fecha){return new Date(fecha).toLocaleDateString('es-ES')} window.formatearFecha = formatearFecha;`, "admin/login.html": ` Admin Login | Vale&Vane

🔧 Vale&Vane

Panel de Administración

`, "admin/dashboard.html": ` Dashboard Admin | Vale&Vane

🔧 Panel de Administración - Vale&Vane

Cerrar sesión

Gestionar Menú

Gestionar Galería

Opiniones

Reservas

Configuración

`, "admin/cambiar-pass.html": ` Cambiar Contraseña

🔐 Cambiar Contraseña

`, "admin/style.css": `.admin-card{transition:transform .2s}.admin-card:hover{transform:translateY(-2px)}.modal{animation:fadeIn .2s}@keyframes fadeIn{from{opacity:0}to{opacity:1}}.modal-content{animation:slideIn .3s}@keyframes slideIn{from{transform:translateY(-50px);opacity:0}to{transform:translateY(0);opacity:1}}` }; // Inicializar datos por defecto function initLocalStorage() { if(!localStorage.getItem('valeVane_admin_password')) { localStorage.setItem('valeVane_admin_password', btoa('admin123')); } if(!localStorage.getItem('valeVane_menu')) { localStorage.setItem('valeVane_menu', JSON.stringify({ "Entradas": [ {"nombre":"Tostones Rellenos","descripcion":"Con camarones y salsa criolla","precio":"$8.50","imagen":"https://placehold.co/100x100/d4af7a/1e2a2b?text=Tostones"}, {"nombre":"Croquetas de Jamón","descripcion":"Caseras, crujientes","precio":"$6.00","imagen":"https://placehold.co/100x100/d4af7a/1e2a2b?text=Croquetas"} ], "Platos fuertes": [ {"nombre":"Ropa Vieja","descripcion":"Carne deshebrada con arroz moro","precio":"$14.00","imagen":"https://placehold.co/100x100/d4af7a/1e2a2b?text=Ropa+Vieja"}, {"nombre":"Pescado a la Plancha","descripcion":"Acompañado de vegetales","precio":"$16.00","imagen":"https://placehold.co/100x100/d4af7a/1e2a2b?text=Pescado"} ], "Bebidas": [ {"nombre":"Mojito","descripcion":"Tradicional cubano","precio":"$5.00","imagen":"https://placehold.co/100x100/d4af7a/1e2a2b?text=Mojito"} ], "Postres": [ {"nombre":"Flan Casero","descripcion":"Con caramelo","precio":"$4.50","imagen":"https://placehold.co/100x100/d4af7a/1e2a2b?text=Flan"} ] })); } if(!localStorage.getItem('valeVane_galeria')) { localStorage.setItem('valeVane_galeria', JSON.stringify([ "https://images.unsplash.com/photo-1555396273-367ea4eb4db5?w=400", "https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=400", "https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=400" ])); } if(!localStorage.getItem('valeVane_info')) { localStorage.setItem('valeVane_info', JSON.stringify({ direccion: "4PC3+GQ8, La Habana", horario: "Cerrado · Abre domingo 09:00", telefono: "(07) 7947261", servicios: ["Bar", "A la moda", "Agradable", "Informal", "Relajado", "Grupos", "Turistas", "Ideal con niños"] })); } if(!localStorage.getItem('valeVane_opiniones_aprobadas')) { localStorage.setItem('valeVane_opiniones_aprobadas', JSON.stringify([])); } if(!localStorage.getItem('valeVane_opiniones_pendientes')) { localStorage.setItem('valeVane_opiniones_pendientes', JSON.stringify([])); } if(!localStorage.getItem('valeVane_reservas')) { localStorage.setItem('valeVane_reservas', JSON.stringify([])); } } let totalFiles = Object.keys(FILES).length; let filesCreated = 0; let installStarted = false; function updateProgress() { const percent = (filesCreated / totalFiles) * 100; document.getElementById('progressBar').style.width = percent + '%'; const fileListDiv = document.getElementById('fileList'); fileListDiv.innerHTML = `📁 Archivos generados: ${filesCreated} / ${totalFiles}
${Object.keys(FILES).slice(0, filesCreated).map(f => `✅ ${f}`).join('
')}`; if(filesCreated === totalFiles) { document.getElementById('installBtn').disabled = false; document.getElementById('installBtn').textContent = '🎉 ¡Instalación completa! Descargar ZIP'; document.getElementById('result').innerHTML = `
✅ ¡Todos los archivos han sido generados exitosamente!
📂 Se han creado ${totalFiles} archivos en la carpeta "vale-vane-restaurante"
🔐 Contraseña admin: admin123
🚀 Abre el archivo index.html para ver tu sitio web
`; document.getElementById('downloadZipBtn')?.addEventListener('click', downloadAllFiles); } } function createFile(filename, content) { return new Promise((resolve) => { // En un entorno real, esto crearía archivos físicos // Como estamos en el navegador, simulamos la creación setTimeout(() => { filesCreated++; updateProgress(); resolve(); }, 50); }); } async function installAll() { if(installStarted) return; installStarted = true; const btn = document.getElementById('installBtn'); btn.disabled = true; btn.innerHTML = ' Instalando archivos...'; initLocalStorage(); for(const [filename, content] of Object.entries(FILES)) { await createFile(filename, content); } } function downloadAllFiles() { // Crear un ZIP con todos los archivos const zip = new JSZip(); for(const [filename, content] of Object.entries(FILES)) { zip.file(filename, content); } zip.generateAsync({type: "blob"}).then(function(blob) { const link = document.createElement('a'); const url = URL.createObjectURL(blob); link.href = url; link.download = "vale-vane-restaurante.zip"; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); }); } document.getElementById('installBtn').addEventListener('click', installAll); // Cargar JSZip si es necesario const script = document.createElement('script'); script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js'; script.onload = () => { console.log('JSZip cargado'); }; document.head.appendChild(script); updateProgress();