361 lines
38 KiB
HTML
361 lines
38 KiB
HTML
{% extends 'base.html' %}
|
||
{% block content %}
|
||
<div class="page-toolbar">
|
||
<div>
|
||
<h1 class="h3 mb-1">Sitio web y frontend</h1>
|
||
<p class="text-muted mb-0">Configuración centralizada del sitio público, diseño, legal, popup y bloques del template.</p>
|
||
</div>
|
||
<div class="d-flex gap-2 flex-wrap">
|
||
<a class="btn btn-outline-secondary" href="{{ url_for('index') }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i> Ver sitio</a>
|
||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#frontendBlockModal"><i class="bi bi-plus-circle"></i> Nuevo bloque</button>
|
||
</div>
|
||
</div>
|
||
|
||
<ul class="nav nav-tabs mb-4">
|
||
<li class="nav-item"><a class="nav-link {% if active_tab=='general' %}active{% endif %}" href="{{ url_for('admin_site_settings', tab='general') }}">General</a></li>
|
||
<li class="nav-item"><a class="nav-link {% if active_tab=='design' %}active{% endif %}" href="{{ url_for('admin_site_settings', tab='design') }}">Diseño Frontend</a></li>
|
||
<li class="nav-item"><a class="nav-link {% if active_tab=='seo' %}active{% endif %}" href="{{ url_for('admin_site_settings', tab='seo') }}">SEO técnico</a></li>
|
||
<li class="nav-item"><a class="nav-link {% if active_tab=='style_admin' %}active{% endif %}" href="{{ url_for('admin_site_settings', tab='style_admin') }}">Stylo Admin</a></li>
|
||
|
||
<li class="nav-item"><a class="nav-link" href="{{ url_for('admin_whatsapp_bot') }}">WhatsApp Bot</a></li>
|
||
<li class="nav-item"><a class="nav-link {% if active_tab=='blocks' %}active{% endif %}" href="{{ url_for('admin_site_settings', tab='blocks') }}">Bloques</a></li>
|
||
<li class="nav-item"><a class="nav-link {% if active_tab=='popup' %}active{% endif %}" href="{{ url_for('admin_site_settings', tab='popup') }}">PopUp</a></li>
|
||
<li class="nav-item"><a class="nav-link {% if active_tab=='legal' %}active{% endif %}" href="{{ url_for('admin_site_settings', tab='legal') }}">Cookies y legal</a></li>
|
||
</ul>
|
||
|
||
{% if active_tab == 'general' %}
|
||
<div class="card table-panel">
|
||
<div class="card-body">
|
||
<form method="post" enctype="multipart/form-data" class="row g-3 geo-form">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||
<input type="hidden" name="return_tab" value="general">
|
||
<div class="col-md-6"><label class="form-label">Título del sitio</label><input class="form-control" name="site_title" value="{{ settings.title }}" required></div>
|
||
<div class="col-md-3"><label class="form-label">Teléfono</label><input class="form-control" name="site_phone" value="{{ settings.phone }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Email</label><input class="form-control" name="site_email" value="{{ settings.email }}"></div>
|
||
<div class="col-md-6"><label class="form-label">URL pública</label><input class="form-control" name="site_url" value="{{ settings.url }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Tagline</label><input class="form-control" name="site_tagline" value="{{ settings.tagline }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Botón CTA</label><input class="form-control" name="site_nav_cta_label" value="{{ settings.nav_cta_label }}"></div>
|
||
<div class="col-md-3"><label class="form-label">N° Plataforma</label><input class="form-control" name="site_platform_number" value="{{ settings.platform_number }}"></div>
|
||
<div class="col-md-3"><label class="form-label">N° Repositorio</label><input class="form-control" name="site_repository_number" value="{{ settings.repository_number }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Logo</label><input type="file" class="form-control" name="site_logo" accept="image/*">{% if settings.logo_path %}<div class="small text-muted mt-1">Actual: {{ settings.logo_path }}</div>{% endif %}</div>
|
||
<div class="col-md-3"><label class="form-label">Favicon</label><input type="file" class="form-control" name="site_favicon" accept="image/*">{% if settings.favicon_path %}<div class="small text-muted mt-1">Actual: {{ settings.favicon_path }}</div>{% endif %}</div>
|
||
<div class="col-md-3"><label class="form-label">País</label><input class="form-control" name="site_country" value="{{ settings.country }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Provincia</label>
|
||
<input class="form-control geo-native-input geo-province-input" list="siteProvinceList" value="{{ settings.province }}" placeholder="Escribí y seleccioná provincia" autocomplete="off">
|
||
<datalist id="siteProvinceList" class="geo-province-list"></datalist>
|
||
<input type="hidden" name="province_name" class="geo-province-name" value="{{ settings.province }}">
|
||
<input type="hidden" name="site_province" class="geo-province-id">
|
||
</div>
|
||
<div class="col-md-3"><label class="form-label">Partido / Municipio</label>
|
||
<input class="form-control geo-native-input geo-municipality-input" list="siteMunicipalityList" value="{{ settings.municipality }}" placeholder="Escribí y seleccioná partido / municipio" autocomplete="off">
|
||
<datalist id="siteMunicipalityList" class="geo-municipality-list"></datalist>
|
||
<input type="hidden" name="municipality_name" class="geo-municipality-name" value="{{ settings.municipality }}">
|
||
<input type="hidden" name="site_municipality" class="geo-municipality-id">
|
||
</div>
|
||
<div class="col-md-3"><label class="form-label">Ciudad / Localidad</label>
|
||
<input class="form-control geo-native-input geo-city-input" list="siteCityList" value="{{ settings.city }}" placeholder="Escribí y seleccioná ciudad / localidad" autocomplete="off">
|
||
<datalist id="siteCityList" class="geo-city-list"></datalist>
|
||
<input type="hidden" name="city_name" class="geo-city-name" value="{{ settings.city }}">
|
||
<input type="hidden" name="site_city" class="geo-city-id">
|
||
</div>
|
||
<div class="col-12"><label class="form-label">Dirección de contacto</label><textarea class="form-control" name="site_contact_address" rows="2">{{ settings.contact_address }}</textarea></div>
|
||
<div class="col-12"><label class="form-label">Mapa embebido</label><textarea class="form-control" name="site_contact_map_embed" rows="4">{{ settings.contact_map_embed }}</textarea></div>
|
||
<div class="col-12"><label class="form-label">Copyright</label><input class="form-control" name="site_copyright" value="{{ settings.copyright }}"></div>
|
||
<div class="col-12 pt-2"><h3 class="h6 mb-0">Redes sociales</h3></div>
|
||
{% for network, label, icon in [('facebook','Facebook','bi-facebook'),('instagram','Instagram','bi-instagram'),('x','X / Twitter','bi-twitter-x'),('youtube','YouTube','bi-youtube'),('linkedin','LinkedIn','bi-linkedin')] %}
|
||
<div class="col-md-2 d-flex align-items-end"><div class="form-check"><input class="form-check-input" type="checkbox" name="site_social_{{ network }}_enabled" {% if settings.socials_raw[network].enabled %}checked{% endif %}><label class="form-check-label"><i class="bi {{ icon }}"></i> {{ label }}</label></div></div>
|
||
<div class="col-md-10"><label class="form-label">URL {{ label }}</label><input class="form-control" name="site_social_{{ network }}_url" value="{{ settings.socials_raw[network].url }}"></div>
|
||
{% endfor %}
|
||
<div class="col-12 d-grid"><button class="btn btn-primary btn-lg">Guardar configuración general</button></div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
{% elif active_tab == 'seo' %}
|
||
<div class="row g-4">
|
||
<div class="col-lg-8">
|
||
<div class="card table-panel">
|
||
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
|
||
<strong>SEO técnico del frontend</strong>
|
||
<div class="small text-muted">Títulos, indexación, Open Graph, Twitter Cards, sitemap y Schema.org.</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<form method="post" enctype="multipart/form-data" class="row g-3">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||
<input type="hidden" name="return_tab" value="seo">
|
||
<div class="col-12">
|
||
<div class="seo-score-card">
|
||
<div class="form-check form-switch">
|
||
<input class="form-check-input" type="checkbox" name="site_seo_indexing_enabled" id="site_seo_indexing_enabled" {% if settings.seo_indexing_enabled %}checked{% endif %}>
|
||
<label class="form-check-label fw-semibold" for="site_seo_indexing_enabled">Permitir indexación en buscadores</label>
|
||
</div>
|
||
<div class="form-text">Desactivarlo genera <code>noindex,nofollow</code> y bloquea <code>robots.txt</code>. Usalo mientras trabajás en staging.</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-8"><label class="form-label">SEO title</label><input class="form-control" name="site_seo_title" value="{{ settings.seo_title }}" maxlength="70" placeholder="Centro médico | Turnos online"><div class="form-text">Recomendado: 50 a 60 caracteres.</div></div>
|
||
<div class="col-md-4"><label class="form-label">Robots meta</label><input class="form-control" name="site_robots_meta" value="{{ settings.robots_meta }}" placeholder="index,follow"></div>
|
||
<div class="col-12"><label class="form-label">Meta description</label><textarea class="form-control" name="site_meta_description" rows="3" maxlength="180" placeholder="Descripción clara de la institución, especialidades y turnos online.">{{ settings.meta_description }}</textarea><div class="form-text">Recomendado: 140 a 160 caracteres.</div></div>
|
||
<div class="col-12"><label class="form-label">Palabras clave internas</label><input class="form-control" name="site_meta_keywords" value="{{ settings.meta_keywords }}" placeholder="turnos médicos, clínica, especialidades"></div>
|
||
<div class="col-md-8"><label class="form-label">Canonical URL</label><input class="form-control" name="site_canonical_url" value="{{ settings.canonical_url }}" placeholder="https://tudominio.com/"></div>
|
||
<div class="col-md-2"><label class="form-label">HTML lang</label><input class="form-control" name="site_lang" value="{{ settings.lang }}" placeholder="es-AR"></div>
|
||
<div class="col-md-2"><label class="form-label">OG locale</label><input class="form-control" name="site_locale" value="{{ settings.locale }}" placeholder="es_AR"></div>
|
||
|
||
<div class="col-12 pt-2"><h3 class="h6 mb-0">Open Graph / redes sociales</h3></div>
|
||
<div class="col-md-6"><label class="form-label">OG title</label><input class="form-control" name="site_og_title" value="{{ settings.og_title }}" placeholder="Usa el SEO title si queda vacío"></div>
|
||
<div class="col-md-6"><label class="form-label">Twitter title</label><input class="form-control" name="site_twitter_title" value="{{ settings.twitter_title }}" placeholder="Usa OG title si queda vacío"></div>
|
||
<div class="col-md-6"><label class="form-label">OG description</label><textarea class="form-control" name="site_og_description" rows="3">{{ settings.og_description }}</textarea></div>
|
||
<div class="col-md-6"><label class="form-label">Twitter description</label><textarea class="form-control" name="site_twitter_description" rows="3">{{ settings.twitter_description }}</textarea></div>
|
||
<div class="col-md-4"><label class="form-label">Imagen OG/Twitter</label><input type="file" class="form-control" name="site_og_image" accept="image/*">{% if settings.og_image_path %}<div class="small text-muted mt-1">Actual: {{ settings.og_image_path }}</div>{% endif %}</div>
|
||
<div class="col-md-4"><label class="form-label">Alt de imagen social</label><input class="form-control" name="site_og_image_alt" value="{{ settings.og_image_alt }}"></div>
|
||
<div class="col-md-2"><label class="form-label">Twitter card</label><select class="form-select" name="site_twitter_card"><option value="summary_large_image" {% if settings.twitter_card=='summary_large_image' %}selected{% endif %}>summary_large_image</option><option value="summary" {% if settings.twitter_card=='summary' %}selected{% endif %}>summary</option></select></div>
|
||
<div class="col-md-2"><label class="form-label">@Twitter/X</label><input class="form-control" name="site_twitter_site" value="{{ settings.twitter_site }}" placeholder="@usuario"></div>
|
||
|
||
<div class="col-12 pt-2"><h3 class="h6 mb-0">Datos estructurados Schema.org</h3></div>
|
||
<div class="col-md-4"><label class="form-label">Tipo de entidad</label><select class="form-select" name="site_schema_type"><option value="MedicalClinic" {% if settings.schema_type=='MedicalClinic' %}selected{% endif %}>MedicalClinic</option><option value="MedicalOrganization" {% if settings.schema_type=='MedicalOrganization' %}selected{% endif %}>MedicalOrganization</option><option value="HealthAndBeautyBusiness" {% if settings.schema_type=='HealthAndBeautyBusiness' %}selected{% endif %}>HealthAndBeautyBusiness</option><option value="LocalBusiness" {% if settings.schema_type=='LocalBusiness' %}selected{% endif %}>LocalBusiness</option></select></div>
|
||
<div class="col-md-5"><label class="form-label">Nombre legal / razón social</label><input class="form-control" name="site_legal_name" value="{{ settings.legal_name }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Rango de precios</label><input class="form-control" name="site_price_range" value="{{ settings.price_range }}" placeholder="$$"></div>
|
||
|
||
<div class="col-12 pt-2"><h3 class="h6 mb-0">Verificación de propiedad</h3></div>
|
||
<div class="col-md-6"><label class="form-label">Google Search Console verification</label><input class="form-control" name="site_google_site_verification" value="{{ settings.google_site_verification }}" placeholder="Solo el token de content"></div>
|
||
<div class="col-md-6"><label class="form-label">Bing Webmaster verification</label><input class="form-control" name="site_bing_site_verification" value="{{ settings.bing_site_verification }}" placeholder="Solo el token de content"></div>
|
||
<div class="col-12 d-grid"><button class="btn btn-primary btn-lg">Guardar SEO técnico</button></div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-4">
|
||
<div class="card table-panel h-100"><div class="card-body">
|
||
<h2 class="h5">Checklist de publicación</h2>
|
||
<ul class="small text-muted mb-3">
|
||
<li>SEO title único y descriptivo.</li>
|
||
<li>Meta description clara, con zona y especialidad.</li>
|
||
<li>Imagen social 1200×630 recomendada.</li>
|
||
<li><code>/robots.txt</code> y <code>/sitemap.xml</code> quedan generados automáticamente.</li>
|
||
<li>Schema.org se arma con servicios, profesionales, ubicación y datos de contacto.</li>
|
||
</ul>
|
||
<div class="d-grid gap-2">
|
||
<a class="btn btn-outline-primary" href="{{ url_for('index') }}" target="_blank">Ver frontend</a>
|
||
<a class="btn btn-outline-secondary" href="{{ url_for('sitemap_xml') }}" target="_blank">Ver sitemap.xml</a>
|
||
<a class="btn btn-outline-secondary" href="{{ url_for('robots_txt') }}" target="_blank">Ver robots.txt</a>
|
||
</div>
|
||
</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
{% elif active_tab == 'design' %}
|
||
<div class="row g-4">
|
||
<div class="col-lg-8">
|
||
<div class="card table-panel">
|
||
<div class="card-header"><strong>Control visual del frontend</strong></div>
|
||
<div class="card-body">
|
||
<form method="post" enctype="multipart/form-data" class="row g-3">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||
<input type="hidden" name="return_tab" value="design">
|
||
<div class="col-12"><h3 class="h6 mb-0">Identidad general</h3></div>
|
||
<div class="col-md-4"><label class="form-label">Color primario</label><input type="color" class="form-control form-control-color w-100" name="site_primary_color" value="{{ settings.primary_color }}"></div>
|
||
<div class="col-md-4"><label class="form-label">Color secundario</label><input type="color" class="form-control form-control-color w-100" name="site_secondary_color" value="{{ settings.secondary_color }}"></div>
|
||
<div class="col-md-4"><label class="form-label">Color acento</label><input type="color" class="form-control form-control-color w-100" name="site_accent_color" value="{{ settings.accent_color }}"></div>
|
||
<div class="col-md-4"><label class="form-label">Fuente cuerpo</label><input class="form-control" name="site_body_font" value="{{ settings.body_font }}" placeholder="Roboto"></div>
|
||
<div class="col-md-4"><label class="form-label">Fuente títulos</label><input class="form-control" name="site_heading_font" value="{{ settings.heading_font }}" placeholder="Poppins"></div>
|
||
<div class="col-md-2"><label class="form-label">Tamaño base px</label><input class="form-control" name="site_base_font_size" value="{{ settings.base_font_size }}" placeholder="16"></div>
|
||
<div class="col-md-2"><label class="form-label">Radio px</label><input class="form-control" name="site_border_radius" value="{{ settings.border_radius }}" placeholder="20"></div>
|
||
|
||
<div class="col-12 pt-2"><h3 class="h6 mb-0">Topbar, header y navegación</h3></div>
|
||
<div class="col-md-3"><label class="form-label">Topbar fondo</label><input type="color" class="form-control form-control-color w-100" name="site_topbar_bg" value="{{ settings.topbar_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Topbar texto</label><input type="color" class="form-control form-control-color w-100" name="site_topbar_text" value="{{ settings.topbar_text }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Header fondo</label><input type="color" class="form-control form-control-color w-100" name="site_header_bg" value="{{ settings.header_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Header texto</label><input type="color" class="form-control form-control-color w-100" name="site_header_text" value="{{ settings.header_text }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Menú texto</label><input type="color" class="form-control form-control-color w-100" name="site_nav_text" value="{{ settings.nav_text }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Menú hover</label><input type="color" class="form-control form-control-color w-100" name="site_nav_hover" value="{{ settings.nav_hover }}"></div>
|
||
|
||
<div class="col-12 pt-2"><h3 class="h6 mb-0">Hero, secciones, tarjetas y footer</h3></div>
|
||
<div class="col-md-3"><label class="form-label">Hero fondo</label><input type="color" class="form-control form-control-color w-100" name="site_hero_bg" value="{{ settings.hero_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Hero caja</label><input type="color" class="form-control form-control-color w-100" name="site_hero_surface" value="{{ settings.hero_surface }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Sección fondo</label><input type="color" class="form-control form-control-color w-100" name="site_section_bg" value="{{ settings.section_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Sección alterna</label><input type="color" class="form-control form-control-color w-100" name="site_section_muted_bg" value="{{ settings.section_muted_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Tarjeta fondo</label><input type="color" class="form-control form-control-color w-100" name="site_card_bg" value="{{ settings.card_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Tarjeta texto</label><input type="color" class="form-control form-control-color w-100" name="site_card_text" value="{{ settings.card_text }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Títulos</label><input type="color" class="form-control form-control-color w-100" name="site_title_color" value="{{ settings.title_color }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Texto botón</label><input type="color" class="form-control form-control-color w-100" name="site_button_text" value="{{ settings.button_text }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Footer fondo</label><input type="color" class="form-control form-control-color w-100" name="site_footer_bg" value="{{ settings.footer_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Footer texto</label><input type="color" class="form-control form-control-color w-100" name="site_footer_text" value="{{ settings.footer_text }}"></div>
|
||
<div class="col-12"><div class="alert alert-light border mb-0">Estos controles impactan el sitio público: topbar, header, navegación, hero, secciones, cards, botones y footer, sin modificar la lógica ni el frontend estructural.</div></div>
|
||
<div class="col-12 d-grid"><button class="btn btn-primary btn-lg">Guardar diseño frontend</button></div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-4">
|
||
<div class="card table-panel h-100"><div class="card-body">
|
||
<h2 class="h5">Vista de referencia</h2>
|
||
<div class="public-style-preview rounded-4 overflow-hidden border">
|
||
<div style="background:{{ settings.topbar_bg }};color:{{ settings.topbar_text }};padding:.6rem 1rem;">Topbar institucional</div>
|
||
<div style="background:{{ settings.header_bg }};color:{{ settings.header_text }};padding:1rem;"><strong>{{ settings.title }}</strong><div style="color:{{ settings.nav_text }};font-size:.9rem;">Inicio · Servicios · Turnos</div></div>
|
||
<div style="background:{{ settings.hero_bg }};padding:1rem;"><div style="background:{{ settings.hero_surface }};border-radius:{{ settings.border_radius }}px;padding:1rem;color:{{ settings.card_text }};"><h3 style="color:{{ settings.title_color }};font-size:1.1rem;">Hero / sección principal</h3><p class="mb-2">Tarjeta de ejemplo con los colores elegidos.</p><span class="btn btn-sm" style="background:{{ settings.primary_color }};color:{{ settings.button_text }};">Botón</span></div></div>
|
||
<div style="background:{{ settings.footer_bg }};color:{{ settings.footer_text }};padding:.8rem 1rem;">Footer</div>
|
||
</div>
|
||
</div></div>
|
||
</div>
|
||
</div>
|
||
{% elif active_tab == 'style_admin' %}
|
||
<div class="card table-panel">
|
||
<div class="card-body">
|
||
<div class="d-flex justify-content-between align-items-start gap-3 flex-wrap mb-3">
|
||
<div>
|
||
<h2 class="h5 mb-1">Control visual del administrador</h2>
|
||
<p class="text-muted mb-0">Colores, tipografía, tamaño, sidebar, modales, secciones internas, títulos y footer del panel privado. No modifica el frontend público.</p>
|
||
</div>
|
||
<span class="badge text-bg-dark">Admin UI</span>
|
||
</div>
|
||
<form method="post" class="row g-3">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||
<input type="hidden" name="return_tab" value="style_admin">
|
||
<div class="col-12"><h3 class="h6 mb-0">Sidebar</h3></div>
|
||
<div class="col-md-3"><label class="form-label">Fondo sidebar</label><input type="color" class="form-control form-control-color w-100" name="admin_sidebar_bg" value="{{ settings.admin_style.sidebar_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Letra sidebar</label><input type="color" class="form-control form-control-color w-100" name="admin_sidebar_text" value="{{ settings.admin_style.sidebar_text }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Fondo activo</label><input type="color" class="form-control form-control-color w-100" name="admin_sidebar_active_bg" value="{{ settings.admin_style.sidebar_active_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Letra activa</label><input type="color" class="form-control form-control-color w-100" name="admin_sidebar_active_text" value="{{ settings.admin_style.sidebar_active_text }}"></div>
|
||
|
||
<div class="col-12 pt-2"><h3 class="h6 mb-0">Base general</h3></div>
|
||
<div class="col-md-3"><label class="form-label">Fondo admin</label><input type="color" class="form-control form-control-color w-100" name="admin_body_bg" value="{{ settings.admin_style.body_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Tarjetas / superficie</label><input type="color" class="form-control form-control-color w-100" name="admin_surface_bg" value="{{ settings.admin_style.surface_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Texto</label><input type="color" class="form-control form-control-color w-100" name="admin_text_color" value="{{ settings.admin_style.text_color }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Texto secundario</label><input type="color" class="form-control form-control-color w-100" name="admin_muted_text_color" value="{{ settings.admin_style.muted_text_color }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Color principal</label><input type="color" class="form-control form-control-color w-100" name="admin_primary_color" value="{{ settings.admin_style.primary_color }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Títulos</label><input type="color" class="form-control form-control-color w-100" name="admin_title_color" value="{{ settings.admin_style.title_color }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Radio bordes px</label><input class="form-control" name="admin_border_radius" value="{{ settings.admin_style.border_radius }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Tamaño fuente px</label><input class="form-control" name="admin_font_size" value="{{ settings.admin_style.font_size }}"></div>
|
||
<div class="col-12"><label class="form-label">Fuente admin</label><input class="form-control" name="admin_font_family" value="{{ settings.admin_style.font_family }}" placeholder="Inter, Roboto, system-ui, sans-serif"></div>
|
||
|
||
<div class="col-12 pt-2"><h3 class="h6 mb-0">Modales, secciones, inputs y footer</h3></div>
|
||
<div class="col-md-3"><label class="form-label">Fondo modal</label><input type="color" class="form-control form-control-color w-100" name="admin_modal_bg" value="{{ settings.admin_style.modal_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Secciones internas</label><input type="color" class="form-control form-control-color w-100" name="admin_section_bg" value="{{ settings.admin_style.section_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Inputs fondo</label><input type="color" class="form-control form-control-color w-100" name="admin_input_bg" value="{{ settings.admin_style.input_bg }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Inputs borde</label><input type="color" class="form-control form-control-color w-100" name="admin_input_border" value="{{ settings.admin_style.input_border }}"></div>
|
||
<div class="col-md-3"><label class="form-label">Footer</label><input type="color" class="form-control form-control-color w-100" name="admin_footer_bg" value="{{ settings.admin_style.footer_bg }}"></div>
|
||
<div class="col-12"><div class="alert alert-light border mb-0">La lunita del header permite alternar modo claro / oscuro por usuario, guardado en el navegador.</div></div>
|
||
<div class="col-12 d-grid"><button class="btn btn-primary btn-lg">Guardar Stylo Admin</button></div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
{% elif active_tab == 'popup' %}
|
||
<div class="card table-panel">
|
||
<div class="card-body">
|
||
<form method="post" enctype="multipart/form-data" class="row g-3">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||
<input type="hidden" name="return_tab" value="popup">
|
||
<div class="col-12"><div class="form-check form-switch"><input class="form-check-input" type="checkbox" name="site_popup_enabled" id="site_popup_enabled" {% if settings.popup_enabled %}checked{% endif %}><label class="form-check-label" for="site_popup_enabled">Habilitar popup al abrir el sitio</label></div></div>
|
||
<div class="col-md-6"><label class="form-label">Título del popup</label><input class="form-control" name="site_popup_title" value="{{ settings.popup_title }}"></div>
|
||
<div class="col-md-6"><label class="form-label">Imagen</label><input type="file" class="form-control" name="site_popup_image" accept="image/*">{% if settings.popup_image_path %}<div class="small text-muted mt-1">Actual: {{ settings.popup_image_path }}</div>{% endif %}</div>
|
||
<div class="col-12"><label class="form-label">Contenido enriquecido</label><textarea class="form-control html-editor" name="site_popup_html" rows="10">{{ settings.popup_html }}</textarea></div>
|
||
<div class="col-md-6"><label class="form-label">Texto del link / botón</label><input class="form-control" name="site_popup_link_text" value="{{ settings.popup_link_text }}"></div>
|
||
<div class="col-md-6"><label class="form-label">URL del link / botón</label><input class="form-control" name="site_popup_link_url" value="{{ settings.popup_link_url }}"></div>
|
||
<div class="col-12 d-grid"><button class="btn btn-primary btn-lg">Guardar popup</button></div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
{% elif active_tab == 'legal' %}
|
||
<div class="row g-4">
|
||
<div class="col-lg-4">
|
||
<div class="card table-panel h-100"><div class="card-body">
|
||
<form method="post" class="row g-3">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||
<input type="hidden" name="return_tab" value="legal">
|
||
<div class="col-12"><div class="form-check form-switch"><input class="form-check-input" type="checkbox" name="site_cookie_banner_enabled" id="site_cookie_banner_enabled" {% if settings.cookie_banner_enabled %}checked{% endif %}><label class="form-check-label" for="site_cookie_banner_enabled">Mostrar aviso de cookies / consentimiento</label></div></div>
|
||
<div class="col-12"><label class="form-label">Texto de cookies / consentimiento</label><textarea class="form-control html-editor" name="site_cookie_text" rows="10">{{ settings.cookie_text }}</textarea></div>
|
||
<div class="col-12 d-grid"><button class="btn btn-primary">Guardar cookies</button></div>
|
||
</form>
|
||
</div></div>
|
||
</div>
|
||
<div class="col-lg-8">
|
||
<div class="card table-panel"><div class="card-body">
|
||
<form method="post" class="row g-3">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||
<input type="hidden" name="return_tab" value="legal">
|
||
<div class="col-12"><label class="form-label">Términos y condiciones</label><textarea class="form-control html-editor" name="site_terms_html" rows="12">{{ settings.terms_html }}</textarea></div>
|
||
<div class="col-12"><label class="form-label">Privacidad y protección de datos</label><textarea class="form-control html-editor" name="site_privacy_html" rows="12">{{ settings.privacy_html }}</textarea></div>
|
||
<div class="col-12 d-grid"><button class="btn btn-primary">Guardar contenido legal</button></div>
|
||
</form>
|
||
</div></div>
|
||
</div>
|
||
</div>
|
||
{% else %}
|
||
<div class="row g-4">
|
||
<div class="col-lg-8">
|
||
<div class="card table-panel"><div class="card-header"><strong>Bloques del frontend</strong></div><div class="table-responsive wide-table"><table class="table align-middle mb-0"><thead><tr><th>Sección</th><th>Título</th><th>Resumen</th><th>Orden</th><th class="text-end">Acciones</th></tr></thead><tbody>
|
||
{% for section, label in section_labels.items() %}
|
||
{% for item in grouped.get(section, []) %}
|
||
<tr>
|
||
<td><span class="badge text-bg-light">{{ label }}</span></td>
|
||
<td>{{ item.title or '—' }}</td>
|
||
<td class="text-wrap">{{ item.body or item.subtitle or '—' }}</td>
|
||
<td>{{ item.sort_order }}</td>
|
||
<td class="text-end"><div class="d-flex gap-2 justify-content-end"><button class="btn btn-sm btn-outline-primary frontend-edit-btn" data-block='{{ {"id": item.id, "section": item.section, "key": item.key, "title": item.title, "subtitle": item.subtitle, "body": item.body, "icon": item.icon, "link_url": item.link_url, "link_text": item.link_text, "sort_order": item.sort_order, "extra_json": item.extra_json, "is_active": item.is_active, "image_path": item.image_path}|tojson|safe }}' data-bs-toggle="modal" data-bs-target="#frontendBlockModal">Editar</button><form method="post" action="{{ url_for('admin_frontend') }}" onsubmit="return confirm('¿Eliminar bloque?')">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}"><input type="hidden" name="action" value="delete_block"><input type="hidden" name="block_id" value="{{ item.id }}"><button class="btn btn-sm btn-outline-danger">Eliminar</button></form></div></td>
|
||
</tr>
|
||
{% endfor %}
|
||
{% endfor %}
|
||
{% if not grouped.values()|select|list %}<tr><td colspan="5" class="text-center text-muted py-4">No hay bloques configurados todavía.</td></tr>{% endif %}
|
||
</tbody></table></div></div>
|
||
</div>
|
||
<div class="col-lg-4">
|
||
<div class="card table-panel h-100"><div class="card-body">
|
||
<h2 class="h5 mb-3">Control del template</h2>
|
||
<p class="text-muted">Desde esta pantalla administrás contenido estructural, diseño, popup, legal y todos los bloques del frontend, evitando duplicación entre “Sitio Web” y “Frontend”.</p>
|
||
<div class="d-grid gap-2">
|
||
<a class="btn btn-outline-primary" href="{{ url_for('admin_site_settings', tab='general') }}">Editar datos generales</a>
|
||
<a class="btn btn-outline-primary" href="{{ url_for('admin_site_settings', tab='design') }}">Editar diseño</a>
|
||
<a class="btn btn-outline-primary" href="{{ url_for('admin_site_settings', tab='popup') }}">Editar popup</a>
|
||
<a class="btn btn-outline-primary" href="{{ url_for('admin_site_settings', tab='legal') }}">Editar legal / cookies</a>
|
||
</div>
|
||
</div></div>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
|
||
<div class="modal fade" id="frontendBlockModal" tabindex="-1" aria-hidden="true"><div class="modal-dialog modal-xl modal-dialog-scrollable"><div class="modal-content"><div class="modal-header"><h5 class="modal-title">Bloque del frontend</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
|
||
<form method="post" enctype="multipart/form-data" id="frontendBlockForm" action="{{ url_for('admin_frontend') }}">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||
<input type="hidden" name="action" value="save_block"><input type="hidden" name="block_id" id="frontend_block_id">
|
||
<div class="modal-body"><div class="row g-4">
|
||
<div class="col-lg-4"><div class="section-card h-100"><div class="section-title">Clasificación</div><div class="row g-3"><div class="col-12"><label class="form-label">Sección</label><select class="form-select searchable-select" name="section" id="frontend_section" required>{% for section, label in section_labels.items() %}<option value="{{ section }}">{{ label }}</option>{% endfor %}</select></div><div class="col-12"><label class="form-label">Clave</label><input class="form-control" name="key" id="frontend_key" placeholder="slug interno"></div><div class="col-md-6"><label class="form-label">Orden</label><input class="form-control" name="sort_order" id="frontend_sort_order" value="0"></div><div class="col-md-6 d-flex align-items-end"><div class="form-check"><input class="form-check-input" type="checkbox" name="is_active" id="frontend_is_active" checked><label class="form-check-label">Activo</label></div></div><div class="col-12"><label class="form-label">Ícono</label><input class="form-control" name="icon" id="frontend_icon" placeholder="bi bi-heart-pulse"></div><div class="col-12"><label class="form-label">Imagen</label><input type="file" class="form-control" name="image_file"><div class="small text-muted mt-1" id="frontend_image_hint"></div></div></div></div></div>
|
||
<div class="col-lg-8"><div class="section-card"><div class="section-title">Contenido</div><div class="row g-3"><div class="col-md-6"><label class="form-label">Título</label><input class="form-control" name="title" id="frontend_title"></div><div class="col-md-6"><label class="form-label">Subtítulo / número</label><input class="form-control" name="subtitle" id="frontend_subtitle"></div><div class="col-12"><label class="form-label">Texto / descripción</label><textarea class="form-control" name="body" id="frontend_body" rows="6"></textarea></div><div class="col-md-6"><label class="form-label">Link URL</label><input class="form-control" name="link_url" id="frontend_link_url"></div><div class="col-md-6"><label class="form-label">Texto del link</label><input class="form-control" name="link_text" id="frontend_link_text"></div><div class="col-12"><label class="form-label">JSON extra</label><textarea class="form-control" name="extra_json" id="frontend_extra_json" rows="4" placeholder='Ej. {"align":"center"}'></textarea></div></div></div></div>
|
||
</div></div>
|
||
<div class="modal-footer"><button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancelar</button><button class="btn btn-primary">Guardar bloque</button></div>
|
||
</form>
|
||
</div></div></div>
|
||
{% endblock %}
|
||
{% block scripts %}
|
||
{{ super() }}
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
document.querySelectorAll('.frontend-edit-btn').forEach(function(btn){
|
||
btn.addEventListener('click', function(){
|
||
const data = JSON.parse(btn.getAttribute('data-block'));
|
||
document.getElementById('frontend_block_id').value = data.id || '';
|
||
document.getElementById('frontend_section').value = data.section || '';
|
||
document.getElementById('frontend_key').value = data.key || '';
|
||
document.getElementById('frontend_sort_order').value = data.sort_order || 0;
|
||
document.getElementById('frontend_title').value = data.title || '';
|
||
document.getElementById('frontend_subtitle').value = data.subtitle || '';
|
||
document.getElementById('frontend_body').value = data.body || '';
|
||
document.getElementById('frontend_icon').value = data.icon || '';
|
||
document.getElementById('frontend_link_url').value = data.link_url || '';
|
||
document.getElementById('frontend_link_text').value = data.link_text || '';
|
||
document.getElementById('frontend_extra_json').value = data.extra_json || '';
|
||
document.getElementById('frontend_is_active').checked = !!data.is_active;
|
||
document.getElementById('frontend_image_hint').textContent = data.image_path ? ('Actual: ' + data.image_path) : '';
|
||
});
|
||
});
|
||
const modal = document.getElementById('frontendBlockModal');
|
||
if (modal) {
|
||
modal.addEventListener('hidden.bs.modal', function(){
|
||
document.getElementById('frontendBlockForm').reset();
|
||
document.getElementById('frontend_block_id').value='';
|
||
document.getElementById('frontend_image_hint').textContent='';
|
||
});
|
||
}
|
||
});
|
||
</script>
|
||
{% endblock %}
|