/* ============================================================ Pipeline list view — sortable table of assessed sites ============================================================ */ const PC_COLS = [ { key: 'name', label: 'Site', num: false }, { key: 'region', label: 'Region', num: false }, { key: 'area_ha', label: 'Area (ha)', num: true }, { key: 'overall_score', label: 'Score', num: true }, { key: 'overall_status',label: 'Status', num: false }, { key: 'assessed_at', label: 'Assessed', num: false }, ]; const STATUS_RANK = { green: 4, amber: 3, red: 2, unknown: 1 }; function scoreColor(status) { return { green: 'var(--st-green)', amber: 'var(--st-amber)', red: 'var(--st-red)', unknown: 'var(--st-unknown)' }[status] || 'var(--st-unknown)'; } const Pipeline = ({ sites, onOpen }) => { const [sort, setSort] = React.useState({ key: 'overall_score', dir: 'desc' }); const sorted = React.useMemo(() => { const arr = [...sites]; const { key, dir } = sort; arr.sort((a, b) => { let av, bv; if (key === 'overall_status') { av = STATUS_RANK[a.overall_status]; bv = STATUS_RANK[b.overall_status]; } else if (key === 'overall_score') { av = a.overall_score == null ? -1 : a.overall_score; bv = b.overall_score == null ? -1 : b.overall_score; } else { av = a[key]; bv = b[key]; } if (typeof av === 'string') { av = av.toLowerCase(); bv = bv.toLowerCase(); } if (av < bv) return dir === 'asc' ? -1 : 1; if (av > bv) return dir === 'asc' ? 1 : -1; return 0; }); return arr; }, [sites, sort]); const toggle = key => setSort(s => s.key === key ? { key, dir: s.dir === 'asc' ? 'desc' : 'asc' } : { key, dir: key === 'name' || key === 'region' ? 'asc' : 'desc' }); const stats = React.useMemo(() => { const c = { green: 0, amber: 0, red: 0, unknown: 0 }; sites.forEach(s => c[s.overall_status]++); return c; }, [sites]); return (
Prospecting pipeline

Every site we’ve screened

Ranked fast-screen results across Hawke’s Bay, Northland and the Bay of Plenty. Open any site to view it on the map and read the full report.

{sites.length}
Sites assessed
{stats.green}
Strong prospects
{stats.amber}
Needs a closer look
{stats.red + stats.unknown}
Flagged or pending
{PC_COLS.map(col => ( ))} {sorted.map(s => ( onOpen(s.id)}> ))}
toggle(col.key)}> {col.label}{sort.key === col.key ? (sort.dir === 'asc' ? '▲' : '▼') : '▾'}
{s.name}
{s.address}
{s.region} {s.area_ha.toFixed(1)} {s.overall_score == null ? '–' : s.overall_score} {s.assessed_at}
); }; window.Pipeline = Pipeline;