Files
gkachele-saas/backups/backup-20260114-085602/local/demo/templates/landing_real.html
2026-01-17 11:40:17 +01:00

1443 lines
63 KiB
HTML

<!DOCTYPE html>
<!--
============================================================================
PROPRIEDAD INTELECTUAL - GKACHELE
============================================================================
Copyright (c) 2025 GKACHELE
Desarrollado desde: 3 de noviembre de 2025
Este código y su estructura son propiedad exclusiva de GKACHELE.
Todos los derechos reservados.
PROPIEDAD:
- Código HTML/CSS/JavaScript: Propiedad de GKACHELE
- Sistema de automatización: Propiedad de GKACHELE
- Estructura y diseño: Propiedad de GKACHELE
- Lógica de negocio: Propiedad de GKACHELE
PROHIBICIONES:
- Prohibida la copia, reproducción o distribución sin autorización
- Prohibida la modificación no autorizada
- Prohibido el uso comercial sin licencia
CONTACTO: gkachele.duckdns.org
============================================================================
-->
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes" />
<!-- Security Headers -->
<meta http-equiv="X-Content-Type-Options" content="nosniff" />
<meta http-equiv="X-Frame-Options" content="DENY" />
<meta http-equiv="X-XSS-Protection" content="1; mode=block" />
<meta http-equiv="Referrer-Policy" content="strict-origin-when-cross-origin" />
<meta http-equiv="Permissions-Policy" content="geolocation=(), microphone=(), camera=()" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdnjs.cloudflare.com https://fonts.googleapis.com; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com https://cdnjs.cloudflare.com; img-src 'self' data: https:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" />
<!-- Cache Control -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<!-- SEO Meta Tags -->
<meta name="author" content="GKACHELE" />
<meta name="generator" content="GKACHELE Sistema Automatizado - Copyright 2025" />
<meta name="copyright" content="Copyright (c) 2025 GKACHELE - Todos los derechos reservados" />
<title>GKACHELE™ | Desarrollo Web Premium</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<!-- Navigation Sticky -->
<nav class="nav-sticky">
<div class="nav-container">
<div class="nav-logo">
<a href="index.html">GKACHELE™</a>
</div>
<div class="nav-menu">
<a href="#planes" class="nav-link">Planes</a>
<a href="#demos" class="nav-link">Demos</a>
<a href="#contacto" class="nav-link">Contacto</a>
</div>
<div class="nav-social">
<a href="https://www.facebook.com/gkachele" target="_blank" title="Facebook"><i class="fab fa-facebook-f"></i></a>
<a href="https://www.instagram.com/gkachele" target="_blank" title="Instagram"><i class="fab fa-instagram"></i></a>
<a href="https://www.youtube.com/@gkachele" target="_blank" title="YouTube"><i class="fab fa-youtube"></i></a>
<a href="https://www.tiktok.com/@gkachele" target="_blank" title="TikTok"><i class="fab fa-tiktok"></i></a>
</div>
</div>
</nav>
<!-- Hero Section -->
<section class="hero-section">
<div class="hero-bg-overlay"></div>
<div class="hero-content">
<h1 class="hero-title">GKACHELE™</h1>
<p class="hero-subtitle">Desarrollo Web Premium</p>
<p class="hero-description">Estamos listos para ayudarte a crear tu sitio moderno, rápido y personalizado.</p>
</div>
</section>
<!-- Plans Section - Acordeón Desplegable -->
<section id="planes" class="plans-section">
<div class="plans-bg-overlay"></div>
<div class="container-large">
<h2 class="section-title">Nuestros Planes</h2>
<!-- Plans Accordion -->
<div class="plans-accordion">
<!-- Base Plan -->
<div class="plan-accordion-item" data-plan="base">
<button class="plan-accordion-header">
<div class="plan-header-content">
<h3>Base</h3>
<p class="plan-tagline">Simple, efectivo y profesional</p>
</div>
<i class="fas fa-chevron-down plan-chevron"></i>
</button>
<div class="plan-accordion-body">
<div class="plan-card-body">
<h4>¿Qué incluye?</h4>
<ul>
<li>✅ Sitio web de una página</li>
<li>✅ Diseño limpio y profesional</li>
<li>✅ Información de contacto</li>
<li>✅ Enlaces a redes sociales</li>
<li>✅ Responsive (móvil y desktop)</li>
<li>✅ Hosting gratuito</li>
<li>✅ Dominio personalizado</li>
</ul>
<h4>Personalización</h4>
<ul>
<li>🎨 Color principal personalizado</li>
<li>✍️ Tipografía a elección</li>
<li>📝 Textos personalizados</li>
</ul>
<p class="plan-ideal"><strong>Ideal para:</strong> Profesionales independientes, pequeños comercios, páginas institucionales básicas.</p>
<div class="qr-mini-card">
<img src="https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=https://gkachele.duckdns.org" alt="QR Base">
<p>Comparte este plan</p>
</div>
<div class="plan-buttons-group">
<button onclick="openForm('base'); return false;" class="plan-btn" style="width: 100%; display: block; text-align: center; text-decoration: none; border: none; cursor: pointer;">
Solicitar Plan Base
</button>
</div>
</div>
</div>
</div>
<!-- Pro Plan -->
<div class="plan-accordion-item" data-plan="pro">
<button class="plan-accordion-header">
<div class="plan-header-content">
<h3>Pro</h3>
<p class="plan-tagline">Visual, dinámico y moderno</p>
</div>
<i class="fas fa-chevron-down plan-chevron"></i>
</button>
<div class="plan-accordion-body">
<div class="plan-card-body">
<h4>¿Qué incluye?</h4>
<ul>
<li>✅ Sitio web multipágina</li>
<li>✅ Animaciones suaves y efectos visuales</li>
<li>✅ Galería de imágenes o portafolio</li>
<li>✅ Formulario de contacto funcional</li>
<li>✅ Responsive avanzado</li>
<li>✅ Hosting gratuito</li>
<li>✅ Dominio personalizado</li>
</ul>
<h4>Personalización</h4>
<ul>
<li>🎨 Paleta de colores personalizada</li>
<li>✍️ Tipografía profesional</li>
<li>🧩 Secciones a medida</li>
</ul>
<p class="plan-ideal"><strong>Ideal para:</strong> Marcas personales, portfolios creativos, negocios que quieren destacar visualmente.</p>
<div class="qr-mini-card">
<img src="https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=https://gkachele.duckdns.org#planes" alt="QR Pro">
<p>Comparte este plan</p>
</div>
<div class="plan-buttons-group">
<button onclick="openForm('pro'); return false;" class="plan-btn" style="width: 100%; display: block; text-align: center; text-decoration: none; border: none; cursor: pointer;">
Solicitar Plan Pro
</button>
</div>
</div>
</div>
</div>
<!-- Premium Plan -->
<div class="plan-accordion-item" data-plan="premium">
<button class="plan-accordion-header">
<div class="plan-header-content">
<h3>Premium</h3>
<p class="plan-tagline">Experiencia completa y profesional</p>
</div>
<i class="fas fa-chevron-down plan-chevron"></i>
</button>
<div class="plan-accordion-body">
<div class="plan-card-body">
<h4>¿Qué incluye?</h4>
<ul>
<li>✅ Sitio web completo y escalable</li>
<li>✅ Integración con redes sociales y herramientas externas</li>
<li>✅ SEO optimizado</li>
<li>✅ Panel de administración (opcional)</li>
<li>✅ Hosting y dominio incluidos</li>
<li>✅ Soporte técnico personalizado</li>
</ul>
<h4>Personalización</h4>
<ul>
<li>🎨 Diseño a medida</li>
<li>📊 Integración con analítica</li>
<li>🔒 Seguridad avanzada</li>
</ul>
<p class="plan-ideal"><strong>Ideal para:</strong> Empresas, proyectos grandes, tiendas online, instituciones con necesidades específicas.</p>
<div class="qr-mini-card">
<img src="https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=https://gkachele.duckdns.org#planes" alt="QR Premium">
<p>Comparte este plan</p>
</div>
<div class="plan-buttons-group">
<button onclick="openForm('premium'); return false;" class="plan-btn premium-btn" style="width: 100%; display: block; text-align: center; text-decoration: none; border: none; cursor: pointer;">
Solicitar Plan Premium
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Formulario de Pedido de Plan -->
<div id="planFormModal" class="modal-form" style="display: none;">
<div class="modal-form-content">
<div class="modal-form-header">
<h2>Solicitar Plan <span id="selectedPlanName"></span></h2>
<button type="button" class="modal-close" onclick="closeForm()">&times;</button>
</div>
<form id="planRequestForm" onsubmit="event.preventDefault(); generatePreview(); return false;">
<input type="hidden" id="selectedPlan" name="plan" required>
<input type="hidden" id="templateVariation" name="templateVariation" value="">
<div class="form-group">
<label for="nombre">Nombre Completo *</label>
<input type="text" id="nombre" name="nombre" required placeholder="Tu nombre completo">
</div>
<div class="form-group">
<label for="rubro">Rubro/Negocio *</label>
<select id="rubro" name="rubro" required onchange="actualizarCamposRubro()">
<option value="">Seleccionar rubro...</option>
<option value="restaurante">Restaurante</option>
<option value="danza">Danza</option>
<option value="cosmeticos">Cosméticos</option>
<option value="despachos">Despachos</option>
<option value="gimnasios">Gimnasios</option>
<option value="educacion">Educación</option>
<option value="base">Base (Otro)</option>
</select>
</div>
<!-- Campos ocultos para mantener compatibilidad con generatePreview() -->
<input type="hidden" id="email" name="email" value="">
<input type="hidden" id="telefono" name="telefono" value="">
<!-- Campos específicos por rubro (ocultos - se completan en admin.html del preview) -->
<div id="campos-rubro-especificos" style="display: none !important;">
<hr style="margin: 20px 0; border: 1px solid #e0e0e0;">
<h3 style="margin-bottom: 15px; color: #2c3e50;" id="titulo-campos-rubro">Información Específica del Rubro</h3>
<!-- Campos para Restaurante -->
<div id="campos-restaurante" class="campos-rubro" style="display: none;">
<div class="form-group">
<label for="menu_url">URL del Menú (opcional)</label>
<input type="url" id="menu_url" name="menu_url" placeholder="https://ejemplo.com/menu.pdf">
</div>
<div class="form-group">
<label for="horarios">Horarios de Atención</label>
<input type="text" id="horarios" name="horarios" placeholder="Ej: Lunes a Viernes 12:00-15:00 y 19:00-23:00">
</div>
<div class="form-group">
<label for="reservas">Sistema de Reservas</label>
<input type="text" id="reservas" name="reservas" placeholder="Ej: WhatsApp, teléfono, online">
</div>
<div class="form-group">
<label for="capacidad">Capacidad (opcional)</label>
<input type="text" id="capacidad" name="capacidad" placeholder="Ej: 50 personas">
</div>
<div class="form-group">
<label for="especialidad_culinaria">Especialidad Culinaria</label>
<input type="text" id="especialidad_culinaria" name="especialidad_culinaria" placeholder="Ej: Cocina italiana, Parrilla, Sushi">
</div>
</div>
<!-- Campos para Danza -->
<div id="campos-danza" class="campos-rubro" style="display: none;">
<div class="form-group">
<label for="clases">Tipos de Clases</label>
<input type="text" id="clases" name="clases" placeholder="Ej: Ballet, Salsa, Hip Hop, Contemporáneo">
</div>
<div class="form-group">
<label for="horarios_clases">Horarios de Clases</label>
<input type="text" id="horarios_clases" name="horarios_clases" placeholder="Ej: Lunes y Miércoles 18:00-20:00">
</div>
<div class="form-group">
<label for="niveles">Niveles</label>
<input type="text" id="niveles" name="niveles" placeholder="Ej: Principiante, Intermedio, Avanzado">
</div>
<div class="form-group">
<label for="estilos">Estilos de Danza</label>
<input type="text" id="estilos" name="estilos" placeholder="Ej: Clásico, Moderno, Urbano">
</div>
<div class="form-group">
<label for="profesores">Profesores (opcional)</label>
<input type="text" id="profesores" name="profesores" placeholder="Ej: María García, Juan Pérez">
</div>
</div>
<!-- Campos para Cosméticos -->
<div id="campos-cosmeticos" class="campos-rubro" style="display: none;">
<div class="form-group">
<label for="productos_url">URL del Catálogo (opcional)</label>
<input type="url" id="productos_url" name="productos_url" placeholder="https://ejemplo.com/catalogo">
</div>
<div class="form-group">
<label for="catalogo">Tipo de Catálogo</label>
<input type="text" id="catalogo" name="catalogo" placeholder="Ej: Maquillaje, Cuidado facial, Perfumes">
</div>
<div class="form-group">
<label for="categorias">Categorías de Productos</label>
<input type="text" id="categorias" name="categorias" placeholder="Ej: Labiales, Bases, Sombras">
</div>
<div class="form-group">
<label for="ofertas">Ofertas Especiales (opcional)</label>
<input type="text" id="ofertas" name="ofertas" placeholder="Ej: 2x1 en labiales, 20% descuento">
</div>
<div class="form-group">
<label for="envios">Información de Envíos</label>
<input type="text" id="envios" name="envios" placeholder="Ej: Envío gratis desde $5000, Retiro en local">
</div>
</div>
<!-- Campos para Despachos -->
<div id="campos-despachos" class="campos-rubro" style="display: none;">
<div class="form-group">
<label for="propuestas">Servicios Principales</label>
<textarea id="propuestas" name="propuestas" rows="3" placeholder="Describe los servicios principales del despacho (asesoría legal, contable, etc.)"></textarea>
</div>
<div class="form-group">
<label for="agenda">Agenda de Actividades (opcional)</label>
<input type="text" id="agenda" name="agenda" placeholder="Ej: Consultas semanales, reuniones con clientes">
</div>
<div class="form-group">
<label for="eventos">Próximos Eventos (opcional)</label>
<input type="text" id="eventos" name="eventos" placeholder="Ej: Charla el 15/03, Seminario el 20/03">
</div>
<div class="form-group">
<label for="noticias">Noticias/Comunicados (opcional)</label>
<input type="text" id="noticias" name="noticias" placeholder="URL o fuente de noticias">
</div>
</div>
<!-- Campos para Gimnasios -->
<div id="campos-gimnasios" class="campos-rubro" style="display: none;">
<div class="form-group">
<label for="planes_fitness">Planes de Entrenamiento</label>
<input type="text" id="planes_fitness" name="planes_fitness" placeholder="Ej: Básico, Premium, Personalizado">
</div>
<div class="form-group">
<label for="horarios_fitness">Horarios</label>
<input type="text" id="horarios_fitness" name="horarios_fitness" placeholder="Ej: Lunes a Sábado 6:00-22:00">
</div>
<div class="form-group">
<label for="entrenadores">Entrenadores (opcional)</label>
<input type="text" id="entrenadores" name="entrenadores" placeholder="Ej: Personal trainers certificados">
</div>
<div class="form-group">
<label for="instalaciones">Instalaciones (opcional)</label>
<input type="text" id="instalaciones" name="instalaciones" placeholder="Ej: Gimnasio completo, piscina, sauna">
</div>
<div class="form-group">
<label for="precios">Precios (opcional)</label>
<input type="text" id="precios" name="precios" placeholder="Ej: Desde $5000/mes">
</div>
</div>
<!-- Campos para Educación -->
<div id="campos-educacion" class="campos-rubro" style="display: none;">
<div class="form-group">
<label for="cursos">Cursos Ofrecidos</label>
<input type="text" id="cursos" name="cursos" placeholder="Ej: Inglés, Programación, Diseño">
</div>
<div class="form-group">
<label for="horarios_educacion">Horarios de Clases</label>
<input type="text" id="horarios_educacion" name="horarios_educacion" placeholder="Ej: Mañana, tarde, noche">
</div>
<div class="form-group">
<label for="niveles_educacion">Niveles</label>
<input type="text" id="niveles_educacion" name="niveles_educacion" placeholder="Ej: Inicial, Intermedio, Avanzado">
</div>
<div class="form-group">
<label for="profesores_educacion">Profesores (opcional)</label>
<input type="text" id="profesores_educacion" name="profesores_educacion" placeholder="Ej: Docentes certificados">
</div>
<div class="form-group">
<label for="inscripcion">Forma de Inscripción</label>
<input type="text" id="inscripcion" name="inscripcion" placeholder="Ej: Online, presencial, WhatsApp">
</div>
</div>
</div>
<!-- Campos ocultos para mantener compatibilidad con generatePreview() -->
<input type="hidden" id="colores" name="colores" value="">
<input type="hidden" id="tipografia" name="tipografia" value="">
<input type="hidden" id="logo_url" name="logo_url" value="">
<input type="hidden" id="descripcion" name="descripcion" value="">
<input type="hidden" id="facebook" name="facebook" value="">
<input type="hidden" id="instagram" name="instagram" value="">
<input type="hidden" id="twitter" name="twitter" value="">
<input type="hidden" id="whatsapp" name="whatsapp" value="">
<input type="hidden" id="youtube" name="youtube" value="">
<input type="hidden" id="tiktok" name="tiktok" value="">
<input type="hidden" id="direccion_calle" name="direccion_calle" value="">
<input type="hidden" id="direccion_ciudad" name="direccion_ciudad" value="">
<input type="hidden" id="direccion_provincia" name="direccion_provincia" value="">
<input type="hidden" id="direccion_cp" name="direccion_cp" value="">
<input type="hidden" id="dominio" name="dominio" value="">
<div class="form-actions">
<button type="button" class="btn-cancel" onclick="closeForm()">Cancelar</button>
<button type="button" class="btn-submit" onclick="generatePreview()" id="btnPreview" style="width: 100%;">
<i class="fas fa-rocket"></i> Generar Preview
</button>
</div>
</form>
</div>
</div>
<!-- Modal de Previews -->
<div id="previewsModal" class="previews-modal" style="display: none;">
<div class="previews-modal-content">
<div class="previews-modal-header">
<h2>Previews - Plan <span id="previewPlanName"></span></h2>
<button type="button" class="modal-close" onclick="closePreviews()">&times;</button>
</div>
<div class="previews-filters">
<div class="filter-group">
<label for="filterRubro">Filtrar por Rubro:</label>
<select id="filterRubro" onchange="filterPreviews()">
<!-- Las opciones se generan dinámicamente según los previews disponibles -->
</select>
</div>
</div>
<div class="previews-grid" id="previewsGrid">
<!-- Las cards se generarán dinámicamente con JavaScript -->
</div>
</div>
</div>
<!-- Modal de Screenshot Grande (Lightbox) -->
<div id="screenshotLightbox" class="screenshot-lightbox" style="display: none;">
<div class="lightbox-content">
<span class="lightbox-close" onclick="closeLightbox()">&times;</span>
<img id="lightboxImage" src="" alt="Preview" />
<div class="lightbox-info">
<h3 id="lightboxTitle"></h3>
<p id="lightboxDescription"></p>
<button class="btn-request-design" onclick="requestDesign()">
<i class="fas fa-check"></i> Solicitar este diseño
</button>
</div>
</div>
</div>
<!-- Demos Section -->
<section id="demos" class="demos-section">
<div class="demos-bg-overlay"></div>
<div class="container-large">
<h2 class="section-title">Proyectos Demo</h2>
<p class="section-subtitle">Ejemplos de sitios web que hemos creado</p>
<div class="demos-grid">
<!-- Demo 1: Blow Dance -->
<div class="demo-card">
<div class="demo-image">
<div style="width:100%;height:300px;background:linear-gradient(135deg,#e91e63 0%,#c2185b 100%);display:flex;align-items:center;justify-content:center;color:white;font-size:2rem;font-weight:bold;">💃 Blow Dance</div>
<div class="demo-overlay">
<a href="https://blowdance.duckdns.org" target="_blank" class="demo-btn">
<i class="fas fa-external-link-alt"></i> Ver Sitio
</a>
</div>
</div>
<div class="demo-info">
<h3>Blow Dance</h3>
<p class="demo-category">💃 Escuela de Danza</p>
<p class="demo-plan">Plan: <span class="badge-pro">Pro</span></p>
<p class="demo-description">Sitio web profesional para escuela de danza con galerías, videos y sistema de inscripción.</p>
</div>
</div>
<!-- Demo 2: Dalmau Intendente -->
<div class="demo-card">
<div class="demo-image">
<div style="width:100%;height:300px;background:linear-gradient(135deg,#1e40af 0%,#1e3a8a 100%);display:flex;align-items:center;justify-content:center;color:white;font-size:2rem;font-weight:bold;">🗳️ Dalmau</div>
<div class="demo-overlay">
<a href="https://dalmau-intendente.duckdns.org" target="_blank" class="demo-btn">
<i class="fas fa-external-link-alt"></i> Ver Sitio
</a>
</div>
</div>
<div class="demo-info">
<h3>Dalmau Intendente</h3>
<p class="demo-category">⚖️ Despacho Profesional</p>
<p class="demo-plan">Plan: <span class="badge-base">Base</span></p>
<p class="demo-description">Landing page profesional para despachos de abogados y contadores con información clara y llamados a la acción.</p>
</div>
</div>
<!-- Demo 3: GKACHELE Portfolio -->
<div class="demo-card">
<div class="demo-image">
<div style="width:100%;height:300px;background:linear-gradient(135deg,#ff6b35 0%,#e55a28 100%);display:flex;align-items:center;justify-content:center;color:white;font-size:2rem;font-weight:bold;">💼 GKACHELE</div>
<div class="demo-overlay">
<a href="https://gkachele.duckdns.org" target="_blank" class="demo-btn">
<i class="fas fa-external-link-alt"></i> Ver Sitio
</a>
</div>
</div>
<div class="demo-info">
<h3>GKACHELE™</h3>
<p class="demo-category">💼 Portfolio Profesional</p>
<p class="demo-plan">Plan: <span class="badge-premium">Premium</span></p>
<p class="demo-description">Sitio web premium con diseño moderno, animaciones y sistema de gestión avanzado.</p>
</div>
</div>
</div>
<!-- Video Demo - DESACTIVADO hasta tener YouTube -->
<!--
<div class="video-demo-section">
<h3>Video Demostrativo</h3>
<div class="video-container">
<div class="video-placeholder">
<i class="fas fa-play-circle"></i>
<p>Próximamente: Video demo de nuestros proyectos</p>
<small>Sube tu video a YouTube y pega el link aquí</small>
</div>
</div>
</div>
-->
</div>
</section>
<!-- QR Section -->
<section class="qr-section">
<div class="qr-bg-overlay"></div>
<div class="container-large">
<div class="qr-card">
<h3>Comparte tu sitio</h3>
<img src="https://api.qrserver.com/v1/create-qr-code/?size=250x250&data=https://gkachele.duckdns.org" alt="QR Code GKACHELE™" class="qr-image">
<p>Escanea el código QR para compartir</p>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contacto" class="contact-section">
<div class="contact-bg-overlay"></div>
<div class="container-large">
<h2 class="section-title">Contacto</h2>
<div class="contact-grid">
<div class="contact-cards">
<a href="tel:+5491123456789" class="contact-card">
<i class="fas fa-phone"></i>
<span>+54 9 11 2345 6789</span>
</a>
<a href="mailto:contacto@gkachele.com" class="contact-card">
<i class="fas fa-envelope"></i>
<span>contacto@gkachele.com</span>
</a>
<a href="https://wa.me/5491123456789?text=Hola!%20Me%20interesa%20conocer%20más%20sobre%20GKACHELE" target="_blank" class="contact-card whatsapp-card">
<i class="fab fa-whatsapp"></i>
<span>WhatsApp</span>
</a>
</div>
<div class="social-card">
<h3>Redes Sociales</h3>
<div class="social-links-grid">
<a href="https://www.facebook.com/gkachele" target="_blank" class="social-link" title="Facebook">
<i class="fab fa-facebook-f"></i>
</a>
<a href="https://www.instagram.com/gkachele" target="_blank" class="social-link" title="Instagram">
<i class="fab fa-instagram"></i>
</a>
<a href="https://www.youtube.com/@gkachele" target="_blank" class="social-link" title="YouTube">
<i class="fab fa-youtube"></i>
</a>
<a href="https://www.tiktok.com/@gkachele" target="_blank" class="social-link" title="TikTok">
<i class="fab fa-tiktok"></i>
</a>
</div>
</div>
</div>
</div>
</section>
<!-- WhatsApp Float Button -->
<a href="https://wa.me/5491123456789?text=Hola!%20Me%20interesa%20conocer%20más%20sobre%20GKACHELE" target="_blank" class="whatsapp-float">
<i class="fab fa-whatsapp"></i>
</a>
<!-- Scroll to Top Button -->
<button class="scroll-to-top" id="scrollToTop" aria-label="Ir arriba">
<i class="fas fa-arrow-up"></i>
</button>
<!-- Footer -->
<footer class="footer-main">
<div class="footer-bg-overlay"></div>
<div class="container-large">
<p>&copy; 2025 GKACHELE™. Todos los derechos reservados.</p>
<span class="gkachele-watermark" aria-hidden="true">
Desarrollado desde noviembre 2025 por GKACHELE
</span>
<p style="font-size: 0.7rem; color: rgba(255, 255, 255, 0.5); margin-top: 0.25rem; opacity: 0.7;">
Código propiedad de GKACHELE © 2025 - Prohibida su reproducción sin autorización
</p>
</div>
</footer>
<script>
// Endpoints locales - sin dependencias externas
// Plan Accordion - Desplegable Premium
const accordionItems = document.querySelectorAll('.plan-accordion-item');
accordionItems.forEach(item => {
const header = item.querySelector('.plan-accordion-header');
const body = item.querySelector('.plan-accordion-body');
const chevron = item.querySelector('.plan-chevron');
header.addEventListener('click', () => {
const isActive = item.classList.contains('active');
// Cerrar todos los items con transición suave
accordionItems.forEach(otherItem => {
if (otherItem !== item) {
const otherBody = otherItem.querySelector('.plan-accordion-body');
const otherChevron = otherItem.querySelector('.plan-chevron');
const wasOtherActive = otherItem.classList.contains('active');
if (wasOtherActive) {
// Cerrar con transición
otherItem.classList.remove('active');
setTimeout(() => {
otherBody.style.maxHeight = null;
otherChevron.style.transform = 'rotate(0deg)';
}, 50);
}
}
});
// Toggle del item actual con transición
if (isActive) {
// Cerrar el item actual
item.classList.remove('active');
setTimeout(() => {
body.style.maxHeight = null;
chevron.style.transform = 'rotate(0deg)';
}, 50);
} else {
// Abrir el item actual
item.classList.add('active');
body.style.maxHeight = body.scrollHeight + 'px';
chevron.style.transform = 'rotate(180deg)';
// Smooth scroll al item expandido con delay para la transición
setTimeout(() => {
item.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}, 300);
}
});
});
// Asegurar que todos los acordeones empiecen cerrados
// Forzar que ningún item tenga 'active' al cargar la página
accordionItems.forEach(item => {
item.classList.remove('active');
const body = item.querySelector('.plan-accordion-body');
const chevron = item.querySelector('.plan-chevron');
body.style.maxHeight = null;
chevron.style.transform = 'rotate(0deg)';
});
// Formulario de Pedido de Plan
function openForm(planType) {
const modal = document.getElementById('planFormModal');
const selectedPlan = document.getElementById('selectedPlan');
const selectedPlanName = document.getElementById('selectedPlanName');
const planNames = {
'base': 'Base',
'pro': 'Pro',
'premium': 'Premium'
};
selectedPlan.value = planType;
selectedPlanName.textContent = planNames[planType];
modal.style.display = 'flex';
document.body.style.overflow = 'hidden';
// Desactivar temporalmente el cierre por clic fuera
modal.dataset.preventClose = 'true';
}
function closeForm() {
const modal = document.getElementById('planFormModal');
modal.style.display = 'none';
document.body.style.overflow = 'auto';
document.getElementById('planRequestForm').reset();
// Ocultar campos de rubro al cerrar
document.getElementById('campos-rubro-especificos').style.display = 'none';
document.querySelectorAll('.campos-rubro').forEach(el => el.style.display = 'none');
// Reactivar el cierre por clic fuera
delete modal.dataset.preventClose;
}
// Función para actualizar campos según rubro seleccionado
function actualizarCamposRubro() {
// NO mostrar campos específicos del rubro - se completan en admin.html del preview
const contenedor = document.getElementById('campos-rubro-especificos');
if (contenedor) {
contenedor.style.display = 'none !important';
}
// Ocultar todos los campos de rubro
document.querySelectorAll('.campos-rubro').forEach(el => el.style.display = 'none');
// Prellenar colores y tipografía sugeridos según rubro
const rubrosData = {
restaurante: { colores: 'Rojo y naranja', tipografia: 'Roboto' },
danza: { colores: 'Rosa y magenta', tipografia: 'Poppins' },
cosmeticos: { colores: 'Morado y violeta', tipografia: 'Montserrat' },
despachos: { colores: 'Azul y azul oscuro', tipografia: 'Georgia' },
gimnasios: { colores: 'Rojo y rojo oscuro', tipografia: 'Roboto' },
educacion: { colores: 'Azul y azul claro', tipografia: 'Open Sans' }
};
if (rubrosData[rubro]) {
if (!document.getElementById('colores').value) {
document.getElementById('colores').value = rubrosData[rubro].colores;
}
if (!document.getElementById('tipografia').value) {
document.getElementById('tipografia').value = rubrosData[rubro].tipografia;
}
}
}
// NOTA: handleFormSubmit ahora se llama desde admin.html cuando el usuario hace clic en "Completar Solicitud Final"
// Esta función se mantiene por compatibilidad pero no se usa desde el formulario inicial
async function handleFormSubmit(event) {
event.preventDefault();
event.stopPropagation();
const formData = new FormData(event.target);
const data = Object.fromEntries(formData);
// Generar nombre de dominio si no se proporcionó
const dominio = data.dominio || data.nombre.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
// Recopilar campos específicos del rubro
const camposRubro = {};
const rubro = data.rubro;
// Campos específicos por rubro
if (rubro === 'restaurante') {
if (data.menu_url) camposRubro.menu_url = data.menu_url;
if (data.horarios) camposRubro.horarios = data.horarios;
if (data.reservas) camposRubro.reservas = data.reservas;
if (data.capacidad) camposRubro.capacidad = data.capacidad;
if (data.especialidad_culinaria) camposRubro.especialidad_culinaria = data.especialidad_culinaria;
} else if (rubro === 'danza') {
if (data.clases) camposRubro.clases = data.clases;
if (data.horarios_clases) camposRubro.horarios_clases = data.horarios_clases;
if (data.niveles) camposRubro.niveles = data.niveles;
if (data.estilos) camposRubro.estilos = data.estilos;
if (data.profesores) camposRubro.profesores = data.profesores;
} else if (rubro === 'cosmeticos') {
if (data.productos_url) camposRubro.productos_url = data.productos_url;
if (data.catalogo) camposRubro.catalogo = data.catalogo;
if (data.categorias) camposRubro.categorias = data.categorias;
if (data.ofertas) camposRubro.ofertas = data.ofertas;
if (data.envios) camposRubro.envios = data.envios;
} else if (rubro === 'despachos') {
if (data.propuestas) camposRubro.propuestas = data.propuestas;
if (data.agenda) camposRubro.agenda = data.agenda;
if (data.eventos) camposRubro.eventos = data.eventos;
if (data.noticias) camposRubro.noticias = data.noticias;
} else if (rubro === 'gimnasios') {
if (data.planes_fitness) camposRubro.planes = data.planes_fitness;
if (data.horarios_fitness) camposRubro.horarios = data.horarios_fitness;
if (data.entrenadores) camposRubro.entrenadores = data.entrenadores;
if (data.instalaciones) camposRubro.instalaciones = data.instalaciones;
if (data.precios) camposRubro.precios = data.precios;
} else if (rubro === 'educacion') {
if (data.cursos) camposRubro.cursos = data.cursos;
if (data.horarios_educacion) camposRubro.horarios = data.horarios_educacion;
if (data.niveles_educacion) camposRubro.niveles = data.niveles_educacion;
if (data.profesores_educacion) camposRubro.profesores = data.profesores_educacion;
if (data.inscripcion) camposRubro.inscripcion = data.inscripcion;
}
// Crear JSON con formato estructurado
const jsonData = {
plan: data.plan,
cliente: {
nombre_completo: data.nombre,
email: data.email,
telefono: data.telefono,
rubro: data.rubro
},
personalizacion: {
colores_preferidos: data.colores || '',
tipografia: data.tipografia || null,
logo_url: data.logo_url || null,
logo_upload: null
},
redes_sociales: {
facebook: data.facebook || null,
instagram: data.instagram || null,
twitter: data.twitter || null,
youtube: data.youtube || null,
tiktok: data.tiktok || null,
linkedin: null,
whatsapp: data.whatsapp || null
},
direccion: {
calle: data.direccion_calle || '',
ciudad: data.direccion_ciudad || '',
provincia: data.direccion_provincia || '',
codigo_postal: data.direccion_cp || '',
pais: 'Argentina'
},
rubro_especifico: Object.keys(camposRubro).length > 0 ? camposRubro : null,
dominio: {
preferido: dominio,
generado: `${dominio}.gkachele.duckdns.org`
},
descripcion: data.descripcion || '',
estado: 'pendiente_pago',
fecha_creacion: new Date().toISOString()
};
// Mostrar loading
const submitBtn = event.target.querySelector('button[type="submit"]');
const originalText = submitBtn.textContent;
submitBtn.disabled = true;
submitBtn.textContent = 'Enviando...';
try {
const payload = new URLSearchParams();
const datosEnvio = {
plan: jsonData.plan,
nombre: jsonData.cliente.nombre_completo,
email: jsonData.cliente.email,
telefono: jsonData.cliente.telefono,
rubro: jsonData.cliente.rubro,
dominio: jsonData.dominio.generado,
descripcion: jsonData.descripcion,
colores: jsonData.personalizacion.colores_preferidos,
tipografia: jsonData.personalizacion.tipografia || '',
logo_url: jsonData.personalizacion.logo_url || '',
redes: JSON.stringify(jsonData.redes_sociales),
whatsapp: jsonData.redes_sociales.whatsapp || '',
rubro_especifico: JSON.stringify(jsonData.rubro_especifico || {}),
templateVariation: data.templateVariation || '',
estado: jsonData.estado
};
Object.entries(datosEnvio).forEach(([clave, valor]) => {
payload.append(clave, valor ?? '');
});
// Solicitud se enviará desde el preview - función deshabilitada por ahora
// TODO: Implementar endpoint /api/request_create en Flask
alert('✅ Redirigiendo al formulario de preview...\n\n' +
'📋 Completa el formulario para generar tu preview.');
// Redirigir al formulario de preview
const plan = document.getElementById('selectedPlan')?.value || 'base';
const rubro = document.getElementById('rubro')?.value || 'gimnasio';
window.location.href = `/register?plan=${plan}&rubro=${rubro}`;
submitBtn.disabled = false;
submitBtn.textContent = originalText;
closeForm();
event.target.reset();
} catch (error) {
console.error('Error al enviar solicitud:', error);
alert('❌ Error al enviar la solicitud. Por favor, intenta nuevamente.');
submitBtn.disabled = false;
submitBtn.textContent = originalText;
}
}
// Generar preview dinámico antes de enviar
async function generatePreview() {
const form = document.getElementById('planRequestForm');
if (!form.checkValidity()) {
form.reportValidity();
return;
}
const formData = new FormData(form);
const data = Object.fromEntries(formData);
// Generar nombre de dominio si no se proporcionó
const dominio = data.dominio || data.nombre.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
// Recopilar campos específicos del rubro (mismo código que handleFormSubmit)
const camposRubro = {};
const rubro = data.rubro;
if (rubro === 'restaurante') {
if (data.menu_url) camposRubro.menu_url = data.menu_url;
if (data.horarios) camposRubro.horarios = data.horarios;
if (data.reservas) camposRubro.reservas = data.reservas;
if (data.capacidad) camposRubro.capacidad = data.capacidad;
if (data.especialidad_culinaria) camposRubro.especialidad_culinaria = data.especialidad_culinaria;
} else if (rubro === 'danza') {
if (data.clases) camposRubro.clases = data.clases;
if (data.horarios_clases) camposRubro.horarios_clases = data.horarios_clases;
if (data.niveles) camposRubro.niveles = data.niveles;
if (data.estilos) camposRubro.estilos = data.estilos;
if (data.profesores) camposRubro.profesores = data.profesores;
} else if (rubro === 'cosmeticos') {
if (data.productos_url) camposRubro.productos_url = data.productos_url;
if (data.catalogo) camposRubro.catalogo = data.catalogo;
if (data.categorias) camposRubro.categorias = data.categorias;
if (data.ofertas) camposRubro.ofertas = data.ofertas;
if (data.envios) camposRubro.envios = data.envios;
} else if (rubro === 'despachos') {
if (data.propuestas) camposRubro.propuestas = data.propuestas;
if (data.agenda) camposRubro.agenda = data.agenda;
if (data.eventos) camposRubro.eventos = data.eventos;
if (data.noticias) camposRubro.noticias = data.noticias;
} else if (rubro === 'gimnasios') {
if (data.planes_fitness) camposRubro.planes = data.planes_fitness;
if (data.horarios_fitness) camposRubro.horarios = data.horarios_fitness;
if (data.entrenadores) camposRubro.entrenadores = data.entrenadores;
if (data.instalaciones) camposRubro.instalaciones = data.instalaciones;
if (data.precios) camposRubro.precios = data.precios;
} else if (rubro === 'educacion') {
if (data.cursos) camposRubro.cursos = data.cursos;
if (data.horarios_educacion) camposRubro.horarios = data.horarios_educacion;
if (data.niveles_educacion) camposRubro.niveles = data.niveles_educacion;
if (data.profesores_educacion) camposRubro.profesores = data.profesores_educacion;
if (data.inscripcion) camposRubro.inscripcion = data.inscripcion;
}
// Crear JSON con formato estructurado
const jsonData = {
plan: data.plan,
cliente: {
nombre_completo: data.nombre,
email: data.email,
telefono: data.telefono,
rubro: data.rubro
},
personalizacion: {
colores_preferidos: data.colores || '',
tipografia: data.tipografia || null,
logo_url: data.logo_url || null,
logo_upload: null
},
redes_sociales: {
facebook: data.facebook || null,
instagram: data.instagram || null,
twitter: data.twitter || null,
youtube: data.youtube || null,
tiktok: data.tiktok || null,
linkedin: null,
whatsapp: data.whatsapp || null
},
direccion: {
calle: data.direccion_calle || '',
ciudad: data.direccion_ciudad || '',
provincia: data.direccion_provincia || '',
codigo_postal: data.direccion_cp || '',
pais: 'Argentina'
},
rubro_especifico: Object.keys(camposRubro).length > 0 ? camposRubro : null,
dominio: {
preferido: dominio,
generado: `${dominio}.gkachele.duckdns.org`
},
descripcion: data.descripcion || '',
estado: 'preview',
fecha_creacion: new Date().toISOString()
};
const btnPreview = document.getElementById('btnPreview');
const originalText = btnPreview.innerHTML;
btnPreview.disabled = true;
btnPreview.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Generando Preview...';
try {
// COPIAR EXACTAMENTE EL FLUJO DE v1/admin/form.html QUE FUNCIONA
const REPO_OWNER = 'komkida91';
const BACKEND_REPO = 'gkachele-requests';
const BACKEND_WORKFLOW = 'submit-request-through-app.yml';
const TARGET_WORKFLOW = 'generate-preview.yml';
// Token de sesión local (no se usa GitHub)
const DEFAULT_SESSION_TOKEN = 'GK@ch3l3-M1s10n3s-2025!#$';
// Construir payload EXACTAMENTE igual que v1/admin/form.html
const slug = data.nombre ? data.nombre.toLowerCase().replace(/[^a-z0-9]+/g, '-') : 'sitio-' + Date.now();
const dominioPreferido = data.dominio || slug;
const jsonData = {
plan: data.plan,
cliente: {
nombre_completo: data.nombre,
email: data.email,
telefono: data.telefono,
rubro: data.rubro
},
personalizacion: {
colores_preferidos: data.colores || '',
tipografia: data.tipografia || null,
logo_url: data.logo_url || null
},
redes_sociales: {
facebook: data.facebook || null,
instagram: data.instagram || null,
twitter: data.twitter || null,
whatsapp: data.whatsapp || null,
youtube: data.youtube || null,
tiktok: data.tiktok || null
},
direccion: {
calle: data.direccion_calle || '',
ciudad: data.direccion_ciudad || '',
provincia: data.direccion_provincia || '',
codigo_postal: data.direccion_cp || '',
pais: 'Argentina'
},
dominio: {
preferido: dominioPreferido,
generado: `${dominioPreferido}.gkachele.duckdns.org`
},
descripcion: data.descripcion || '',
estado: 'preview',
fecha_creacion: new Date().toISOString()
};
const workflowInputs = {
form_data: JSON.stringify(jsonData),
rubro: data.rubro,
plan: data.plan,
target_branch: 'main' // SIEMPRE usar main después del rollback
};
const inputsBase64 = btoa(JSON.stringify(workflowInputs));
// ✅ SOLUCIÓN COMPLETAMENTE DIFERENTE: Generar token en cliente, guardar en localStorage
console.log('🔄 Generando preview LOCALMENTE (sin llamadas externas)...');
// Generar token dinámico en el cliente (igual formato que el workflow)
function generateToken() {
const randomHash = Array.from(crypto.getRandomValues(new Uint8Array(4)))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
const dateStr = `${year}${month}${day}`;
const timeStr = `${hours}${minutes}${seconds}`;
return `${randomHash}-${dateStr}-${timeStr}`;
}
const token = generateToken();
console.log('✅ Token generado:', token);
// Guardar datos del preview en localStorage
// Calcular expiración: 15 minutos exactos
const expiresAt = new Date(Date.now() + 15 * 60 * 1000).toISOString();
const previewData = {
token: token,
form_data: jsonData,
rubro: data.rubro,
plan: data.plan,
created_at: new Date().toISOString(),
expires_at: expiresAt, // 15 minutos exactos
status: 'local_preview'
};
// Guardar en localStorage con clave única
localStorage.setItem('preview_' + token, JSON.stringify(previewData));
sessionStorage.setItem('current_preview_token', token);
// Guardar también en formato que el admin.html espera (con expiración de 15 min)
const adminData = {
form_data: jsonData,
rubro: data.rubro,
plan: data.plan,
created_at: new Date().toISOString(),
expires_at: expiresAt, // 15 minutos exactos
session_token_expires_at: expiresAt // Para que el admin muestre correctamente
};
localStorage.setItem('preview_data_' + token, JSON.stringify(adminData));
console.log('✅ Datos del preview guardados en localStorage');
// Redirigir al formulario de creación con plan y rubro
const createUrl = `/register?plan=${data.plan}&rubro=${data.rubro}`;
console.log('✅ Redirigiendo a:', createUrl);
btnPreview.innerHTML = '<i class="fas fa-check"></i> Preview Generado';
// Cerrar el modal del formulario
closeForm();
// Redirigir directamente al registro
window.location.href = createUrl;
return;
} catch (error) {
console.error('Error generando preview:', error);
alert('❌ No se pudo generar el preview en este momento.\n\n' +
'Por favor, intenta nuevamente en unos instantes.');
} finally {
btnPreview.disabled = false;
btnPreview.innerHTML = originalText;
}
}
// DESACTIVAR COMPLETAMENTE el cierre por clic fuera del modal
// Solo se puede cerrar con los botones explícitos (X, Cancelar, o después de enviar)
const modal = document.getElementById('planFormModal');
const modalContent = modal.querySelector('.modal-form-content');
// Prevenir TODOS los clics dentro del contenido
modalContent.addEventListener('click', function(event) {
event.stopPropagation();
});
// Prevenir TODOS los clics en el fondo del modal también
modal.addEventListener('click', function(event) {
// NO cerrar automáticamente - solo con botones explícitos
event.stopPropagation();
});
// Scroll to Top Button
const scrollToTopBtn = document.getElementById('scrollToTop');
window.addEventListener('scroll', () => {
if (window.pageYOffset > 300) {
scrollToTopBtn.classList.add('show');
} else {
scrollToTopBtn.classList.remove('show');
}
});
scrollToTopBtn.addEventListener('click', () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
// Smooth scroll for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// ============================================
// SISTEMA DE PREVIEWS
// ============================================
// Datos de previews (mock - luego vendrán de screenshots reales)
const previewsData = {
base: [
{ rubro: 'gimnasios', variacion: 'fuerte', nombre: 'Gimnasios - Diseño Fuerte', descripcion: 'Diseño oscuro y atlético, perfecto para gimnasios y centros de fitness', imagen: 'https://via.placeholder.com/800x450/1a1a1a/ffffff?text=Gimnasios+Fuerte' },
{ rubro: 'motos', variacion: 'clasico', nombre: 'Motos - Diseño Clásico', descripcion: 'Estilo robusto e industrial, ideal para concesionarias y talleres', imagen: 'https://via.placeholder.com/800x450/e74c3c/ffffff?text=Motos+Clasico' },
{ rubro: 'restaurante', variacion: 'acogedor', nombre: 'Restaurante - Diseño Acogedor', descripcion: 'Cálido y amigable, perfecto para restaurantes y cafeterías', imagen: 'https://via.placeholder.com/800x450/f39c12/ffffff?text=Restaurante+Acogedor' },
{ rubro: 'danza', variacion: 'vibrante', nombre: 'Danza - Diseño Vibrante', descripcion: 'Colorido y dinámico, ideal para escuelas de danza y academias', imagen: 'https://via.placeholder.com/800x450/e91e63/ffffff?text=Danza+Vibrante' },
{ rubro: 'cosmeticos', variacion: 'elegante', nombre: 'Cosméticos - Diseño Elegante', descripcion: 'Sofisticado y refinado, perfecto para salones de belleza y cosmética', imagen: 'https://via.placeholder.com/800x450/9b59b6/ffffff?text=Cosmeticos+Elegante' },
{ rubro: 'despachos', variacion: 'moderno', nombre: 'Despachos - Diseño Moderno', descripcion: 'Minimalista y profesional, ideal para despachos de abogados y contadores', imagen: 'https://via.placeholder.com/800x450/3498db/ffffff?text=Despachos+Moderno' }
],
pro: [
{ rubro: 'gimnasios', variacion: 'fuerte', nombre: 'Gimnasios PRO - Fuerte', descripcion: 'Diseño oscuro y atlético con animaciones, perfecto para gimnasios premium', imagen: 'https://via.placeholder.com/800x450/1a1a1a/ffffff?text=Gimnasios+PRO+Fuerte' },
{ rubro: 'gimnasios', variacion: 'moderno', nombre: 'Gimnasios PRO - Moderno', descripcion: 'Minimalista y limpio, ideal para centros de fitness modernos', imagen: 'https://via.placeholder.com/800x450/3498db/ffffff?text=Gimnasios+PRO+Moderno' },
{ rubro: 'gimnasios', variacion: 'elegante', nombre: 'Gimnasios PRO - Elegante', descripcion: 'Sofisticado y refinado, perfecto para estudios de yoga y pilates', imagen: 'https://via.placeholder.com/800x450/9b59b6/ffffff?text=Gimnasios+PRO+Elegante' }
],
premium: [
{ rubro: 'gimnasios', variacion: 'fuerte', nombre: 'Gimnasios PREMIUM - Fuerte', descripcion: 'Diseño premium con todas las características, ideal para cadenas de gimnasios', imagen: 'https://via.placeholder.com/800x450/1a1a1a/ffffff?text=Gimnasios+PREMIUM+Fuerte' }
]
};
// Variables globales para el sistema de previews
let currentPlan = '';
let selectedPreview = null;
// Abrir modal de previews
function openPreviews(planType) {
currentPlan = planType;
const modal = document.getElementById('previewsModal');
const planName = document.getElementById('previewPlanName');
const planNames = {
'base': 'Base',
'pro': 'Pro',
'premium': 'Premium',
'vip': 'VIP'
};
planName.textContent = planNames[planType] || planType;
modal.style.display = 'flex';
document.body.style.overflow = 'hidden';
// Cargar previews del plan
loadPreviews(planType);
}
// Cerrar modal de previews
function closePreviews() {
const modal = document.getElementById('previewsModal');
modal.style.display = 'none';
document.body.style.overflow = 'auto';
// Resetear filtro
const filterSelect = document.getElementById('filterRubro');
if (filterSelect) {
filterSelect.value = '';
}
}
// Cargar previews en el grid
function loadPreviews(planType) {
const grid = document.getElementById('previewsGrid');
const previews = previewsData[planType] || [];
grid.innerHTML = '';
// Crear las cards de preview
previews.forEach(preview => {
const card = createPreviewCard(preview, planType);
grid.appendChild(card);
});
// Actualizar filtro con TODOS los rubros disponibles
updateFilterOptions(previews);
// Filtrar según el rubro seleccionado
filterPreviews();
}
// Actualizar opciones del filtro - TODOS los rubros disponibles (sin screenshots)
function updateFilterOptions(previews) {
const filterSelect = document.getElementById('filterRubro');
const rubroNames = {
'gimnasios': 'Gimnasios',
'motos': 'Motos',
'restaurante': 'Restaurante',
'danza': 'Danza',
'cosmeticos': 'Cosméticos',
'despachos': 'Despachos'
};
// Obtener TODOS los rubros disponibles (no solo los que tienen previews)
const todosLosRubros = Object.keys(rubroNames);
// Mostrar filtro siempre
document.querySelector('.previews-filters').style.display = 'block';
filterSelect.innerHTML = '';
// Agregar TODOS los rubros al filtro
todosLosRubros.forEach(rubro => {
const option = document.createElement('option');
option.value = rubro;
option.textContent = rubroNames[rubro] || rubro;
filterSelect.appendChild(option);
});
// Seleccionar el primer rubro por defecto
if (todosLosRubros.length > 0) {
filterSelect.value = todosLosRubros[0];
}
}
// Crear card de preview
function createPreviewCard(preview, planType) {
const card = document.createElement('div');
card.className = 'template-card';
card.dataset.rubro = preview.rubro;
card.dataset.variacion = preview.variacion;
const rubroNames = {
'gimnasios': 'Gimnasios',
'motos': 'Motos',
'restaurante': 'Restaurante',
'danza': 'Danza',
'cosmeticos': 'Cosméticos',
'despachos': 'Despachos (Abogados/Contadores)'
};
const planBadgeClass = `badge-${planType}`;
card.innerHTML = `
<div class="template-preview">
<img src="${preview.imagen}" alt="${preview.nombre}" loading="lazy" />
<div class="template-overlay">
<div class="overlay-info">
<h4>${preview.nombre}</h4>
<p>${preview.descripcion}</p>
</div>
</div>
</div>
<div class="template-info">
<h3>${preview.nombre}</h3>
<div class="template-meta">
<span class="badge-plan ${planBadgeClass}">${planType.toUpperCase()}</span>
<span class="badge-rubro">${rubroNames[preview.rubro] || preview.rubro}</span>
</div>
<p class="template-description">${preview.descripcion}</p>
</div>
`;
// Click en card → abrir lightbox
card.addEventListener('click', () => {
openLightbox(preview, planType);
});
return card;
}
// Filtrar previews por rubro
function filterPreviews() {
const filterSelect = document.getElementById('filterRubro');
if (!filterSelect) return;
const filterValue = filterSelect.value.toLowerCase();
const cards = document.querySelectorAll('.template-card');
cards.forEach(card => {
const rubro = card.dataset.rubro;
if (!filterValue || rubro === filterValue) {
card.style.display = 'block';
} else {
card.style.display = 'none';
}
});
}
// Abrir lightbox con screenshot grande
function openLightbox(preview, planType) {
selectedPreview = { ...preview, plan: planType };
const lightbox = document.getElementById('screenshotLightbox');
const image = document.getElementById('lightboxImage');
const title = document.getElementById('lightboxTitle');
const description = document.getElementById('lightboxDescription');
image.src = preview.imagen;
image.alt = preview.nombre;
title.textContent = preview.nombre;
description.textContent = preview.descripcion;
lightbox.style.display = 'flex';
document.body.style.overflow = 'hidden';
}
// Cerrar lightbox
function closeLightbox() {
const lightbox = document.getElementById('screenshotLightbox');
lightbox.style.display = 'none';
document.body.style.overflow = 'auto';
selectedPreview = null;
}
// Solicitar diseño (abre formulario prellenado)
function requestDesign() {
if (!selectedPreview) return;
// Cerrar lightbox y modal de previews
closeLightbox();
closePreviews();
// Abrir formulario con datos prellenados
const planType = selectedPreview.plan;
openForm(planType);
// Prellenar campos después de un pequeño delay para que el formulario se abra
setTimeout(() => {
const rubroSelect = document.getElementById('rubro');
const templateVariation = document.getElementById('templateVariation');
if (rubroSelect) {
rubroSelect.value = selectedPreview.rubro;
// Disparar evento para actualizar campos de rubro
rubroSelect.dispatchEvent(new Event('change'));
}
if (templateVariation) {
templateVariation.value = selectedPreview.variacion;
}
// Actualizar campos de rubro si existe la función
if (typeof actualizarCamposRubro === 'function') {
actualizarCamposRubro();
}
}, 300);
}
// Cerrar modales al hacer clic fuera
document.getElementById('previewsModal').addEventListener('click', function(e) {
if (e.target === this) {
closePreviews();
}
});
document.getElementById('screenshotLightbox').addEventListener('click', function(e) {
if (e.target === this) {
closeLightbox();
}
});
// Cerrar con ESC
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
closePreviews();
closeLightbox();
}
});
</script>
</body>
</html>