blog+contacto php listo
This commit is contained in:
+85
-160
@@ -1,185 +1,110 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log('Blog JS cargado');
|
||||
|
||||
const searchInput = document.getElementById('blog-search');
|
||||
const searchClear = document.getElementById('search-clear');
|
||||
const blogGrid = document.getElementById('blog-grid');
|
||||
const emptyState = document.getElementById('empty-state');
|
||||
const categoryBtns = document.querySelectorAll('.category-btn');
|
||||
const filterBtns = document.querySelectorAll('.filter-btn');
|
||||
const resetBtn = document.getElementById('reset-filters');
|
||||
const resultsCount = document.getElementById('results-count');
|
||||
const filtersHeader = document.getElementById('blog-filters-header');
|
||||
const emptyState = document.getElementById('empty-state');
|
||||
|
||||
if (!searchInput || !blogGrid) {
|
||||
console.error('Faltan elementos del DOM');
|
||||
return;
|
||||
}
|
||||
const allCards = document.querySelectorAll('.blog-card, .featured-card');
|
||||
let activeCategory = 'all';
|
||||
let activeFilter = 'all';
|
||||
let searchQuery = '';
|
||||
|
||||
let currentFilters = {
|
||||
search: '',
|
||||
category: 'all',
|
||||
featured: 'all',
|
||||
sort: 'recent'
|
||||
};
|
||||
|
||||
// ===== EFECTO SCROLL EN FILTROS =====
|
||||
window.addEventListener('scroll', () => {
|
||||
if (window.scrollY > 100) {
|
||||
filtersHeader.classList.add('is-scrolled');
|
||||
} else {
|
||||
filtersHeader.classList.remove('is-scrolled');
|
||||
}
|
||||
});
|
||||
|
||||
// ===== BUSCADOR =====
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
const value = e.target.value.trim();
|
||||
currentFilters.search = value;
|
||||
|
||||
if (searchClear) {
|
||||
searchClear.classList.toggle('visible', value.length > 0);
|
||||
}
|
||||
|
||||
filterArticles();
|
||||
});
|
||||
|
||||
if (searchClear) {
|
||||
searchClear.addEventListener('click', () => {
|
||||
searchInput.value = '';
|
||||
searchClear.classList.remove('visible');
|
||||
currentFilters.search = '';
|
||||
filterArticles();
|
||||
searchInput.focus();
|
||||
});
|
||||
}
|
||||
|
||||
// ===== FILTROS PRINCIPALES =====
|
||||
document.querySelectorAll('.filter-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
currentFilters.featured = btn.dataset.filter;
|
||||
filterArticles();
|
||||
});
|
||||
});
|
||||
|
||||
// ===== CATEGORÍAS =====
|
||||
document.querySelectorAll('.category-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.category-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
currentFilters.category = btn.dataset.category;
|
||||
filterArticles();
|
||||
});
|
||||
});
|
||||
|
||||
// ===== ORDENAMIENTO =====
|
||||
const sortSelect = document.getElementById('sort-select');
|
||||
if (sortSelect) {
|
||||
sortSelect.addEventListener('change', (e) => {
|
||||
currentFilters.sort = e.target.value;
|
||||
sortArticles();
|
||||
});
|
||||
}
|
||||
|
||||
// ===== RESET =====
|
||||
const resetFilters = document.getElementById('reset-filters');
|
||||
if (resetFilters) {
|
||||
resetFilters.addEventListener('click', () => {
|
||||
currentFilters = { search: '', category: 'all', featured: 'all', sort: 'recent' };
|
||||
searchInput.value = '';
|
||||
searchClear?.classList.remove('visible');
|
||||
|
||||
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
||||
document.querySelector('.filter-btn[data-filter="all"]')?.classList.add('active');
|
||||
|
||||
document.querySelectorAll('.category-btn').forEach(b => b.classList.remove('active'));
|
||||
document.querySelector('.category-btn[data-category="all"]')?.classList.add('active');
|
||||
|
||||
if (sortSelect) sortSelect.value = 'recent';
|
||||
|
||||
filterArticles();
|
||||
});
|
||||
}
|
||||
|
||||
// ===== FUNCIÓN DE FILTRADO =====
|
||||
const filterArticles = () => {
|
||||
const articles = document.querySelectorAll('.blog-card, .featured-card');
|
||||
function filterArticles() {
|
||||
let visibleCount = 0;
|
||||
|
||||
articles.forEach(article => {
|
||||
const categories = article.dataset.categories || '';
|
||||
const tags = article.dataset.tags || '';
|
||||
const isFeatured = article.dataset.featured === 'true';
|
||||
allCards.forEach(card => {
|
||||
const categories = card.dataset.categories || '';
|
||||
const isFeatured = card.dataset.featured === 'true';
|
||||
const title = card.querySelector('.featured-title, .card-title')?.textContent.toLowerCase() || '';
|
||||
const excerpt = card.querySelector('.featured-excerpt, .card-excerpt')?.textContent.toLowerCase() || '';
|
||||
|
||||
// 1. Filtro de categoría
|
||||
const matchCategory = activeCategory === 'all' || categories.includes(activeCategory);
|
||||
|
||||
const title = article.querySelector('.card-title, .featured-title')?.textContent.toLowerCase() || '';
|
||||
const excerpt = article.querySelector('.card-excerpt, .featured-excerpt')?.textContent.toLowerCase() || '';
|
||||
// 2. Filtro de tipo (Todos / Destacados)
|
||||
const matchFilter = activeFilter === 'all' || (activeFilter === 'destacados' && isFeatured);
|
||||
|
||||
const searchTerm = currentFilters.search.toLowerCase();
|
||||
const matchSearch = searchTerm === '' ||
|
||||
title.includes(searchTerm) ||
|
||||
excerpt.includes(searchTerm) ||
|
||||
categories.toLowerCase().includes(searchTerm) ||
|
||||
tags.toLowerCase().includes(searchTerm);
|
||||
|
||||
const matchCategory = currentFilters.category === 'all' ||
|
||||
categories.toLowerCase().includes(currentFilters.category.toLowerCase());
|
||||
|
||||
let matchFeatured = true;
|
||||
if (currentFilters.featured === 'destacados') {
|
||||
matchFeatured = isFeatured;
|
||||
}
|
||||
|
||||
if (matchSearch && matchCategory && matchFeatured) {
|
||||
article.style.display = '';
|
||||
// 3. Filtro de búsqueda
|
||||
const matchSearch = searchQuery === '' || title.includes(searchQuery) || excerpt.includes(searchQuery);
|
||||
|
||||
if (matchCategory && matchFilter && matchSearch) {
|
||||
card.style.display = 'flex';
|
||||
visibleCount++;
|
||||
} else {
|
||||
article.style.display = 'none';
|
||||
card.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
sortArticles();
|
||||
updateResultsCount(visibleCount);
|
||||
// Actualizar contador y estado vacío
|
||||
if (resultsCount) {
|
||||
resultsCount.innerHTML = `Mostrando <strong>${visibleCount}</strong> artículo${visibleCount !== 1 ? 's' : ''}`;
|
||||
}
|
||||
|
||||
if (emptyState) {
|
||||
emptyState.style.display = visibleCount === 0 ? 'block' : 'none';
|
||||
}
|
||||
};
|
||||
|
||||
const sortArticles = () => {
|
||||
const articles = Array.from(document.querySelectorAll('.blog-card'));
|
||||
const container = blogGrid;
|
||||
|
||||
switch(currentFilters.sort) {
|
||||
case 'recent':
|
||||
articles.sort((a, b) => {
|
||||
const dateA = new Date(a.querySelector('time')?.datetime || 0);
|
||||
const dateB = new Date(b.querySelector('time')?.datetime || 0);
|
||||
return dateB - dateA;
|
||||
});
|
||||
break;
|
||||
case 'alphabetical':
|
||||
articles.sort((a, b) => {
|
||||
const titleA = a.querySelector('.card-title')?.textContent || '';
|
||||
const titleB = b.querySelector('.card-title')?.textContent || '';
|
||||
return titleA.localeCompare(titleB);
|
||||
});
|
||||
break;
|
||||
// Mostrar/ocultar botón de limpiar búsqueda
|
||||
if (searchClear) {
|
||||
searchClear.classList.toggle('visible', searchQuery.length > 0);
|
||||
}
|
||||
|
||||
articles.forEach(article => container.appendChild(article));
|
||||
};
|
||||
}
|
||||
|
||||
const updateResultsCount = (count) => {
|
||||
if (!resultsCount) return;
|
||||
|
||||
if (count === 0) {
|
||||
resultsCount.innerHTML = 'No se encontraron artículos';
|
||||
} else if (currentFilters.category === 'all' && currentFilters.search === '') {
|
||||
resultsCount.innerHTML = `Mostrando <strong>${count}</strong> artículos`;
|
||||
} else {
|
||||
resultsCount.innerHTML = `Mostrando <strong>${count}</strong> artículo${count !== 1 ? 's' : ''}`;
|
||||
}
|
||||
};
|
||||
// Event Listeners
|
||||
if (searchInput) {
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
searchQuery = e.target.value.toLowerCase().trim();
|
||||
filterArticles();
|
||||
});
|
||||
}
|
||||
|
||||
// Inicializar
|
||||
if (searchClear) {
|
||||
searchClear.addEventListener('click', () => {
|
||||
searchInput.value = '';
|
||||
searchQuery = '';
|
||||
searchInput.focus();
|
||||
filterArticles();
|
||||
});
|
||||
}
|
||||
|
||||
categoryBtns.forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
categoryBtns.forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
activeCategory = btn.dataset.category;
|
||||
filterArticles();
|
||||
});
|
||||
});
|
||||
|
||||
filterBtns.forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
filterBtns.forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
activeFilter = btn.dataset.filter;
|
||||
filterArticles();
|
||||
});
|
||||
});
|
||||
|
||||
if (resetBtn) {
|
||||
resetBtn.addEventListener('click', () => {
|
||||
activeCategory = 'all';
|
||||
activeFilter = 'all';
|
||||
searchQuery = '';
|
||||
if (searchInput) searchInput.value = '';
|
||||
|
||||
categoryBtns.forEach(b => b.classList.remove('active'));
|
||||
document.querySelector('.category-btn[data-category="all"]')?.classList.add('active');
|
||||
|
||||
filterBtns.forEach(b => b.classList.remove('active'));
|
||||
document.querySelector('.filter-btn[data-filter="all"]')?.classList.add('active');
|
||||
|
||||
filterArticles();
|
||||
});
|
||||
}
|
||||
|
||||
// Ejecutar al inicio
|
||||
filterArticles();
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Envío AJAX del formulario de contacto + modal de éxito.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const form = document.getElementById('form-contacto');
|
||||
const modal = document.getElementById('modal-contacto');
|
||||
const btnCerrar = modal ? modal.querySelector('.modal-cerrar') : null;
|
||||
const btnEnviar = form ? form.querySelector('button[type="submit"]') : null;
|
||||
|
||||
if (!form || !modal) return;
|
||||
|
||||
let redirectTimer = null;
|
||||
|
||||
// ── Helpers ────────────────────────────────────────────────────────
|
||||
function abrirModal(mensaje) {
|
||||
const texto = modal.querySelector('.modal-mensaje');
|
||||
if (texto && mensaje) texto.textContent = mensaje;
|
||||
modal.classList.add('is-visible');
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function cerrarModal(redirigir = false) {
|
||||
modal.classList.remove('is-visible');
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
document.body.style.overflow = '';
|
||||
if (redirectTimer) clearTimeout(redirectTimer);
|
||||
if (redirigir) window.location.href = 'inicio.html';
|
||||
}
|
||||
|
||||
function mostrarError(mensaje) {
|
||||
// Reutilizamos el modal con estética distinta
|
||||
modal.classList.add('is-error');
|
||||
abrirModal(mensaje);
|
||||
}
|
||||
|
||||
// ── Cerrar modal ───────────────────────────────────────────────────
|
||||
if (btnCerrar) {
|
||||
btnCerrar.addEventListener('click', () => cerrarModal(true));
|
||||
}
|
||||
modal.addEventListener('click', (e) => {
|
||||
if (e.target === modal) cerrarModal(true);
|
||||
});
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && modal.classList.contains('is-visible')) {
|
||||
cerrarModal(true);
|
||||
}
|
||||
});
|
||||
|
||||
// ── Submit ─────────────────────────────────────────────────────────
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
// Validación nativa HTML5
|
||||
if (!form.checkValidity()) {
|
||||
form.reportValidity();
|
||||
return;
|
||||
}
|
||||
|
||||
// Estado de carga
|
||||
const textoOriginal = btnEnviar ? btnEnviar.innerHTML : '';
|
||||
if (btnEnviar) {
|
||||
btnEnviar.disabled = true;
|
||||
btnEnviar.innerHTML = 'Enviando…';
|
||||
}
|
||||
|
||||
try {
|
||||
const data = new FormData(form);
|
||||
const res = await fetch('enviar.php', {
|
||||
method: 'POST',
|
||||
body: data,
|
||||
headers: { 'X-Requested-With': 'XMLHttpRequest' },
|
||||
});
|
||||
|
||||
const json = await res.json().catch(() => ({
|
||||
status: 'error',
|
||||
message: 'Respuesta inválida del servidor.',
|
||||
}));
|
||||
|
||||
if (json.status === 'success') {
|
||||
modal.classList.remove('is-error');
|
||||
abrirModal(json.message || '¡Gracias! Te contactaremos en breve.');
|
||||
form.reset();
|
||||
|
||||
const delay = Number(json.delay) || 4000;
|
||||
redirectTimer = setTimeout(() => {
|
||||
window.location.href = json.redirect || 'inicio.html';
|
||||
}, delay);
|
||||
} else {
|
||||
mostrarError(json.message || 'No pudimos enviar tu mensaje.');
|
||||
}
|
||||
} catch (err) {
|
||||
mostrarError('Hubo un problema de conexión. Probá nuevamente.');
|
||||
} finally {
|
||||
if (btnEnviar) {
|
||||
btnEnviar.disabled = false;
|
||||
btnEnviar.innerHTML = textoOriginal;
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user