// Projects index page — filterable grid.
function Projects({ navigate, initialFilter = "all" }) {
const data = window.DS_DATA;
const [filter, setFilter] = useState(initialFilter);
const [sort, setSort] = useState("year-desc");
const [view, setView] = useState("grid");
useEffect(() => { setFilter(initialFilter); }, [initialFilter]);
const filtered = useMemo(() => {
let list = data.projects;
if (filter !== "all") list = list.filter((p) => p.sector === filter);
if (sort === "year-desc") list = [...list].sort((a, b) => b.year - a.year);
if (sort === "year-asc") list = [...list].sort((a, b) => a.year - b.year);
if (sort === "az") list = [...list].sort((a, b) => a.name.localeCompare(b.name));
return list;
}, [filter, sort, data.projects]);
const chips = [
{ id: "all", label: "All", count: data.projects.length },
...data.sectors.map((s) => ({ id: s.id, label: s.label, count: data.projects.filter((p) => p.sector === s.id).length })),
];
return (
Portfolio
{filter === "all" ? "Selected work — every sector, attributed." : (data.sectors.find((s) => s.id === filter)?.label || "All") + " portfolio."}
{filter === "all"
? "A working portfolio of recent named builds across hospitality, commercial, residential, healthcare, wellness and tower construction. Each card opens a structured case study."
: data.sectors.find((s) => s.id === filter)?.blurb}
{/* Filter + sort bar */}
{chips.map((c) => (
setFilter(c.id)}
>
{c.label} {String(c.count).padStart(2, "0")}
))}
View
setView("grid")}>GRID
setView("index")}>INDEX
Sort
setSort(e.target.value)}
style={{ border: "1px solid var(--border)", background: "transparent", padding: "8px 12px", fontFamily: "inherit", fontSize: 13, color: "var(--text)" }}
>
Newest first
Oldest first
A–Z
{view === "grid" ? (
{filtered.map((p) => (
navigate({ name: "project", id: p.id })} />
))}
) : (
)}
{filtered.length === 0 ? (
No projects under this filter.
) : null}
);
}
function ProjectIndexTable({ projects, navigate }) {
return (
No.
Project
Sector
Location
Scope
Year
{projects.map((p, i) => (
navigate({ name: "project", id: p.id })}
style={{
display: "grid", gridTemplateColumns: "60px 1.5fr 1.4fr 1.2fr 1.4fr 80px", gap: 16,
padding: "20px 0", borderBottom: "1px solid var(--border)", alignItems: "center",
cursor: "pointer", textAlign: "left", width: "100%",
transition: "background 0.16s ease"
}}
className="project-index-row"
onMouseEnter={(e) => e.currentTarget.style.background = "var(--surface)"}
onMouseLeave={(e) => e.currentTarget.style.background = "transparent"}
>
{String(i + 1).padStart(2, "0")}
{p.name}
{p.subtitle}
{p.sectorLabel}
{p.location}
{p.scope}
{p.year}
))}
);
}
Object.assign(window, { Projects });