feat: paginación de noticias (app.py + templates)

This commit is contained in:
jlimolina 2025-10-08 18:53:10 +02:00
parent db6fa3d2c3
commit 8109dbf274
3 changed files with 233 additions and 104 deletions

View file

@ -1,25 +1,27 @@
{% extends "base.html" %}
{% block title %}Últimas Noticias RSS{% endblock %}
{% block content %}
<div class="card">
<h2><i class="fas fa-filter" style="color: var(--secondary-color); margin-right: 10px;"></i>Filtrar Noticias</h2>
<form method="get" action="{{ url_for('home') }}" id="filter-form">
<!-- Campos ocultos para paginación -->
<input type="hidden" name="page" id="page" value="{{ page or 1 }}">
<input type="hidden" name="per_page" id="per_page" value="{{ per_page or 20 }}">
<div class="filter-main-row">
<div class="filter-search-box">
<label for="q">Buscar por palabra clave</label>
<input type="search" name="q" id="q" placeholder="Ej: Trump, California, IA..." value="{{ q or '' }}">
</div>
<div class="filter-actions">
<button type="submit" class="btn"><i class="fas fa-search"></i> Filtrar</button>
<a href="{{ url_for('home') }}" class="btn btn-secondary"><i class="fas fa-eraser"></i> Limpiar</a>
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px; align-items: flex-end; border-top: 1px solid var(--border-color); padding-top: 20px;">
<div>
<label for="categoria_id">Categoría</label>
@ -59,6 +61,7 @@
</div>
<div id="noticias-container">
{# El parcial incluye la lista + la paginación #}
{% include '_noticias_list.html' %}
</div>
@ -67,8 +70,8 @@ document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('filter-form');
const continenteSelect = document.getElementById('continente_id');
const paisSelect = document.getElementById('pais_id');
const pageInput = document.getElementById('page');
// Lógica para filtrar países al cambiar el continente
function filtrarPaises() {
const continenteId = continenteSelect.value;
for (let i = 1; i < paisSelect.options.length; i++) {
@ -82,19 +85,20 @@ document.addEventListener('DOMContentLoaded', function() {
}
}
// Lógica para enviar el formulario con AJAX
async function actualizarNoticias(event) {
if (event) event.preventDefault();
async function cargarNoticias(keepPage) {
// Si cambiamos filtros manualmente, reiniciamos a página 1
if (!keepPage) pageInput.value = 1;
const formData = new FormData(form);
const params = new URLSearchParams(formData);
const newUrl = `${form.action}?${params.toString()}`;
const container = document.getElementById('noticias-container');
container.style.opacity = '0.5';
container.innerHTML = '<div style="text-align:center; padding: 40px;"><i class="fas fa-spinner fa-spin fa-2x"></i></div>';
try {
const response = await fetch(newUrl, {
headers: { 'X-Requested-With': 'XMLHttpRequest' }
});
const response = await fetch(newUrl, { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
const html = await response.text();
container.innerHTML = html;
window.history.pushState({path: newUrl}, '', newUrl);
@ -106,10 +110,31 @@ document.addEventListener('DOMContentLoaded', function() {
}
}
// Asignar los eventos
continenteSelect.addEventListener('change', filtrarPaises);
form.addEventListener('submit', actualizarNoticias);
// Envío del formulario (filtrar) -> page = 1
form.addEventListener('submit', function(e) {
e.preventDefault();
cargarNoticias(false);
});
// Clic en enlaces de paginación (delegación)
document.addEventListener('click', function(e) {
const link = e.target.closest('a.page-link');
if (link && link.dataset.page) {
e.preventDefault();
pageInput.value = link.dataset.page;
cargarNoticias(true);
}
});
// Inicializaciones
continenteSelect.addEventListener('change', function() {
filtrarPaises();
// al cambiar continente, forzamos recarga desde página 1
cargarNoticias(false);
});
filtrarPaises(); // Ejecutar al inicio
});
</script>
{% endblock %}