Files
gkachele-saas/demo/templates/customizer-wordpress-demo.html
2026-01-17 11:40:17 +01:00

689 lines
26 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Customizer Demo - Estilo WordPress</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
overflow: hidden;
}
/* HEADER - Estilo WordPress */
.customizer-header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 46px;
background: #23282d;
border-bottom: 1px solid #000;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 15px;
z-index: 1000;
}
.customizer-header-left {
display: flex;
align-items: center;
gap: 15px;
}
.customizer-logo {
width: 20px;
height: 20px;
background: #fff;
border-radius: 3px;
display: flex;
align-items: center;
justify-content: center;
color: #23282d;
font-weight: bold;
font-size: 12px;
}
.customizer-title {
color: #fff;
font-size: 14px;
font-weight: 600;
}
.customizer-close {
background: transparent;
border: none;
color: #a7aaad;
font-size: 20px;
cursor: pointer;
padding: 5px 10px;
line-height: 1;
}
.customizer-close:hover {
color: #fff;
}
/* MAIN CONTAINER */
.customizer-container {
display: flex;
height: 100vh;
padding-top: 46px;
}
/* SIDEBAR - Estilo WordPress */
.customizer-sidebar {
width: 300px;
background: #fff;
border-right: 1px solid #ddd;
display: flex;
flex-direction: column;
overflow: hidden;
}
.customizer-sidebar-content {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: 0;
}
/* Menú lateral de secciones (como WordPress) */
.customizer-nav {
background: #f6f7f7;
border-bottom: 1px solid #ddd;
padding: 0;
}
.customizer-nav-item {
display: block;
padding: 12px 15px;
color: #23282d;
text-decoration: none;
border-bottom: 1px solid #ddd;
font-size: 13px;
cursor: pointer;
transition: background 0.1s;
}
.customizer-nav-item:hover {
background: #fff;
}
.customizer-nav-item.active {
background: #fff;
border-left: 4px solid #2271b1;
padding-left: 11px;
}
/* Secciones de controles */
.customizer-section {
display: none;
padding: 20px;
}
.customizer-section.active {
display: block;
}
.customizer-section-title {
font-size: 13px;
font-weight: 600;
color: #23282d;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid #ddd;
}
.customizer-control {
margin-bottom: 20px;
}
.customizer-control-label {
display: block;
font-size: 13px;
font-weight: 600;
color: #23282d;
margin-bottom: 8px;
}
.customizer-control-input {
width: 100%;
padding: 8px 12px;
border: 1px solid #8c8f94;
border-radius: 4px;
font-size: 14px;
font-family: inherit;
transition: border-color 0.2s, box-shadow 0.2s;
}
.customizer-control-input:focus {
outline: none;
border-color: #2271b1;
box-shadow: 0 0 0 1px #2271b1;
}
.customizer-control-textarea {
min-height: 80px;
resize: vertical;
}
.customizer-control-description {
font-size: 12px;
color: #646970;
margin-top: 5px;
}
/* Color picker */
.customizer-color-group {
display: flex;
align-items: center;
gap: 10px;
}
.customizer-color-picker {
width: 50px;
height: 40px;
border: 1px solid #8c8f94;
border-radius: 4px;
cursor: pointer;
padding: 2px;
}
.customizer-color-text {
flex: 1;
}
/* PREVIEW */
.customizer-preview {
flex: 1;
background: #f0f0f1;
position: relative;
overflow: hidden;
}
.customizer-preview iframe {
width: 100%;
height: 100%;
border: none;
}
/* FOOTER - Estilo WordPress */
.customizer-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 50px;
background: #f6f7f7;
border-top: 1px solid #ddd;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
z-index: 1000;
}
.customizer-footer-left {
display: flex;
align-items: center;
gap: 10px;
}
.customizer-footer-right {
display: flex;
gap: 10px;
}
.customizer-btn {
padding: 8px 16px;
border: none;
border-radius: 4px;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}
.customizer-btn-secondary {
background: #f0f0f1;
color: #2c3338;
}
.customizer-btn-secondary:hover {
background: #dcdcde;
}
.customizer-btn-primary {
background: #2271b1;
color: #fff;
}
.customizer-btn-primary:hover {
background: #135e96;
}
.customizer-btn-primary:disabled {
background: #c3c4c7;
cursor: not-allowed;
}
.customizer-btn-discard {
display: none;
}
.customizer-btn-discard.has-changes {
display: inline-block;
}
.customizer-status {
font-size: 12px;
color: #646970;
margin-left: 10px;
}
.customizer-status.saving {
color: #2271b1;
}
.customizer-status.saved {
color: #00a32a;
}
.customizer-status.error {
color: #d63638;
}
/* Indicador de cambios sin guardar */
.customizer-unsaved-indicator {
display: inline-block;
width: 8px;
height: 8px;
background: #d63638;
border-radius: 50%;
margin-right: 8px;
display: none;
}
.customizer-unsaved-indicator.has-changes {
display: inline-block;
}
/* Scroll suave */
.customizer-sidebar-content {
scroll-behavior: smooth;
}
/* Loading */
.customizer-loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #646970;
font-size: 14px;
}
</style>
</head>
<body>
<!-- HEADER -->
<div class="customizer-header">
<div class="customizer-header-left">
<div class="customizer-logo">W</div>
<div class="customizer-title">Personalizar</div>
</div>
<button class="customizer-close" onclick="closeCustomizer()" title="Cerrar">×</button>
</div>
<!-- MAIN CONTAINER -->
<div class="customizer-container">
<!-- SIDEBAR -->
<div class="customizer-sidebar">
<!-- Menú lateral de secciones -->
<div class="customizer-nav">
<a href="#" class="customizer-nav-item active" data-section="site-identity">Identidad del sitio</a>
<a href="#" class="customizer-nav-item" data-section="colors">Colores</a>
<a href="#" class="customizer-nav-item" data-section="typography">Tipografía</a>
<a href="#" class="customizer-nav-item" data-section="content">Contenido</a>
<a href="#" class="customizer-nav-item" data-section="media">Medios</a>
<a href="#" class="customizer-nav-item" data-section="contact">Contacto</a>
<a href="#" class="customizer-nav-item" data-section="social">Redes Sociales</a>
</div>
<!-- Contenido de secciones -->
<div class="customizer-sidebar-content">
<!-- Sección: Identidad del sitio -->
<div class="customizer-section active" id="site-identity">
<div class="customizer-section-title">Identidad del sitio</div>
<div class="customizer-control">
<label class="customizer-control-label">Nombre del sitio</label>
<input type="text" class="customizer-control-input" id="site_name" value="Mi Restaurante" data-setting="site_name">
<div class="customizer-control-description">El nombre aparece en el encabezado del sitio.</div>
</div>
<div class="customizer-control">
<label class="customizer-control-label">Descripción corta</label>
<textarea class="customizer-control-input customizer-control-textarea" id="site_description" data-setting="site_description">El mejor restaurante de la ciudad</textarea>
<div class="customizer-control-description">En pocas palabras, explica de qué trata este sitio.</div>
</div>
</div>
<!-- Sección: Colores -->
<div class="customizer-section" id="colors">
<div class="customizer-section-title">Colores</div>
<div class="customizer-control">
<label class="customizer-control-label">Color primario</label>
<div class="customizer-color-group">
<input type="color" class="customizer-color-picker" id="color_primary" value="#c94d4d" data-setting="color_primary">
<input type="text" class="customizer-control-input customizer-color-text" id="color_primary_text" value="#c94d4d" readonly>
</div>
</div>
<div class="customizer-control">
<label class="customizer-control-label">Color secundario</label>
<div class="customizer-color-group">
<input type="color" class="customizer-color-picker" id="color_secondary" value="#d97757" data-setting="color_secondary">
<input type="text" class="customizer-control-input customizer-color-text" id="color_secondary_text" value="#d97757" readonly>
</div>
</div>
<div class="customizer-control">
<label class="customizer-control-label">Color de texto</label>
<div class="customizer-color-group">
<input type="color" class="customizer-color-picker" id="color_text" value="#2c2c2c" data-setting="color_text">
<input type="text" class="customizer-control-input customizer-color-text" id="color_text_text" value="#2c2c2c" readonly>
</div>
</div>
</div>
<!-- Sección: Tipografía -->
<div class="customizer-section" id="typography">
<div class="customizer-section-title">Tipografía</div>
<div class="customizer-control">
<label class="customizer-control-label">Familia de fuente</label>
<select class="customizer-control-input" id="font_family" data-setting="font_family">
<option value="Roboto">Roboto</option>
<option value="Georgia">Georgia</option>
<option value="Playfair Display">Playfair Display</option>
<option value="Cormorant Garamond">Cormorant Garamond</option>
<option value="Oswald">Oswald</option>
<option value="Arial">Arial</option>
</select>
</div>
</div>
<!-- Sección: Contenido -->
<div class="customizer-section" id="content">
<div class="customizer-section-title">Contenido</div>
<div class="customizer-control">
<label class="customizer-control-label">Título principal</label>
<input type="text" class="customizer-control-input" id="hero_title" value="Bienvenido" data-setting="hero_title">
</div>
<div class="customizer-control">
<label class="customizer-control-label">Descripción</label>
<textarea class="customizer-control-input customizer-control-textarea" id="hero_description" data-setting="hero_description">Descripción de tu restaurante...</textarea>
</div>
</div>
<!-- Sección: Medios -->
<div class="customizer-section" id="media">
<div class="customizer-section-title">Medios</div>
<div class="customizer-control">
<label class="customizer-control-label">Logo</label>
<input type="url" class="customizer-control-input" id="media_logo" placeholder="https://ejemplo.com/logo.png" data-setting="media_logo">
<div class="customizer-control-description">URL de la imagen del logo</div>
</div>
<div class="customizer-control">
<label class="customizer-control-label">Imagen Hero</label>
<input type="url" class="customizer-control-input" id="media_hero" placeholder="https://ejemplo.com/hero.jpg" data-setting="media_hero">
<div class="customizer-control-description">Imagen de fondo para la sección principal</div>
</div>
</div>
<!-- Sección: Contacto -->
<div class="customizer-section" id="contact">
<div class="customizer-section-title">Contacto</div>
<div class="customizer-control">
<label class="customizer-control-label">Dirección</label>
<input type="text" class="customizer-control-input" id="contact_address" placeholder="Calle Principal 123" data-setting="contact_address">
</div>
<div class="customizer-control">
<label class="customizer-control-label">Teléfono</label>
<input type="tel" class="customizer-control-input" id="contact_phone" placeholder="+34 123 456 789" data-setting="contact_phone">
</div>
<div class="customizer-control">
<label class="customizer-control-label">Email</label>
<input type="email" class="customizer-control-input" id="contact_email" placeholder="contacto@restaurante.com" data-setting="contact_email">
</div>
</div>
<!-- Sección: Redes Sociales -->
<div class="customizer-section" id="social">
<div class="customizer-section-title">Redes Sociales</div>
<div class="customizer-control">
<label class="customizer-control-label">Facebook</label>
<input type="url" class="customizer-control-input" id="social_facebook" placeholder="https://facebook.com/tu-pagina" data-setting="social_facebook">
</div>
<div class="customizer-control">
<label class="customizer-control-label">Instagram</label>
<input type="url" class="customizer-control-input" id="social_instagram" placeholder="https://instagram.com/tu-cuenta" data-setting="social_instagram">
</div>
<div class="customizer-control">
<label class="customizer-control-label">WhatsApp</label>
<input type="tel" class="customizer-control-input" id="social_whatsapp" placeholder="+34123456789" data-setting="social_whatsapp">
<div class="customizer-control-description">Número de WhatsApp para botón flotante</div>
</div>
</div>
</div>
</div>
<!-- PREVIEW -->
<div class="customizer-preview">
<div class="customizer-loading" id="preview-loading">Cargando vista previa...</div>
<iframe id="preview-iframe" src="about:blank" style="display: none;"></iframe>
</div>
</div>
<!-- FOOTER -->
<div class="customizer-footer">
<div class="customizer-footer-left">
<span class="customizer-unsaved-indicator" id="unsaved-indicator"></span>
<span class="customizer-status" id="status-text">Listo</span>
</div>
<div class="customizer-footer-right">
<button class="customizer-btn customizer-btn-secondary customizer-btn-discard" id="btn-discard" onclick="discardChanges()">Descartar cambios</button>
<button class="customizer-btn customizer-btn-primary" id="btn-save" onclick="saveChanges()">Guardar y Publicar</button>
</div>
</div>
<script>
// Estado del customizer
let hasUnsavedChanges = false;
let originalValues = {};
let currentValues = {};
// Inicializar
document.addEventListener('DOMContentLoaded', function() {
// Guardar valores originales
document.querySelectorAll('[data-setting]').forEach(input => {
originalValues[input.dataset.setting] = input.value;
currentValues[input.dataset.setting] = input.value;
});
// Navegación entre secciones
document.querySelectorAll('.customizer-nav-item').forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault();
const section = this.dataset.section;
showSection(section);
});
});
// Sincronizar color pickers
document.querySelectorAll('.customizer-color-picker').forEach(picker => {
const textInput = document.getElementById(picker.id + '_text');
if (textInput) {
picker.addEventListener('input', function() {
textInput.value = this.value;
markAsChanged();
updatePreview();
});
}
});
// Escuchar cambios en inputs
document.querySelectorAll('[data-setting]').forEach(input => {
input.addEventListener('input', function() {
markAsChanged();
updatePreview();
});
input.addEventListener('change', function() {
markAsChanged();
updatePreview();
});
});
// Confirmar antes de salir si hay cambios
window.addEventListener('beforeunload', function(e) {
if (hasUnsavedChanges) {
e.preventDefault();
e.returnValue = '';
}
});
});
// Mostrar sección
function showSection(sectionId) {
// Ocultar todas las secciones
document.querySelectorAll('.customizer-section').forEach(section => {
section.classList.remove('active');
});
// Mostrar sección seleccionada
document.getElementById(sectionId).classList.add('active');
// Actualizar navegación
document.querySelectorAll('.customizer-nav-item').forEach(item => {
item.classList.remove('active');
if (item.dataset.section === sectionId) {
item.classList.add('active');
}
});
}
// Marcar como cambiado
function markAsChanged() {
hasUnsavedChanges = true;
document.getElementById('unsaved-indicator').classList.add('has-changes');
document.getElementById('btn-discard').classList.add('has-changes');
// Actualizar valores actuales
document.querySelectorAll('[data-setting]').forEach(input => {
currentValues[input.dataset.setting] = input.value;
});
}
// Actualizar preview (simulado)
function updatePreview() {
// En un customizer real, aquí se actualizaría el iframe
// Por ahora solo simulamos
console.log('Preview actualizado:', currentValues);
}
// Guardar cambios
function saveChanges() {
const btn = document.getElementById('btn-save');
const status = document.getElementById('status-text');
btn.disabled = true;
status.textContent = 'Guardando...';
status.className = 'customizer-status saving';
// Simular guardado
setTimeout(() => {
// Guardar valores originales
Object.keys(currentValues).forEach(key => {
originalValues[key] = currentValues[key];
});
hasUnsavedChanges = false;
document.getElementById('unsaved-indicator').classList.remove('has-changes');
document.getElementById('btn-discard').classList.remove('has-changes');
status.textContent = 'Guardado';
status.className = 'customizer-status saved';
btn.disabled = false;
setTimeout(() => {
status.textContent = 'Listo';
status.className = 'customizer-status';
}, 2000);
}, 1000);
}
// Descartar cambios
function discardChanges() {
if (!confirm('¿Descartar todos los cambios sin guardar?')) {
return;
}
// Restaurar valores originales
Object.keys(originalValues).forEach(key => {
const input = document.querySelector(`[data-setting="${key}"]`);
if (input) {
input.value = originalValues[key];
currentValues[key] = originalValues[key];
}
});
// Sincronizar color pickers
document.querySelectorAll('.customizer-color-picker').forEach(picker => {
const textInput = document.getElementById(picker.id + '_text');
if (textInput) {
picker.value = textInput.value;
}
});
hasUnsavedChanges = false;
document.getElementById('unsaved-indicator').classList.remove('has-changes');
document.getElementById('btn-discard').classList.remove('has-changes');
updatePreview();
}
// Cerrar customizer
function closeCustomizer() {
if (hasUnsavedChanges) {
if (!confirm('¿Tienes cambios sin guardar. ¿Seguro que quieres salir?')) {
return;
}
}
// En un customizer real, aquí se redirigiría
alert('Redirigiendo al dashboard...');
}
</script>
</body>
</html>