Files
roi-theme/wp-content/themes/apus-theme/single.php
FrankZamora c5ce5eb06d [COMPONENTE 11] Implementar Sidebar TOC con ScrollSpy custom - Issue #121
- CREAR: template-parts/content-toc.php
  * Función PHP apu_generate_toc() para generar TOC automáticamente
  * Regex para buscar H2 con atributo ID
  * Solo se muestra en is_single()

- MODIFICAR: single.php (sidebar)
  * Agregar div.sidebar-sticky wrapper
  * Integrar get_template_part('template-parts/content', 'toc')
  * Preparar espacio para CTA Box (componente 12)

- MODIFICAR: style.css (+87 líneas)
  * 9 selectores CSS + 4 pseudo-elementos scrollbar
  * Sticky positioning (top: 85px)
  * Max-height calculado con calc()
  * Scroll interno con overflow-y: auto
  * Min-height: 0 (crítico para scroll en flexbox)
  * Border-left indicator (navy, NO naranja)
  * Scrollbar personalizado 6px (solo Webkit)

- MODIFICAR: main.js (+66 líneas)
  * Función updateActiveSection() para ScrollSpy
  * Algoritmo SIMPLE: verifica si pasaste el top
  * Offset scroll: navbarHeight + 100
  * Smooth scroll: navbarHeight + 40
  * Selector .toc-container a (NO .toc-link)
  * NO tiene auto-scroll del TOC
  * NO actualiza URL con history.pushState()

Características:
 Generación automática desde H2 con ID
 ScrollSpy custom (JavaScript vanilla, NO Bootstrap)
 Sticky positioning con flexbox
 Scroll interno solo en lista
 Border-left indicator activo
 Scrollbar delgado personalizado

Selectores REALES usados:
- .toc-container a (NO .toc-link)
- .toc-container h4 (NO .toc-title)
- .toc-container li (NO .toc-list li)

🎨 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 09:55:56 -06:00

212 lines
7.4 KiB
PHP

