Portfolio

Explore our creative projects and artwork

Loading...

Loading portfolio projects...

id="noProjects" style="display: none; text-align: center; padding: 40px; color: #666" >

No portfolio projects available at the moment.

id="modalContent" overflow-y: auto; overflow-x: hidden; flex: 1; scroll-behavior: smooth;
let portfolioProjects = []; // Open project modal function openProjectModal(projectId) { try { const project = portfolioProjects.find((p) => p.id === projectId); if (!project) { console.error('[Portfolio] Project not found:', projectId); return; } // Validate project data if (!project.title) { console.error('[Portfolio] Invalid project data - missing title:', project); return; } const modal = document.getElementById("projectModal"); const modalContent = document.getElementById("modalContent"); // Safe template with validated data modalContent.innerHTML = `
${project.title}
${ project.category ? `${project.category}` : "" }

${ project.title }

${project.description || "No description available."}
${ project.createdat ? `
Created on ${new Date( project.createdat ).toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric", })}
` : "" }
`; modal.style.display = "block"; modalContent.scrollTop = 0; document.body.style.overflow = "hidden"; } catch (error) { console.error('[Portfolio] Error opening modal:', error); alert('Unable to open project details. Please try again.'); } } // Close project modal function closeProjectModal() { document.getElementById("projectModal").style.display = "none"; document.body.style.overflow = "auto"; } // Close modal on outside click document.addEventListener("click", (e) => { if (e.target === modal) { closeProjectModal(); } }); // Close modal on Escape key document.addEventListener("keydown", (e) => { if (e.key === "Escape") { closeProjectModal(); } }); // Load portfolio projects from API async function loadPortfolio() { try { const response = await fetch("/api/portfolio/projects"); if (response.ok) { const data = await response.json(); portfolioProjects = data.projects || []; document.getElementById("loadingMessage").style.display = "none"; if (portfolioProjects.length === 0) { document.getElementById("noProjects").style.display = "block"; return; } // Validate and filter projects const validProjects = portfolioProjects.filter(project => { if (!project || !project.id || !project.title) { console.warn('[Portfolio] Skipping invalid project:', project); return false; } return true; }); if (validProjects.length === 0) { document.getElementById("noProjects").style.display = "block"; return; } const grid = document.getElementById("portfolioGrid"); grid.innerHTML = validProjects .map( (project) => `
${project.title} ${ project.category ? `${project.category}` : "" }

${ project.title }

${ project.description && project.description.replace(/<[^>]*>/g, '').trim() ? `

${project.description.replace(/<[^>]*>/g, '').substring(0, 80)}${project.description.length > 80 ? '...' : ''}

` : "" }
` ) .join(""); } else { document.getElementById("noProjects").style.display = "block"; } } catch (error) { console.error("Error loading portfolio:", error); document.getElementById("loadingMessage").innerHTML = '

Error loading portfolio projects. Please try again later.

'; // Initialize loadPortfolio();