Skip to main content

Team

Laura Martínez

Expert en cine y series, Laura aporta su pasión por la narración.

Juan Pérez

Crítico cinematográfico que comparte su visión única sobre cada película.

Ana Torres

Encargada de contenido y valoración, asegura la calidad de nuestras reseñas.

Pedro Gómez

Desarrollador del sitio, crea la experiencia de usuario perfecta.

Sofía Ruiz

Community Manager que conecta a nuestra comunidad de amantes del cine.

Carlos Rojas

Colaborador en investigación, siempre en busca de nuevas historias.

!DOCTYPE html html lang=es head meta charset=UTF-8 meta name=viewport content=width=device-width, initial-scale=1.0 titleCatálogo Interactivo de Películastitle style root { --bg-color #141414; --card-bg #181818; --text-color #ffffff; --accent-color #e50914; } body { font-family 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background-color var(--bg-color); color var(--text-color); margin 0; padding 20px; } h1 { color var(--accent-color); text-align center; margin-bottom 30px; } .grid { display grid; grid-template-columns repeat(auto-fill, minmax(250px, 1fr)); gap 25px; max-width 1200px; margin 0 auto; } .card { background-color var(--card-bg); border-radius 8px; overflow hidden; box-shadow 0 4px 10px rgba(0,0,0,0.5); transition transform 0.3s ease; position relative; } .cardhover { transform scale(1.03); } .card-img-container { position relative; width 100%; height 350px; } .card img { width 100%; height 100%; object-fit cover; } Indicador visual de visto superpuesto en la imagen .viewed-badge { position absolute; top 10px; right 10px; background-color rgba(0, 200, 83, 0.9); color white; padding 5px 10px; border-radius 20px; font-size 12px; font-weight bold; display none; } .card.is-viewed .viewed-badge { display block; } .card-content { padding 15px; } .card-title { margin 0 0 10px 0; font-size 1.1rem; } .actions { display flex; justify-content space-between; align-items center; border-top 1px solid #333; padding-top 12px; } .btn { background none; border none; color #aaa; cursor pointer; font-size 1.3rem; padding 5px; transition color 0.2s, transform 0.1s; border-radius 50px; width 40px; height 40px; display flex; align-items center; justify-content center; } .btnhover { transform scale(1.2); background-color rgba(255,255,255,0.1); } Estados activos según la selección del usuario .btn-view.active { color #00c853; } Verde .btn-love.active { color #ff3d00; } Rojo fuego (Me encanta) .btn-like.active { color #29b6f6; } Azul (MenosNormal) .btn-dislike.active { color #757575; } Gris oscuro (No me gusta) .feedback-status { text-align center; margin-top 30px; font-size 0.9rem; color #808080; } style head body h1Mi Catálogo de Películash1 div class=grid id=catalog-griddiv div class=feedback-status Los cambios se guardan automáticamente en la base de datos local (LocalStorage) de tu navegador. div script 1. Datos simulados del servidor (Películas con imágenes de ejemplo) const peliculasIniciales = [ { id p1, titulo Aventura en el Espacio, img httpsunsplash.com }, { id p2, titulo El Secreto del Bosque, img httpsunsplash.com }, { id p3, titulo Neón y Asfalto 2049, img httpsunsplash.com }, { id p4, titulo Mar de Tormentas, img httpsunsplash.com } ]; 2. Base de Datos Local Inicializa el estado si es la primera vez que se abre la web if (!localStorage.getItem('usuario_interacciones')) { localStorage.setItem('usuario_interacciones', JSON.stringify({})); } Leer datos de nuestra base de datos function obtenerBaseDatos() { return JSON.parse(localStorage.getItem('usuario_interacciones')); } Guardar datos en nuestra base de datos function guardarEnBaseDatos(id, campo, valor) { const db = obtenerBaseDatos(); if (!db[id]) { db[id] = { visto false, reaccion null }; } db[id][campo] = valor; localStorage.setItem('usuario_interacciones', JSON.stringify(db)); } 3. Renderizar la interfaz web dinámicamente const grid = document.getElementById('catalog-grid'); const interaccionesUsuario = obtenerBaseDatos(); peliculasIniciales.forEach(pelicula = { Recuperar el estado guardado para esta película específica const estadoGuardado = interaccionesUsuario[pelicula.id] { visto false, reaccion null }; const card = document.createElement('div'); card.className = `card ${estadoGuardado.visto 'is-viewed' ''}`; card.id = `card-${pelicula.id}`; card.innerHTML = ` div class=card-img-container span class=viewed-badge✓ Vistospan img src=${pelicula.img} alt=${pelicula.titulo} div div class=card-content h3 class=card-title${pelicula.titulo}h3 div class=actions !-- Botón de Visto -- button class=btn btn-view ${estadoGuardado.visto 'active' ''} onclick=toggleVisto('${pelicula.id}') title=Marcar como visto 👁 button !-- Botones de Reacción (Me gusta mucho, regular, no me gusta) -- button class=btn btn-love ${estadoGuardado.reaccion === 'mucho' 'active' ''} onclick=setReaccion('${pelicula.id}', 'mucho') title=Me gusta mucho 🔥 button button class=btn btn-like ${estadoGuardado.reaccion === 'menos' 'active' ''} onclick=setReaccion('${pelicula.id}', 'menos') title=Me gusta (pero menos) 👍 button button class=btn btn-dislike ${estadoGuardado.reaccion === 'no' 'active' ''} onclick=setReaccion('${pelicula.id}', 'no') title=No me gusta 👎 button div div `; grid.appendChild(card); }); 4. Lógica de Interacción del Usuario (Controladores de Eventos) Cambiar estado de Visto function toggleVisto(id) { const cardElement = document.getElementById(`card-${id}`); const btnView = cardElement.querySelector('.btn-view'); const db = obtenerBaseDatos(); const estadoActual = db[id].visto false; const nuevoEstado = !estadoActual; Guardar cambio en la Base de Datos guardarEnBaseDatos(id, 'visto', nuevoEstado); Actualizar la interfaz visual en tiempo real if (nuevoEstado) { cardElement.classList.add('is-viewed'); btnView.classList.add('active'); } else { cardElement.classList.remove('is-viewed'); btnView.classList.remove('active'); } } Cambiar estado de las 3 reacciones de valoración function setReaccion(id, tipoReaccion) { const cardElement = document.getElementById(`card-${id}`); const btnLove = cardElement.querySelector('.btn-love'); const btnLike = cardElement.querySelector('.btn-like'); const btnDislike = cardElement.querySelector('.btn-dislike'); const db = obtenerBaseDatos(); const reaccionActual = db[id].reaccion null; Si hace clic en la misma reacción que ya estaba activa, se desmarca (vuelve a null) const nuevaReaccion = (reaccionActual === tipoReaccion) null tipoReaccion; Guardar cambio en la Base de Datos guardarEnBaseDatos(id, 'reaccion', nuevaReaccion); Limpiar todas las clases activas de los tres botones de reacción btnLove.classList.remove('active'); btnLike.classList.remove('active'); btnDislike.classList.remove('active'); Activar únicamente el botón que corresponde a la nueva reacción if (nuevaReaccion === 'mucho') btnLove.classList.add('active'); if (nuevaReaccion === 'menos') btnLike.classList.add('active'); if (nuevaReaccion === 'no') btnDislike.classList.add('active'); } script body html