const dataPath = "data/data.json"; const servicesGrid = document.getElementById("servicesGrid"); const portfolioGrid = document.getElementById("portfolioGrid"); const portfolioFilters = document.getElementById("portfolioFilters"); const revealNodes = document.querySelectorAll(".reveal"); let portfolioItems = []; function createServiceCards(services) { if (!servicesGrid) return; servicesGrid.innerHTML = services .map( (service) => `

${service.titulo}

${service.descripcion}

`, ) .join(""); } function buildMedia(project) { if (project.tipoMedia === "video") { return ` `; } return `${project.titulo}`; } function renderPortfolio(items) { if (!portfolioGrid) return; if (items.length === 0) { portfolioGrid.innerHTML = "

No hay proyectos en esta categoria.

"; return; } portfolioGrid.innerHTML = items .map( (project) => `
${buildMedia(project)}

${project.titulo}

${project.categoriaLabel}

`, ) .join(""); const videos = portfolioGrid.querySelectorAll("video"); videos.forEach((video) => { video.parentElement.addEventListener("mouseenter", () => video.play()); video.parentElement.addEventListener("mouseleave", () => { video.pause(); video.currentTime = 0; }); }); } function renderFilters(items) { if (!portfolioFilters) return; const uniqueCategories = ["todos", ...new Set(items.map((item) => item.categoria))]; portfolioFilters.innerHTML = uniqueCategories .map((category, index) => { const label = category === "todos" ? "Todos" : items.find((item) => item.categoria === category)?.categoriaLabel || category; return ``; }) .join(""); portfolioFilters.addEventListener("click", (event) => { const target = event.target.closest(".filter-btn"); if (!target) return; portfolioFilters .querySelectorAll(".filter-btn") .forEach((button) => button.classList.remove("active")); target.classList.add("active"); const { category } = target.dataset; if (category === "todos") { renderPortfolio(portfolioItems); return; } const filtered = portfolioItems.filter((item) => item.categoria === category); renderPortfolio(filtered); }); } function setupReveal() { if (!("IntersectionObserver" in window)) { revealNodes.forEach((node) => node.classList.add("visible")); return; } const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add("visible"); observer.unobserve(entry.target); } }); }, { threshold: 0.12 }, ); revealNodes.forEach((node) => observer.observe(node)); } function setupParallax() { const heroMedia = document.querySelector(".hero-media video, .hero-media"); if (!heroMedia) return; window.addEventListener("scroll", () => { const y = window.scrollY; heroMedia.style.transform = `translateY(${y * 0.12}px)`; }); } function setupContactValidation() { const form = document.getElementById("contactForm"); const formError = document.getElementById("formError"); if (!form || !formError) return; form.addEventListener("submit", (event) => { const nombre = form.querySelector("#nombre")?.value.trim() || ""; const email = form.querySelector("#email")?.value.trim() || ""; const mensaje = form.querySelector("#mensaje")?.value.trim() || ""; if (nombre.length < 2) { event.preventDefault(); formError.textContent = "El nombre debe tener al menos 2 caracteres."; return; } const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); if (!emailValid) { event.preventDefault(); formError.textContent = "Introduce un email valido."; return; } if (mensaje.length < 10) { event.preventDefault(); formError.textContent = "El mensaje debe tener al menos 10 caracteres."; return; } formError.textContent = ""; }); } async function init() { setupReveal(); setupParallax(); setupContactValidation(); try { const response = await fetch(dataPath, { cache: "no-store" }); if (!response.ok) { throw new Error("No se pudo cargar el catalogo."); } const data = await response.json(); const services = Array.isArray(data.servicios) ? data.servicios : []; portfolioItems = Array.isArray(data.proyectos) ? data.proyectos : []; createServiceCards(services); renderFilters(portfolioItems); renderPortfolio(portfolioItems); } catch (error) { if (servicesGrid) { servicesGrid.innerHTML = "

No se pudieron cargar los servicios en este momento.

"; } if (portfolioGrid) { portfolioGrid.innerHTML = "

No se pudo cargar el portfolio en este momento.

"; } console.error(error); } } init();