feat: sitio CV completo v1.0.0
- 4 temas WordPress: persona-cv (activo), lumina, apex-cv, cvolio - Plugin pflores-cv-fields con CMB2 (100% gratuito) — admin editable - Generador PDF dinámico con Chromium headless (?cv_pdf=1) - Datos del CV de Patricia Flores cargados en CMB2 - URL dinámica con soporte proxy SSL (NPM/X-Forwarded-Proto) - WP Mail SMTP instalado (pendiente config SMTP) - Documentación completa: PROMPT_IA.md, DEPLOY_WEB.md, PRODUCCION.md, VERSIONADO.md
This commit is contained in:
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 535 B |
@@ -0,0 +1,10 @@
|
||||
<svg width="640" height="760" viewBox="0 0 640 760" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="640" height="760" rx="48" fill="#F7EFE4"/>
|
||||
<circle cx="320" cy="238" r="112" fill="#E6B596"/>
|
||||
<path d="M182 612C182 515.35 260.35 437 357 437H283C379.65 437 458 515.35 458 612V640H182V612Z" fill="#D4582B"/>
|
||||
<path d="M221 230C221 175.324 265.324 131 320 131C374.676 131 419 175.324 419 230V284C419 338.676 374.676 383 320 383C265.324 383 221 338.676 221 284V230Z" fill="#1F1D1A"/>
|
||||
<path d="M244 245C244 202.474 278.474 168 321 168C363.526 168 398 202.474 398 245V283C398 325.526 363.526 360 321 360C278.474 360 244 325.526 244 283V245Z" fill="#F5CBB2"/>
|
||||
<rect x="116" y="488" width="408" height="28" rx="14" fill="#F2DDCC"/>
|
||||
<rect x="116" y="536" width="332" height="24" rx="12" fill="#F2DDCC"/>
|
||||
<rect x="116" y="578" width="280" height="24" rx="12" fill="#F2DDCC"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 902 B |
@@ -0,0 +1,60 @@
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const toggle = document.querySelector(".lm-nav-toggle");
|
||||
const nav = document.querySelector(".lm-nav");
|
||||
|
||||
if (toggle && nav) {
|
||||
toggle.addEventListener("click", () => {
|
||||
const expanded = toggle.getAttribute("aria-expanded") === "true";
|
||||
toggle.setAttribute("aria-expanded", String(!expanded));
|
||||
nav.classList.toggle("is-open", !expanded);
|
||||
});
|
||||
|
||||
document.addEventListener("click", (e) => {
|
||||
if (!nav.contains(e.target) && !toggle.contains(e.target)) {
|
||||
nav.classList.remove("is-open");
|
||||
toggle.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll("[data-lumina-print]").forEach((btn) => {
|
||||
btn.addEventListener("click", () => window.print());
|
||||
});
|
||||
|
||||
const header = document.querySelector(".lm-header");
|
||||
if (header) {
|
||||
let lastY = window.scrollY;
|
||||
window.addEventListener("scroll", () => {
|
||||
const currentY = window.scrollY;
|
||||
if (currentY > 80) {
|
||||
header.style.boxShadow = "0 2px 16px rgba(0,0,0,.12)";
|
||||
} else {
|
||||
header.style.boxShadow = "";
|
||||
}
|
||||
lastY = currentY;
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
const sections = document.querySelectorAll("[id]");
|
||||
const navLinks = document.querySelectorAll(".lm-nav__list a[href^='#']");
|
||||
|
||||
if (navLinks.length && sections.length) {
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
navLinks.forEach((link) => {
|
||||
link.classList.toggle(
|
||||
"is-active",
|
||||
link.getAttribute("href") === `#${entry.target.id}`
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
{ rootMargin: "-20% 0px -70% 0px" }
|
||||
);
|
||||
|
||||
sections.forEach((section) => observer.observe(section));
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
?>
|
||||
</main>
|
||||
|
||||
<footer class="lm-footer">
|
||||
<div class="lm-footer__inner">
|
||||
<p class="lm-footer__copy">
|
||||
<?php echo esc_html(get_bloginfo('name')); ?> · <?php echo esc_html(date_i18n('Y')); ?>
|
||||
</p>
|
||||
<a class="lm-footer__top" href="#top" aria-label="<?php esc_attr_e('Volver al inicio', 'lumina'); ?>">↑</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<?php wp_footer(); ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,343 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
get_header();
|
||||
|
||||
$cv = function_exists('pflores_get_cv_data') ? pflores_get_cv_data() : lumina_cv_data();
|
||||
$hero = $cv['hero'];
|
||||
$metrics = $cv['metrics'];
|
||||
$highlights = $cv['highlights'];
|
||||
$summary = $cv['summary'];
|
||||
$impact = $cv['impact'];
|
||||
$experience = $cv['experience'];
|
||||
$education = $cv['education'];
|
||||
$certifications = $cv['certifications'];
|
||||
$competencies = $cv['competencies'];
|
||||
$volunteer = $cv['volunteer'];
|
||||
$additional = $cv['additional'];
|
||||
|
||||
$qrImage = get_template_directory_uri() . '/assets/images/patricia-flores-qr.png';
|
||||
$publicUrl = 'https://pflores.linkedcorp.net';
|
||||
|
||||
$heroName = $hero['name'];
|
||||
$heroRole = $hero['role'];
|
||||
$heroIntro = $hero['intro'];
|
||||
$heroLocation = $hero['location'];
|
||||
$heroEmail = $hero['email'];
|
||||
$heroPhone = $hero['phone'];
|
||||
$heroCtaLabel = 'Ver trayectoria';
|
||||
$heroCtaUrl = '#experiencia';
|
||||
$linkedin = $hero['linkedin'];
|
||||
$acfPhoto = $cv['photo'] ?? '';
|
||||
$profileImage = $acfPhoto ?: get_template_directory_uri() . '/assets/images/patricia-flores-profile.jpeg';
|
||||
$cvFile = get_template_directory_uri() . '/assets/docs/CV_Patricia_Flores_Sanchez_ES_FINAL.docx';
|
||||
?>
|
||||
|
||||
<!-- ================================================
|
||||
HERO — gradiente teal centrado, foto circular
|
||||
================================================ -->
|
||||
<section class="lm-hero">
|
||||
<div class="lm-hero__bg-pattern" aria-hidden="true"></div>
|
||||
|
||||
<div class="lm-hero__center">
|
||||
<div class="lm-hero__avatar">
|
||||
<img
|
||||
src="<?php echo esc_url($profileImage); ?>"
|
||||
alt="<?php echo esc_attr($heroName); ?>"
|
||||
class="lm-hero__photo"
|
||||
>
|
||||
</div>
|
||||
|
||||
<p class="lm-eyebrow lm-eyebrow--light"><?php echo esc_html($hero['eyebrow']); ?></p>
|
||||
<h1 class="lm-hero__name"><?php echo esc_html($heroName); ?></h1>
|
||||
<p class="lm-hero__role"><?php echo esc_html($heroRole); ?></p>
|
||||
<p class="lm-hero__intro"><?php echo esc_html($heroIntro); ?></p>
|
||||
|
||||
<div class="lm-hero__chips">
|
||||
<span class="lm-chip lm-chip--hero">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
|
||||
<?php echo esc_html($heroLocation); ?>
|
||||
</span>
|
||||
<?php if ($heroEmail) : ?>
|
||||
<a class="lm-chip lm-chip--hero" href="mailto:<?php echo esc_attr(antispambot($heroEmail)); ?>">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
|
||||
<?php echo esc_html($heroEmail); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($heroPhone) : ?>
|
||||
<a class="lm-chip lm-chip--hero" href="tel:<?php echo esc_attr(preg_replace('/[^0-9+]/', '', $heroPhone)); ?>">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.69 12 19.79 19.79 0 0 1 1.61 3.41 2 2 0 0 1 3.6 1.25h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L7.91 8.96a16 16 0 0 0 6.02 6.02l.96-.96a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 21.73 16.92z"/></svg>
|
||||
<?php echo esc_html($heroPhone); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<?php if ($linkedin) : ?>
|
||||
<a class="lm-chip lm-chip--hero" href="<?php echo esc_url($linkedin); ?>" target="_blank" rel="noreferrer">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"/><rect x="2" y="9" width="4" height="12"/><circle cx="4" cy="4" r="2"/></svg>
|
||||
LinkedIn
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="lm-hero__actions">
|
||||
<a class="lm-btn lm-btn--amber" href="<?php echo esc_url($heroCtaUrl); ?>">
|
||||
<?php echo esc_html($heroCtaLabel); ?>
|
||||
</a>
|
||||
<a class="lm-btn lm-btn--white" href="<?php echo esc_url(home_url('/?cv_pdf=1')); ?>">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
||||
<?php esc_html_e('Descargar CV PDF', 'lumina'); ?>
|
||||
</a>
|
||||
<button class="lm-btn lm-btn--ghost-light" type="button" data-lumina-print>
|
||||
<?php esc_html_e('Versión imprimible', 'lumina'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Métricas strip -->
|
||||
<div class="lm-hero__metrics">
|
||||
<?php foreach ($metrics as $metric) : ?>
|
||||
<div class="lm-metric">
|
||||
<strong><?php echo esc_html($metric['value']); ?></strong>
|
||||
<span><?php echo esc_html($metric['label']); ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Wave decorativa -->
|
||||
<div class="lm-hero__wave" aria-hidden="true">
|
||||
<svg viewBox="0 0 1440 80" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg"><path d="M0,40 C360,80 1080,0 1440,40 L1440,80 L0,80 Z" fill="var(--lm-bg)"/></svg>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ================================================
|
||||
HIGHLIGHTS — 4 números de impacto
|
||||
================================================ -->
|
||||
<section class="lm-section lm-highlights-section" id="impacto">
|
||||
<div class="lm-container">
|
||||
<header class="lm-section-head lm-section-head--center">
|
||||
<p class="lm-eyebrow"><?php esc_html_e('Resultados medibles', 'lumina'); ?></p>
|
||||
<h2><?php esc_html_e('Impacto ejecutivo con alcance nacional', 'lumina'); ?></h2>
|
||||
</header>
|
||||
|
||||
<div class="lm-highlights-grid">
|
||||
<?php foreach ($highlights as $h) : ?>
|
||||
<article class="lm-highlight-card">
|
||||
<strong><?php echo esc_html($h['value']); ?></strong>
|
||||
<span><?php echo esc_html($h['label']); ?></span>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div class="lm-impact-row">
|
||||
<?php foreach ($impact as $item) : ?>
|
||||
<article class="lm-impact-card">
|
||||
<div class="lm-impact-card__icon" aria-hidden="true">
|
||||
<?php if ($item['title'] === 'Transformación digital') : ?>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
|
||||
<?php elseif ($item['title'] === 'Automatización crítica') : ?>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="3"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 4.93a10 10 0 0 0 0 14.14"/><path d="M16.24 7.76a6 6 0 0 1 0 8.49M7.76 7.76a6 6 0 0 0 0 8.49"/></svg>
|
||||
<?php else : ?>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<h3><?php echo esc_html($item['title']); ?></h3>
|
||||
<p><?php echo esc_html($item['body']); ?></p>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ================================================
|
||||
CUERPO PRINCIPAL — sidebar izquierdo + contenido
|
||||
================================================ -->
|
||||
<div class="lm-body lm-container">
|
||||
|
||||
<!-- SIDEBAR IZQUIERDO -->
|
||||
<aside class="lm-sidebar">
|
||||
|
||||
<!-- Perfil rápido -->
|
||||
<section class="lm-widget lm-widget--profile" id="resumen">
|
||||
<p class="lm-eyebrow"><?php esc_html_e('Perfil profesional', 'lumina'); ?></p>
|
||||
<h2><?php echo esc_html($summary['title']); ?></h2>
|
||||
<p><?php echo esc_html($summary['body']); ?></p>
|
||||
|
||||
<dl class="lm-quick-info">
|
||||
<div>
|
||||
<dt><?php esc_html_e('Disponibilidad', 'lumina'); ?></dt>
|
||||
<dd><?php echo esc_html($hero['availability']); ?></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt><?php esc_html_e('Enfoque', 'lumina'); ?></dt>
|
||||
<dd><?php echo esc_html($hero['focus']); ?></dd>
|
||||
</div>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<!-- Competencias -->
|
||||
<section class="lm-widget lm-widget--skills">
|
||||
<p class="lm-eyebrow"><?php esc_html_e('Competencias clave', 'lumina'); ?></p>
|
||||
<h2><?php esc_html_e('Capacidades ejecutivas y técnicas', 'lumina'); ?></h2>
|
||||
|
||||
<?php foreach ($competencies as $group => $items) : ?>
|
||||
<div class="lm-skill-group">
|
||||
<h3><?php echo esc_html($group); ?></h3>
|
||||
<div class="lm-pills">
|
||||
<?php foreach ($items as $item) : ?>
|
||||
<span class="lm-pill"><?php echo esc_html(is_array($item) ? ($item['name'] ?? '') : $item); ?></span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</section>
|
||||
|
||||
<!-- Voluntariado -->
|
||||
<section class="lm-widget">
|
||||
<p class="lm-eyebrow"><?php esc_html_e('Voluntariado', 'lumina'); ?></p>
|
||||
<h2><?php echo esc_html($volunteer['title']); ?></h2>
|
||||
<p class="lm-widget__year"><?php echo esc_html($volunteer['year']); ?></p>
|
||||
<p><?php echo esc_html($volunteer['body']); ?></p>
|
||||
</section>
|
||||
|
||||
<!-- Datos adicionales -->
|
||||
<section class="lm-widget" id="contacto">
|
||||
<p class="lm-eyebrow"><?php esc_html_e('Información adicional', 'lumina'); ?></p>
|
||||
<h2><?php esc_html_e('Datos clave del perfil', 'lumina'); ?></h2>
|
||||
|
||||
<dl class="lm-info-list">
|
||||
<?php foreach ($additional as $label => $value) : ?>
|
||||
<div>
|
||||
<dt><?php echo esc_html($label); ?></dt>
|
||||
<dd><?php echo esc_html($value); ?></dd>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</dl>
|
||||
|
||||
<div class="lm-contact-links">
|
||||
<?php echo wp_kses_post(lumina_contact_link('email', $heroEmail)); ?>
|
||||
<?php echo wp_kses_post(lumina_contact_link('phone', $heroPhone)); ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tarjeta de presentación -->
|
||||
<section class="lm-widget lm-widget--card">
|
||||
<p class="lm-eyebrow"><?php esc_html_e('Tarjeta de presentación', 'lumina'); ?></p>
|
||||
<h2><?php esc_html_e('Perfil digital', 'lumina'); ?></h2>
|
||||
|
||||
<article class="lm-bcard">
|
||||
<div class="lm-bcard__header">
|
||||
<p class="lm-bcard__name"><?php echo esc_html($heroName); ?></p>
|
||||
<p class="lm-bcard__role"><?php echo esc_html($heroRole); ?></p>
|
||||
</div>
|
||||
<div class="lm-bcard__body">
|
||||
<div class="lm-bcard__qr">
|
||||
<img src="<?php echo esc_url($qrImage); ?>" alt="<?php esc_attr_e('Código QR hacia el perfil web', 'lumina'); ?>">
|
||||
</div>
|
||||
<div class="lm-bcard__info">
|
||||
<p><?php echo esc_html($heroLocation); ?></p>
|
||||
<p><?php echo esc_html($heroPhone); ?></p>
|
||||
<p><?php echo esc_html($heroEmail); ?></p>
|
||||
<a href="<?php echo esc_url($publicUrl); ?>" target="_blank" rel="noreferrer"><?php echo esc_html($publicUrl); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
</aside><!-- /.lm-sidebar -->
|
||||
|
||||
<!-- CONTENIDO PRINCIPAL -->
|
||||
<div class="lm-content">
|
||||
|
||||
<!-- Experiencia -->
|
||||
<section class="lm-section-inner" id="experiencia">
|
||||
<header class="lm-section-head">
|
||||
<p class="lm-eyebrow"><?php esc_html_e('Experiencia profesional', 'lumina'); ?></p>
|
||||
<h2><?php esc_html_e('Trayectoria sólida en banca, operaciones y microfinanzas', 'lumina'); ?></h2>
|
||||
</header>
|
||||
|
||||
<div class="lm-timeline">
|
||||
<?php foreach ($experience as $job) : ?>
|
||||
<article class="lm-timeline__item">
|
||||
<div class="lm-timeline__marker" aria-hidden="true"></div>
|
||||
<div class="lm-timeline__body">
|
||||
<span class="lm-timeline__period"><?php echo esc_html($job['period']); ?></span>
|
||||
<h3><?php echo esc_html($job['title']); ?></h3>
|
||||
<p class="lm-timeline__meta">
|
||||
<strong><?php echo esc_html($job['company']); ?></strong>
|
||||
· <?php echo esc_html($job['location']); ?>
|
||||
</p>
|
||||
<p class="lm-timeline__lead"><?php echo esc_html($job['lead']); ?></p>
|
||||
<ul class="lm-timeline__bullets">
|
||||
<?php foreach ($job['bullets'] as $bullet) : ?>
|
||||
<li><?php echo esc_html($bullet); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Formación -->
|
||||
<section class="lm-section-inner" id="formacion">
|
||||
<header class="lm-section-head">
|
||||
<p class="lm-eyebrow"><?php esc_html_e('Formación académica', 'lumina'); ?></p>
|
||||
<h2><?php esc_html_e('Base técnica y formación ejecutiva de alto nivel', 'lumina'); ?></h2>
|
||||
</header>
|
||||
|
||||
<div class="lm-edu-grid">
|
||||
<?php foreach ($education as $edu) : ?>
|
||||
<article class="lm-edu-card">
|
||||
<span class="lm-edu-card__year"><?php echo esc_html($edu['year']); ?></span>
|
||||
<div>
|
||||
<h3><?php echo esc_html($edu['title']); ?></h3>
|
||||
<p><?php echo esc_html($edu['institution']); ?></p>
|
||||
<?php if ($edu['detail'] !== '') : ?>
|
||||
<p class="lm-edu-card__detail"><?php echo esc_html($edu['detail']); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Certificaciones -->
|
||||
<section class="lm-section-inner" id="certificaciones">
|
||||
<header class="lm-section-head">
|
||||
<p class="lm-eyebrow"><?php esc_html_e('Certificaciones relevantes', 'lumina'); ?></p>
|
||||
<h2><?php esc_html_e('Actualización continua en gerencia, procesos y analítica', 'lumina'); ?></h2>
|
||||
</header>
|
||||
|
||||
<div class="lm-cert-list">
|
||||
<?php foreach ($certifications as $cert) : ?>
|
||||
<article class="lm-cert-item">
|
||||
<span class="lm-cert-item__year"><?php echo esc_html($cert['year']); ?></span>
|
||||
<div>
|
||||
<h3><?php echo esc_html($cert['title']); ?></h3>
|
||||
<p><?php echo esc_html($cert['issuer']); ?></p>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Contenido editable de WordPress -->
|
||||
<?php while (have_posts()) : the_post(); ?>
|
||||
<?php if (trim((string) get_the_content()) !== '') : ?>
|
||||
<section class="lm-section-inner">
|
||||
<header class="lm-section-head">
|
||||
<p class="lm-eyebrow"><?php esc_html_e('Contenido adicional', 'lumina'); ?></p>
|
||||
<h2><?php esc_html_e('Bloques editables desde WordPress', 'lumina'); ?></h2>
|
||||
</header>
|
||||
<div class="lm-entry__body">
|
||||
<?php the_content(); ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
<?php endwhile; ?>
|
||||
|
||||
</div><!-- /.lm-content -->
|
||||
|
||||
</div><!-- /.lm-body -->
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once get_template_directory() . '/inc/customizer.php';
|
||||
require_once get_template_directory() . '/inc/cv-data.php';
|
||||
require_once get_template_directory() . '/inc/visits.php';
|
||||
|
||||
function lumina_setup(): void
|
||||
{
|
||||
add_theme_support('title-tag');
|
||||
add_theme_support('post-thumbnails');
|
||||
add_theme_support('editor-styles');
|
||||
add_theme_support('responsive-embeds');
|
||||
add_theme_support('wp-block-styles');
|
||||
add_theme_support('align-wide');
|
||||
|
||||
register_nav_menus([
|
||||
'primary' => __('Menú principal', 'lumina'),
|
||||
]);
|
||||
}
|
||||
add_action('after_setup_theme', 'lumina_setup');
|
||||
|
||||
function lumina_enqueue_assets(): void
|
||||
{
|
||||
wp_enqueue_style(
|
||||
'lumina-fonts',
|
||||
'https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap',
|
||||
[],
|
||||
null
|
||||
);
|
||||
|
||||
wp_enqueue_style(
|
||||
'lumina-theme',
|
||||
get_template_directory_uri() . '/assets/css/theme.css',
|
||||
['lumina-fonts'],
|
||||
wp_get_theme()->get('Version')
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'lumina-theme',
|
||||
get_template_directory_uri() . '/assets/js/theme.js',
|
||||
[],
|
||||
wp_get_theme()->get('Version'),
|
||||
true
|
||||
);
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'lumina_enqueue_assets');
|
||||
|
||||
function lumina_body_classes(array $classes): array
|
||||
{
|
||||
$classes[] = 'lumina-shell';
|
||||
|
||||
if (is_front_page()) {
|
||||
$classes[] = 'lumina-front';
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
add_filter('body_class', 'lumina_body_classes');
|
||||
|
||||
function lumina_redirect_sample_page(): void
|
||||
{
|
||||
if (! is_page()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$page = get_queried_object();
|
||||
if (! $page instanceof WP_Post) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($page->post_name !== 'pagina-ejemplo') {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_safe_redirect(home_url('/'), 301);
|
||||
exit;
|
||||
}
|
||||
add_action('template_redirect', 'lumina_redirect_sample_page', 1);
|
||||
|
||||
function lumina_render_primary_menu(): string
|
||||
{
|
||||
if (has_nav_menu('primary')) {
|
||||
return trim((string) wp_nav_menu([
|
||||
'theme_location' => 'primary',
|
||||
'container' => false,
|
||||
'fallback_cb' => false,
|
||||
'menu_class' => 'lm-nav__list',
|
||||
'echo' => false,
|
||||
]));
|
||||
}
|
||||
|
||||
$items = [
|
||||
'#resumen' => __('Perfil', 'lumina'),
|
||||
'#impacto' => __('Impacto', 'lumina'),
|
||||
'#experiencia' => __('Experiencia', 'lumina'),
|
||||
'#formacion' => __('Formación', 'lumina'),
|
||||
'#certificaciones' => __('Certificaciones', 'lumina'),
|
||||
'#contacto' => __('Contacto', 'lumina'),
|
||||
];
|
||||
|
||||
$html = '<ul class="lm-nav__list">';
|
||||
foreach ($items as $href => $label) {
|
||||
$html .= sprintf(
|
||||
'<li><a href="%s">%s</a></li>',
|
||||
esc_url($href),
|
||||
esc_html($label)
|
||||
);
|
||||
}
|
||||
$html .= '</ul>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
function lumina_contact_link(string $type, string $value): string
|
||||
{
|
||||
if ($value === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$href = match ($type) {
|
||||
'email' => 'mailto:' . antispambot($value),
|
||||
'phone' => 'tel:' . preg_replace('/[^0-9+]/', '', $value),
|
||||
default => esc_url($value),
|
||||
};
|
||||
|
||||
return sprintf(
|
||||
'<a class="lm-chip" href="%s">%s</a>',
|
||||
esc_url($href),
|
||||
esc_html($value)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$brand = get_theme_mod('lm_hero_name', get_bloginfo('name'));
|
||||
?>
|
||||
<!doctype html>
|
||||
<html <?php language_attributes(); ?>>
|
||||
<head>
|
||||
<meta charset="<?php bloginfo('charset'); ?>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?php wp_head(); ?>
|
||||
</head>
|
||||
<body <?php body_class(); ?>>
|
||||
<?php wp_body_open(); ?>
|
||||
|
||||
<header class="lm-header" id="top">
|
||||
<div class="lm-header__inner">
|
||||
<a class="lm-brand" href="<?php echo esc_url(home_url('/')); ?>">
|
||||
<span class="lm-brand__dot"></span>
|
||||
<?php echo esc_html($brand); ?>
|
||||
</a>
|
||||
|
||||
<button class="lm-nav-toggle" type="button" aria-expanded="false" aria-controls="lm-nav" aria-label="<?php esc_attr_e('Abrir menú', 'lumina'); ?>">
|
||||
<span></span><span></span><span></span>
|
||||
</button>
|
||||
|
||||
<nav id="lm-nav" class="lm-nav" aria-label="<?php esc_attr_e('Menú principal', 'lumina'); ?>">
|
||||
<?php echo lumina_render_primary_menu(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</nav>
|
||||
|
||||
<div class="lm-header__actions">
|
||||
<a class="lm-btn lm-btn--outline-sm" href="<?php echo esc_url(home_url('/?cv_pdf=1')); ?>" target="_blank">
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>
|
||||
<?php esc_html_e('Descargar CV PDF', 'lumina'); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="lm-main">
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
function lumina_customize_register(WP_Customize_Manager $wp_customize): void
|
||||
{
|
||||
$wp_customize->add_section('lumina_hero', [
|
||||
'title' => __('Lumina CV: Presentación', 'lumina'),
|
||||
'priority' => 30,
|
||||
]);
|
||||
|
||||
$fields = [
|
||||
'lm_hero_name' => ['label' => __('Nombre principal', 'lumina'), 'default' => 'Patricia Soledad Flores Sánchez'],
|
||||
'lm_hero_role' => ['label' => __('Rol o titular', 'lumina'), 'default' => 'Gerente / Jefa de Operaciones Financieras | Sector financiero y microfinanzas'],
|
||||
'lm_hero_intro' => ['label' => __('Introducción', 'lumina'), 'default' => 'Ejecutiva financiera con más de 22 años de trayectoria en banca y microfinanzas. Máster en Dirección y Planificación Financiera, reconocido por la SENECYT en Ecuador, con especialización en gestión operativa, transformación digital de procesos, control interno y liderazgo de equipos multidisciplinarios.'],
|
||||
'lm_hero_cta_label' => ['label' => __('Texto del botón', 'lumina'), 'default' => 'Ver trayectoria'],
|
||||
'lm_hero_cta_url' => ['label' => __('Enlace del botón', 'lumina'), 'default' => '#experiencia'],
|
||||
'lm_contact_location'=> ['label' => __('Ubicación', 'lumina'), 'default' => 'Loja, Ecuador'],
|
||||
'lm_contact_email' => ['label' => __('Correo', 'lumina'), 'default' => 'patricflorsanchez@gmail.com'],
|
||||
'lm_contact_phone' => ['label' => __('Teléfono', 'lumina'), 'default' => '+593 99 469 8405'],
|
||||
'lm_social_linkedin' => ['label' => __('LinkedIn', 'lumina'), 'default' => 'https://www.linkedin.com/in/patricia-soledad-flores-s%C3%A1nchez-43b84418/'],
|
||||
'lm_social_github' => ['label' => __('GitHub', 'lumina'), 'default' => ''],
|
||||
];
|
||||
|
||||
$wp_customize->add_setting('lm_profile_image', [
|
||||
'default' => '',
|
||||
'sanitize_callback' => 'esc_url_raw',
|
||||
]);
|
||||
|
||||
$wp_customize->add_control(new WP_Customize_Image_Control($wp_customize, 'lm_profile_image', [
|
||||
'label' => __('Foto de perfil', 'lumina'),
|
||||
'section' => 'lumina_hero',
|
||||
'settings' => 'lm_profile_image',
|
||||
]));
|
||||
|
||||
foreach ($fields as $key => $field) {
|
||||
$isUrl = str_contains($key, 'url')
|
||||
|| str_contains($key, 'linkedin')
|
||||
|| str_contains($key, 'github');
|
||||
|
||||
$wp_customize->add_setting($key, [
|
||||
'default' => $field['default'],
|
||||
'sanitize_callback' => $isUrl ? 'esc_url_raw' : 'sanitize_text_field',
|
||||
]);
|
||||
|
||||
$wp_customize->add_control($key, [
|
||||
'label' => $field['label'],
|
||||
'section' => 'lumina_hero',
|
||||
'type' => $key === 'lm_hero_intro' ? 'textarea' : 'text',
|
||||
]);
|
||||
}
|
||||
}
|
||||
add_action('customize_register', 'lumina_customize_register');
|
||||
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
function lumina_cv_data(): array
|
||||
{
|
||||
return [
|
||||
'hero' => [
|
||||
'eyebrow' => 'Currículum ejecutivo',
|
||||
'name' => 'Patricia Soledad Flores Sánchez',
|
||||
'role' => 'Gerente / Jefa de Operaciones Financieras | Sector financiero y microfinanzas',
|
||||
'intro' => 'Ejecutiva financiera con más de 22 años de trayectoria en banca y microfinanzas. Máster en Dirección y Planificación Financiera, reconocido por la SENECYT en Ecuador, con especialización en gestión operativa, transformación digital de procesos, control interno y liderazgo de equipos multidisciplinarios.',
|
||||
'location' => 'Loja, Ecuador',
|
||||
'email' => 'patricflorsanchez@gmail.com',
|
||||
'phone' => '+593 99 469 8405',
|
||||
'linkedin' => 'https://www.linkedin.com/in/patricia-soledad-flores-s%C3%A1nchez-43b84418/',
|
||||
'availability' => 'Inmediata | Presencial / Híbrida / Remota',
|
||||
'focus' => 'Operaciones financieras, control interno y transformación digital',
|
||||
],
|
||||
'metrics' => [
|
||||
['value' => '22+', 'label' => 'años de experiencia en banca y microfinanzas'],
|
||||
['value' => '26', 'label' => 'agencias bajo liderazgo operativo nacional'],
|
||||
['value' => '48', 'label' => 'personas a cargo en la estructura operativa'],
|
||||
['value' => 'USD 5 M', 'label' => 'en operaciones mensuales de microcrédito'],
|
||||
['value' => '28.000', 'label' => 'clientes coordinados en recaudación por canales internos y externos'],
|
||||
],
|
||||
'highlights' => [
|
||||
['value' => '9/10', 'label' => 'calificación de gestión con resultado excelente en cuatro trimestres consecutivos'],
|
||||
['value' => '74 %', 'label' => 'reducción de requerimientos de soporte desde Dirección por descentralización de procesos'],
|
||||
['value' => '1,68 días', 'label' => 'tiempo de desembolso logrado en Q3 2025, mejor resultado del año'],
|
||||
['value' => '75 %', 'label' => 'reducción del índice de rotación del área entre 2022 y 2026'],
|
||||
],
|
||||
'summary' => [
|
||||
'title' => 'Perfil estratégico con enfoque en eficiencia, control y ejecución sostenible',
|
||||
'body' => 'Actualmente lidera la operatividad de 26 agencias a nivel nacional y coordina aproximadamente 1.500 operaciones de microcrédito mensuales, por un monto cercano a USD 5 millones. También articula la recaudación de cerca de 28.000 clientes por canales internos y externos, integrando visión operativa, criterio financiero, disciplina de control y liderazgo sostenido del desempeño.',
|
||||
],
|
||||
'impact' => [
|
||||
[
|
||||
'title' => 'Transformación digital',
|
||||
'body' => 'Lideró desembolsos por transferencia bancaria, integración de APIs bancarias y digitalización de expedientes y pagarés en 13 agencias.',
|
||||
],
|
||||
[
|
||||
'title' => 'Automatización crítica',
|
||||
'body' => 'Automatizó el seguro de desgravamen, desde el cálculo de prima hasta la liquidación contable, reduciendo tiempos de 17 a 10 días.',
|
||||
],
|
||||
[
|
||||
'title' => 'Supervisión nacional',
|
||||
'body' => 'Implementó una matriz de supervisión y certificación por agencia, elevando el índice de cumplimiento operativo del 65 % al 88 %.',
|
||||
],
|
||||
],
|
||||
'experience' => [
|
||||
[
|
||||
'period' => 'Abr. 2022 – Presente',
|
||||
'title' => 'Jefa de Operaciones',
|
||||
'company' => 'Fundación FACES Microfinanzas',
|
||||
'location' => 'Loja, Ecuador',
|
||||
'lead' => 'Responsable del desempeño operativo nacional, cumplimiento del POA, control interno, digitalización de procesos y gestión de equipos.',
|
||||
'bullets' => [
|
||||
'Cumplimiento del POA: 98 % (Q2 2025), 96 % (Q3 2025), 100 % (Q4 2025) y 105 % (Q1 2026).',
|
||||
'La transformación digital logró que los desembolsos por transferencia representen el 47,80 % del monto total en Q1 2026.',
|
||||
'Redujo los requerimientos de soporte desde Dirección en un 74 %, de 1.489 a 382, mediante la descentralización de procesos hacia las agencias.',
|
||||
'Automatizó el proceso del seguro de desgravamen con cálculo de prima, conciliación mensual, liquidación de siniestros y asientos contables automatizados.',
|
||||
'Elevó el índice de cumplimiento operativo nacional del 65 % al 88 % con la matriz de supervisión y certificación por agencia.',
|
||||
'Redujo el tiempo de atención del seguro de desgravamen de 17 a 10 días.',
|
||||
'Redujo los tiempos de desembolso a 1,68 días en Q3 2025, mejor resultado del año frente a la meta institucional máxima de 2 días.',
|
||||
'La efectividad de recuperación de mora alcanzó 90,60 % en Q1 2026, con USD 3,06 millones recuperados sobre USD 3,37 millones en mora.',
|
||||
'Redujo el índice de rotación del área del 41,46 % al 10,24 % entre diciembre de 2022 y marzo de 2026 mediante mejoras salariales, remuneración variable, evaluación trimestral y un plan de carrera con certificación de 60 horas para asistentes de caja.',
|
||||
'Participa en comités estratégicos, auditorías internas y externas, y en representación institucional ante organismos financieros internacionales de desarrollo.',
|
||||
],
|
||||
],
|
||||
[
|
||||
'period' => 'Feb. 2021 – Mar. 2022',
|
||||
'title' => 'Supervisora de Operaciones',
|
||||
'company' => 'Fundación FACES Microfinanzas',
|
||||
'location' => 'Loja, Ecuador',
|
||||
'lead' => 'Supervisó operaciones de 18 agencias a nivel nacional y regularizó procesos críticos inexistentes o incompletos.',
|
||||
'bullets' => [
|
||||
'Reconstruyó desde cero las bases de cálculo del seguro de desgravamen y regularizó pagos pendientes desde enero de 2021.',
|
||||
'Elaboró el instructivo de constitución de garantías hipotecarias, proceso que no existía previamente en la institución.',
|
||||
'Inició el proyecto de automatización de pagos por depósitos y transferencias.',
|
||||
],
|
||||
],
|
||||
[
|
||||
'period' => '2019 – 2021',
|
||||
'title' => 'Actualización y formación profesional',
|
||||
'company' => 'Formación independiente',
|
||||
'location' => 'Ecuador',
|
||||
'lead' => 'Etapa enfocada en fortalecimiento técnico y actualización profesional tras su salida de Mutualista Pichincha.',
|
||||
'bullets' => [
|
||||
'SAP FI (30 h).',
|
||||
'Excel Empresarial (24 h).',
|
||||
'Prevención de Lavado de Activos — UAFE (5 h).',
|
||||
],
|
||||
],
|
||||
[
|
||||
'period' => 'Ago. 2004 – May. 2019',
|
||||
'title' => 'Oficial Operativa Regional / Jefa Operativa',
|
||||
'company' => 'Mutualista Pichincha',
|
||||
'location' => 'Loja, Ecuador',
|
||||
'lead' => 'Trayectoria ascendente de 15 años desde Cajera hasta Jefa Operativa Regional.',
|
||||
'bullets' => [
|
||||
'Reconocida a nivel nacional por excelencia en control operativo.',
|
||||
'La agencia se mantuvo consistentemente por encima del 80 % en gestión de excepciones de crédito hipotecario.',
|
||||
'Administró proyecto inmobiliario institucional en Loja.',
|
||||
'Gestionó alertas ALA/FT con 100 % de cumplimiento en comités trimestrales y auditorías internas sin observaciones significativas de forma sostenida.',
|
||||
],
|
||||
],
|
||||
[
|
||||
'period' => 'Ene. 2002 – Nov. 2003',
|
||||
'title' => 'Cajera',
|
||||
'company' => 'Cooperativa de Ahorro y Crédito El Porvenir',
|
||||
'location' => 'Loja, Ecuador',
|
||||
'lead' => 'Inicio de carrera en el frente operativo financiero con disciplina de caja y apoyo contable.',
|
||||
'bullets' => [
|
||||
'Gestión de caja sin faltantes ni sobrantes.',
|
||||
'Contrato renovado de forma anticipada a los tres meses.',
|
||||
'Apoyo al área de Contabilidad y reemplazo temporal de la contadora durante vacaciones.',
|
||||
],
|
||||
],
|
||||
],
|
||||
'education' => [
|
||||
[
|
||||
'year' => '2021',
|
||||
'title' => 'Máster Universitario en Dirección y Planificación Financiera',
|
||||
'institution' => 'Universidad Europea Miguel de Cervantes — Valladolid, España',
|
||||
'detail' => 'Título reconocido por la SENECYT — Ecuador, febrero de 2023 | Reg. 2021/394270.',
|
||||
],
|
||||
[
|
||||
'year' => '2007',
|
||||
'title' => 'Ingeniera en Administración en Banca y Finanzas',
|
||||
'institution' => 'Universidad Técnica Particular de Loja (UTPL)',
|
||||
'detail' => '',
|
||||
],
|
||||
],
|
||||
'certifications' => [
|
||||
['year' => '2026', 'title' => 'Mujeres que Lideran: Alta Gerencia', 'issuer' => 'Foro UNIR — Universidad Internacional de La Rioja'],
|
||||
['year' => '2025', 'title' => 'Programa Internacional de Habilidades Gerenciales (48 h)', 'issuer' => 'IDEASGROUP — Ecuador / México'],
|
||||
['year' => '2025', 'title' => 'Transforma tu Trabajo con Inteligencia Artificial (12 h)', 'issuer' => 'Red de Instituciones Financieras de Desarrollo'],
|
||||
['year' => '2025', 'title' => 'Excel: Básico a Dashboard (40 h)', 'issuer' => 'DMARURI Training & Consulting'],
|
||||
['year' => '2024', 'title' => 'Administración por Procesos — BPM (64 h)', 'issuer' => 'Escuela Politécnica Nacional — CEC'],
|
||||
['year' => '2023', 'title' => 'Formación de Formadores (80 h)', 'issuer' => 'Ministerio del Trabajo del Ecuador | Certificación vigente hasta 2028'],
|
||||
['year' => '2023', 'title' => 'Power BI (40 h) | Indicadores Clave de Desempeño — KPI (12 h)', 'issuer' => 'Liderazgo Capacitación & Eventos'],
|
||||
['year' => '2020', 'title' => 'Gestión Financiera ERP SAP FI — Key User (30 h)', 'issuer' => 'Socio SAP certificado'],
|
||||
['year' => '2020', 'title' => 'Prevención de Lavado de Activos y Financiamiento de Delitos', 'issuer' => 'UAFE — Ecuador'],
|
||||
['year' => '2013', 'title' => 'Tributación Integral (36 h)', 'issuer' => 'Universidad Técnica Particular de Loja'],
|
||||
],
|
||||
'competencies' => [
|
||||
'Finanzas y Operaciones' => [
|
||||
'Gestión de operaciones financieras',
|
||||
'Conciliación bancaria',
|
||||
'Originación de crédito',
|
||||
'Gestión de cartera',
|
||||
'Control interno',
|
||||
'Tesorería operativa',
|
||||
'Microfinanzas',
|
||||
'ALA/FT',
|
||||
],
|
||||
'Tecnología y Procesos' => [
|
||||
'Transformación digital',
|
||||
'BPM',
|
||||
'Integración de APIs / Web Services',
|
||||
'SAP FI',
|
||||
'Excel avanzado y dashboards',
|
||||
'Power BI',
|
||||
'IA aplicada',
|
||||
'Core financiero',
|
||||
],
|
||||
'Liderazgo' => [
|
||||
'Equipos de hasta 48 personas',
|
||||
'Remuneración variable',
|
||||
'Gestión del cambio',
|
||||
'Formación de formadores',
|
||||
'Diversidad, equidad e inclusión',
|
||||
],
|
||||
],
|
||||
'volunteer' => [
|
||||
'title' => 'Voluntaria — Hogar San Camilo de Lellis',
|
||||
'year' => '2025',
|
||||
'body' => 'Hogar de niñas con discapacidad | Loja, Ecuador. Alineado a la visión y misión de responsabilidad social de la Fundación FACES Microfinanzas.',
|
||||
],
|
||||
'additional' => [
|
||||
'Idiomas' => 'Español nativo | Inglés básico en formación activa',
|
||||
'Disponibilidad' => 'Inmediata | Presencial / Híbrida / Remota',
|
||||
'C.I.' => '1103591648',
|
||||
'Fecha de nacimiento' => '3 de agosto de 1980',
|
||||
'Web profesional' => 'pflres.linkedcorp.net',
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
function lumina_should_track_visit(): bool
|
||||
{
|
||||
if (is_admin() || wp_doing_ajax() || wp_doing_cron()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! isset($_SERVER['REQUEST_METHOD']) || $_SERVER['REQUEST_METHOD'] !== 'GET') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_user_logged_in() && current_user_can('manage_options')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_front_page() || is_home() || is_singular();
|
||||
}
|
||||
|
||||
function lumina_track_visit(): void
|
||||
{
|
||||
if (! lumina_should_track_visit()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$requestUri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
|
||||
$visitorHash = md5($requestUri . '|' . lumina_get_client_ip() . '|' . gmdate('Y-m-d-H'));
|
||||
$transientKey = 'lumina_visit_' . $visitorHash;
|
||||
|
||||
if (get_transient($transientKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_transient($transientKey, '1', HOUR_IN_SECONDS);
|
||||
|
||||
$total = (int) get_option('lumina_total_visits', 0);
|
||||
update_option('lumina_total_visits', $total + 1, false);
|
||||
|
||||
if (is_front_page()) {
|
||||
$frontPage = (int) get_option('page_on_front');
|
||||
if ($frontPage > 0) {
|
||||
$views = (int) get_post_meta($frontPage, '_lumina_views', true);
|
||||
update_post_meta($frontPage, '_lumina_views', $views + 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$postId = get_queried_object_id();
|
||||
if ($postId > 0) {
|
||||
$views = (int) get_post_meta($postId, '_lumina_views', true);
|
||||
update_post_meta($postId, '_lumina_views', $views + 1);
|
||||
}
|
||||
}
|
||||
add_action('template_redirect', 'lumina_track_visit');
|
||||
|
||||
function lumina_get_client_ip(): string
|
||||
{
|
||||
$keys = [
|
||||
'HTTP_X_FORWARDED_FOR',
|
||||
'HTTP_CLIENT_IP',
|
||||
'REMOTE_ADDR',
|
||||
];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if (! empty($_SERVER[$key])) {
|
||||
$value = explode(',', (string) $_SERVER[$key]);
|
||||
return trim($value[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return '0.0.0.0';
|
||||
}
|
||||
|
||||
function lumina_register_visits_widget(): void
|
||||
{
|
||||
wp_add_dashboard_widget(
|
||||
'lumina_visits_widget',
|
||||
__('Lumina CV: Visitas', 'lumina'),
|
||||
'lumina_render_visits_widget'
|
||||
);
|
||||
}
|
||||
add_action('wp_dashboard_setup', 'lumina_register_visits_widget');
|
||||
|
||||
function lumina_render_visits_widget(): void
|
||||
{
|
||||
$total = (int) get_option('lumina_total_visits', 0);
|
||||
$frontPage = (int) get_option('page_on_front');
|
||||
$frontViews = $frontPage > 0 ? (int) get_post_meta($frontPage, '_lumina_views', true) : 0;
|
||||
?>
|
||||
<p><strong><?php esc_html_e('Visitas totales registradas:', 'lumina'); ?></strong> <?php echo esc_html((string) $total); ?></p>
|
||||
<p><strong><?php esc_html_e('Visitas a la portada:', 'lumina'); ?></strong> <?php echo esc_html((string) $frontViews); ?></p>
|
||||
<p><?php esc_html_e('El contador evita duplicados del mismo visitante en la misma URL durante una hora.', 'lumina'); ?></p>
|
||||
<?php
|
||||
}
|
||||
|
||||
function lumina_add_views_column(array $columns): array
|
||||
{
|
||||
$columns['lumina_views'] = __('Visitas', 'lumina');
|
||||
return $columns;
|
||||
}
|
||||
add_filter('manage_pages_columns', 'lumina_add_views_column');
|
||||
add_filter('manage_posts_columns', 'lumina_add_views_column');
|
||||
|
||||
function lumina_render_views_column(string $column, int $postId): void
|
||||
{
|
||||
if ($column !== 'lumina_views') {
|
||||
return;
|
||||
}
|
||||
|
||||
echo esc_html((string) ((int) get_post_meta($postId, '_lumina_views', true)));
|
||||
}
|
||||
add_action('manage_pages_custom_column', 'lumina_render_views_column', 10, 2);
|
||||
add_action('manage_posts_custom_column', 'lumina_render_views_column', 10, 2);
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<section class="lm-wrap">
|
||||
<div class="lm-card">
|
||||
<?php if (have_posts()) : ?>
|
||||
<?php while (have_posts()) : the_post(); ?>
|
||||
<article <?php post_class('lm-entry'); ?>>
|
||||
<h1 class="lm-entry__title"><?php the_title(); ?></h1>
|
||||
<div class="lm-entry__body">
|
||||
<?php the_content(); ?>
|
||||
</div>
|
||||
</article>
|
||||
<?php endwhile; ?>
|
||||
<?php else : ?>
|
||||
<article class="lm-entry lm-entry--empty">
|
||||
<h1><?php esc_html_e('Empieza a construir tu perfil', 'lumina'); ?></h1>
|
||||
<p><?php esc_html_e('Crea una página de inicio y usa Lumina CV como tema activo.', 'lumina'); ?></p>
|
||||
</article>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
Theme Name: Lumina CV
|
||||
Theme URI: https://pflres.linkedcorp.net
|
||||
Author: mgonzalez
|
||||
Description: Tema WordPress moderno, alegre y profesional para hoja de vida ejecutiva. Diseño claro con paleta teal y ámbar, tipografía limpia y layout de sidebar izquierdo.
|
||||
Version: 1.0.0
|
||||
Requires at least: 6.8
|
||||
Tested up to: 6.8
|
||||
Requires PHP: 8.1
|
||||
Text Domain: lumina
|
||||
*/
|
||||
Reference in New Issue
Block a user