kh3_site_fixed/js/projects.js
2026-02-11 19:37:15 +00:00

163 lines
No EOL
9.5 KiB
JavaScript

document.addEventListener('DOMContentLoaded', function () {
// --- Start of projects.js specific logic ---
let projectsData = [];
let currentProject = null;
let currentImageIndex = 0;
// --- Core Functions for fetching and rendering project cards ---
async function loadProjects() {
try {
const response = await fetch("data/projects.json");
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
projectsData = await response.json();
renderProjects();
} catch (error) {
console.error("Error loading projects:", error);
const grid = document.getElementById("projectsGrid");
if(grid) grid.innerHTML = `<p class="text-center text-kh3-red col-span-full">Failed to load projects.</p>`;
}
}
function renderProjects() {
const grid = document.getElementById("projectsGrid");
if (!grid) return;
grid.innerHTML = projectsData.map((project, index) => `
<div class="project-card group relative overflow-hidden rounded-lg bg-kh3-grey/10 border border-white/10 cursor-pointer opacity-0"
data-anim="fade-in-up" data-anim-delay="${200 + index * 100}"
onclick="openProjectDetails('${project.id}')">
<div class="relative h-64 overflow-hidden">
<img src="${project.images[0]}" alt="${project.name}" class="project-image w-full h-full object-cover transition-all duration-600" />
<div class="project-overlay absolute inset-0 bg-black/80 flex items-center justify-center"><div class="text-center"><div class="w-12 h-12 bg-kh3-red rounded-full flex items-center justify-center mx-auto mb-4"><svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path></svg></div><p class="text-white font-medium">VIEW PROJECT</p></div></div>
</div>
<div class="p-6">
<div class="flex items-center justify-between mb-3"><span class="text-kh3-red text-sm font-medium tracking-wider">${project.category}</span><span class="text-white/60 text-sm">${project.completionDate}</span></div>
<h3 class="text-xl font-bold text-white mb-2 group-hover:text-kh3-red transition-colors duration-300">${project.name}</h3>
<p class="text-white/70 text-sm mb-4 line-clamp-2">${project.description}</p>
<div class="flex items-center justify-between"><span class="text-white/50 text-sm">${project.size}</span><span class="text-white/50 text-sm">${project.location}</span></div>
</div>
</div>
`).join("");
if (window.initDynamicAnimations) window.initDynamicAnimations();
}
// --- MODAL Functionality (Restored from original) ---
function openProjectDetails(projectId) {
const project = projectsData.find((p) => p.id === projectId);
if (!project) return;
currentProject = project;
currentImageIndex = 0;
document.getElementById("modalTitle").textContent = project.name;
document.getElementById("modalCategory").textContent = project.category;
document.getElementById("modalDescription").textContent = project.description;
document.getElementById("modalClient").textContent = project.client;
document.getElementById("modalTypeOfWork").textContent = project.typeOfWork;
document.getElementById("modalSize").textContent = project.size;
document.getElementById("modalCompletionDate").textContent = project.completionDate;
document.getElementById("modalLocation").textContent = project.location;
document.getElementById("modalHighlights").innerHTML = project.highlights.map(h => `<li class="flex items-start space-x-2"><div class="w-1.5 h-1.5 bg-kh3-red rounded-full mt-2 flex-shrink-0"></div><span class="text-white/80 text-sm">${h}</span></li>`).join("");
setupImageCarousel(project.images); // RESTORED CALL
const modal = document.getElementById("projectModal");
const modalContent = document.getElementById("modalContent");
modal.classList.remove("hidden");
document.body.style.overflow = "hidden";
setTimeout(() => modalContent.classList.remove("scale-95", "opacity-0"), 10);
}
function closeModal() {
const modal = document.getElementById("projectModal");
const modalContent = document.getElementById("modalContent");
modalContent.classList.add("scale-95", "opacity-0");
setTimeout(() => {
modal.classList.add("hidden");
document.body.style.overflow = "auto";
}, 500);
}
// --- MODAL CAROUSEL Functionality (Restored from original) ---
function setupImageCarousel(images) {
const mainImage = document.getElementById("modalMainImage");
const imageDots = document.getElementById("imageDots");
const imageCounter = document.getElementById("imageCounter");
const totalImages = document.getElementById("totalImages");
mainImage.src = images[0];
mainImage.alt = currentProject.name;
totalImages.textContent = images.length;
imageDots.innerHTML = images.map((_, index) => `<button class="w-2 h-2 rounded-full transition-all duration-300 ${index === 0 ? "bg-kh3-red" : "bg-white/30"}" onclick="goToImage(${index})"></button>`).join("");
updateImageCarousel(); // Initial call to set counter
}
function updateImageCarousel() {
const mainImage = document.getElementById("modalMainImage");
const imageDots = document.getElementById("imageDots");
const imageCounter = document.getElementById("imageCounter");
if (!mainImage || !currentProject) return;
mainImage.style.opacity = "0";
setTimeout(() => {
mainImage.src = currentProject.images[currentImageIndex];
mainImage.style.opacity = "1";
}, 250);
imageCounter.textContent = currentImageIndex + 1;
const dots = imageDots.querySelectorAll("button");
dots.forEach((dot, index) => {
dot.classList.toggle("bg-kh3-red", index === currentImageIndex);
dot.classList.toggle("bg-white/30", index !== currentImageIndex);
});
}
// --- IMAGE ENLARGEMENT Functionality (Restored from original) ---
function enlargeImage() {
if (!currentProject) return;
const enlargedImage = document.getElementById("enlargedImage");
document.getElementById("enlargedImageCounter").textContent = currentImageIndex + 1;
document.getElementById("enlargedTotalImages").textContent = currentProject.images.length;
enlargedImage.src = currentProject.images[currentImageIndex];
document.getElementById("imageEnlargeModal").classList.remove("hidden");
}
function closeEnlargeModal() {
document.getElementById("imageEnlargeModal").classList.add("hidden");
}
// --- Global Accessibility for onclick and keyboard events (Restored) ---
window.openProjectDetails = openProjectDetails;
window.closeModal = closeModal;
window.enlargeImage = enlargeImage;
window.goToImage = (index) => { currentImageIndex = index; updateImageCarousel(); };
window.nextImage = () => { currentImageIndex = (currentImageIndex + 1) % currentProject.images.length; updateImageCarousel(); };
window.prevImage = () => { currentImageIndex = (currentImageIndex === 0) ? currentProject.images.length - 1 : currentImageIndex - 1; updateImageCarousel(); };
// Event listeners for modal controls
document.getElementById("closeModal")?.addEventListener("click", closeModal);
document.getElementById("projectModal")?.addEventListener("click", (e) => { if (e.target.id === "projectModal") closeModal(); });
document.getElementById("prevImage")?.addEventListener("click", window.prevImage);
document.getElementById("nextImage")?.addEventListener("click", window.nextImage);
document.getElementById("closeEnlargeModal")?.addEventListener("click", closeEnlargeModal);
document.getElementById("enlargePrevImage")?.addEventListener("click", () => { window.prevImage(); enlargeImage(); });
document.getElementById("enlargeNextImage")?.addEventListener("click", () => { window.nextImage(); enlargeImage(); });
document.getElementById("imageEnlargeModal")?.addEventListener("click", (e) => { if (e.target.id === "imageEnlargeModal") closeEnlargeModal(); });
document.addEventListener("keydown", (e) => {
const isProjectModalOpen = !document.getElementById("projectModal")?.classList.contains("hidden");
const isEnlargeModalOpen = !document.getElementById("imageEnlargeModal")?.classList.contains("hidden");
if (isEnlargeModalOpen) {
if (e.key === "ArrowLeft") { window.prevImage(); enlargeImage(); }
if (e.key === "ArrowRight") { window.nextImage(); enlargeImage(); }
if (e.key === "Escape") closeEnlargeModal();
} else if (isProjectModalOpen) {
if (e.key === "ArrowLeft") window.prevImage();
if (e.key === "ArrowRight") window.nextImage();
if (e.key === "Escape") closeModal();
}
});
// --- Initialize Page ---
loadProjects();
});