{project.name}
{project.summary[lang]}
/* portfolio.jsx — Image-heavy grid + lightbox modal */ const { useState: _useState, useEffect: _useEffect, useMemo: _useMemo } = React; function PortfolioPage({ onNavigate, initialProject = null }) { const { t, lang } = useLang(); const { PORTFOLIO, FILTERS } = window.JMC_DATA; const [filter, setFilter] = _useState('all'); const [sort, setSort] = _useState('recent'); const [openId, setOpenId] = _useState(initialProject); _useEffect(() => { if (initialProject) setOpenId(initialProject); }, [initialProject]); const filtered = _useMemo(() => { let list = filter === 'all' ? PORTFOLIO : PORTFOLIO.filter(p => p.type === filter); list = [...list]; if (sort === 'recent') list.sort((a, b) => b.year - a.year); if (sort === 'capacity') list.sort((a, b) => { const num = s => parseFloat((s || '').replace(/[^\d.]/g, '')) || 0; return num(b.capacity) - num(a.capacity); }); if (sort === 'alpha') list.sort((a, b) => a.name.localeCompare(b.name)); return list; }, [filter, sort, PORTFOLIO]); const openProject = openId ? PORTFOLIO.find(p => p.id === openId) : null; return (
{t.portfolio.sub}
{project.summary[lang]}
{project.summary[lang]}