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 `
`;
}
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();