<?php
/**
* Single Post Template
*
* Replica EXACTAMENTE la estructura del template RDash (líneas 135-1020)
* Sin wrappers extra de WordPress tradicional.
*
* @package Apus_Theme
* @since 1.0.0
*/
get_header();
?>
<?php while (have_posts()) : the_post(); ?>
<!-- Hero Section (Template líneas 141-167) -->
<div class="container-fluid py-5 mb-4 hero-title">
<div class="container">
<!-- Category Badges -->
<div class="mb-3 d-flex justify-content-center">
<div class="d-flex gap-2 flex-wrap justify-content-center">
<?php
$categories = get_the_category();
if (!empty($categories)) {
foreach ($categories as $category) {
if ($category->name !== 'Uncategorized' && $category->name !== 'Sin categoría') {
?>
<a href="<?php echo esc_url(get_category_link($category->term_id)); ?>" class="category-badge category-badge-hero">
<i class="bi bi-folder-fill me-1"></i>
<?php echo esc_html($category->name); ?>
</a>
<?php
}
}
}
?>
</div>
</div>
<!-- Post Title -->
<h1 class="display-5 fw-bold text-center"><?php the_title(); ?></h1>
</div>
</div>
<!-- Main Content Grid (Template líneas 169-1020) -->
<div class="container">
<div class="row">
<!-- Main Content Column (col-lg-9) -->
<div class="col-lg-9">
<!-- Featured Image -->
<?php if (has_post_thumbnail()) : ?>
<div class="featured-image-container my-4">
<?php the_post_thumbnail('full', array('class' => 'img-fluid', 'loading' => 'lazy')); ?>
</div>
<?php endif; ?>
<!-- Post Content -->
<article class="post-content">
<?php
the_content();
wp_link_pages(array(
'before' => '<div class="page-links">' . esc_html__('Pages:', 'apus-theme'),
'after' => '</div>',
));
?>
</article>
<!-- Share Buttons (Template líneas 786-810) -->
<div class="my-5 py-4 border-top">
<p class="mb-3 text-muted"><?php esc_html_e('Compartir:', 'apus-theme'); ?></p>
<div class="d-flex gap-2 flex-wrap share-buttons">
<a href="https://www.facebook.com/sharer/sharer.php?u=<?php echo urlencode(get_permalink()); ?>"
class="btn btn-outline-primary btn-sm" target="_blank" rel="noopener">
<i class="bi bi-facebook me-1"></i> Facebook
</a>
<a href="https://www.instagram.com/"
class="btn btn-outline-danger btn-sm" target="_blank" rel="noopener">
<i class="bi bi-instagram me-1"></i> Instagram
</a>
<a href="https://www.linkedin.com/sharing/share-offsite/?url=<?php echo urlencode(get_permalink()); ?>"
class="btn btn-outline-info btn-sm" target="_blank" rel="noopener">
<i class="bi bi-linkedin me-1"></i> LinkedIn
</a>
<a href="https://wa.me/?text=<?php echo urlencode(get_the_title() . ' ' . get_permalink()); ?>"
class="btn btn-outline-success btn-sm" target="_blank" rel="noopener">
<i class="bi bi-whatsapp me-1"></i> WhatsApp
</a>
<a href="https://twitter.com/intent/tweet?url=<?php echo urlencode(get_permalink()); ?>&text=<?php echo urlencode(get_the_title()); ?>"
class="btn btn-outline-dark btn-sm" target="_blank" rel="noopener">
<i class="bi bi-twitter-x me-1"></i> X
</a>
<a href="mailto:?subject=<?php echo urlencode(get_the_title()); ?>&body=<?php echo urlencode(get_permalink()); ?>"
class="btn btn-outline-secondary btn-sm">
<i class="bi bi-envelope me-1"></i> Email
</a>
</div>
</div>
<!-- CTA A/B Testing (Template líneas 812-841) -->
<div class="cta-section cta-variant-a" data-variant="A" style="display: none;">
<div class="row align-items-center">
<div class="col-md-8">
<h3 class="cta-title"><?php esc_html_e('¿Necesitas acceso a nuestro catálogo completo?', 'apus-theme'); ?></h3>
<p class="cta-text mb-md-0"><?php esc_html_e('Descarga miles de análisis de precios unitarios actualizados', 'apus-theme'); ?></p>
</div>
<div class="col-md-4 text-md-end">
<a href="<?php echo esc_url(home_url('/catalogo')); ?>" class="btn btn-light btn-lg cta-button" data-cta-variant="A">
<?php esc_html_e('Ver Catálogo', 'apus-theme'); ?>
</a>
</div>
</div>
</div>
<div class="cta-section cta-variant-b" data-variant="B" style="display: none;">
<div class="row align-items-center">
<div class="col-md-8">
<h3 class="cta-title"><?php esc_html_e('¿Listo para optimizar tus proyectos?', 'apus-theme'); ?></h3>
<p class="cta-text mb-md-0"><?php esc_html_e('Únete a nuestra membresía y accede a contenido exclusivo', 'apus-theme'); ?></p>
</div>
<div class="col-md-4 text-md-end">
<a href="<?php echo esc_url(home_url('/planes')); ?>" class="btn btn-light btn-lg cta-button" data-cta-variant="B">
<?php esc_html_e('Conocer Planes', 'apus-theme'); ?>
</a>
</div>
</div>
</div>
<!-- Related Posts (Template líneas 843-981) -->
<div class="my-5 related-posts">
<h2 class="h3 mb-4"><?php esc_html_e('Descubre Más Contenido', 'apus-theme'); ?></h2>
<div class="row g-4">
<?php
// Query para related posts
$related_args = array(
'post_type' => 'post',
'posts_per_page' => 12,
'post__not_in' => array(get_the_ID()),
'orderby' => 'rand',
'no_found_rows' => true,
);
$related_query = new WP_Query($related_args);
if ($related_query->have_posts()) :
while ($related_query->have_posts()) : $related_query->the_post();
?>
<div class="col-md-4">
<a href="<?php the_permalink(); ?>" class="text-decoration-none">
<div class="card h-100 shadow-sm">
<div class="card-body d-flex align-items-center justify-content-center p-4">
<h5 class="card-title h6 mb-0 text-center"><?php the_title(); ?></h5>
</div>
</div>
</a>
</div>
<?php
endwhile;
wp_reset_postdata();
endif;
?>
</div>
<!-- Pagination (Template líneas 957-980) -->
<nav aria-label="<?php esc_attr_e('Navegación de posts relacionados', 'apus-theme'); ?>" class="mt-4">
<ul class="pagination justify-content-center">
<li class="page-item">
<a class="page-link" href="#" aria-label="<?php esc_attr_e('Inicio', 'apus-theme'); ?>">
<?php esc_html_e('Inicio', 'apus-theme'); ?>
</a>
</li>
<li class="page-item active" aria-current="page">
<a class="page-link" href="#">1</a>
</li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">4</a></li>
<li class="page-item"><a class="page-link" href="#">5</a></li>
<li class="page-item">
<a class="page-link" href="#"><?php esc_html_e('Ver más', 'apus-theme'); ?></a>
</li>
<li class="page-item">
<a class="page-link" href="#" aria-label="<?php esc_attr_e('Fin', 'apus-theme'); ?>">
<?php esc_html_e('Fin', 'apus-theme'); ?>
</a>
</li>
</ul>
</nav>
</div><!-- .related-posts -->
</div><!-- .col-lg-9 -->
<!-- Sidebar Column (col-lg-3) -->
<div class="col-lg-3">
<div class="sidebar-sticky">
<?php get_template_part('template-parts/content', 'toc'); ?>
<!-- Aquí irá el CTA Box (componente 12) -->
</div>
</div>
</div><!-- .row -->
</div><!-- .container -->
<?php endwhile; ?>
<?php
get_footer();