// Sold archive — header stats + table + gallery const SoldPage = ({ showToast }) => { useLucide(); const [view, setView] = React.useState('gallery'); const [yearFilter, setYearFilter] = React.useState('all'); const filtered = SITE_DATA.sold.filter(s => { if (yearFilter === 'all') return true; return (s.soldDate || '').startsWith(yearFilter); }); const totalSold = SITE_DATA.sold.length; const totalValue = SITE_DATA.sold.reduce((a, b) => a + b.soldPrice, 0); // Days-on-market and ask price aren't always available (e.g. rew-scraped sales). // Compute over just the rows that have them, and show "—" when there's nothing. const domItems = SITE_DATA.sold.filter(s => s.daysOnMarket != null); const avgDays = domItems.length ? Math.round(domItems.reduce((a, b) => a + b.daysOnMarket, 0) / domItems.length) : null; const askItems = SITE_DATA.sold.filter(s => s.askPrice && s.askPrice !== s.soldPrice); const overAsk = SITE_DATA.sold.filter(s => s.soldPrice > s.askPrice).length; const overAskPct = askItems.length ? Math.round((overAsk / totalSold) * 100) : null; return (
Closed transactions

Sold properties

Twenty years of negotiated outcomes. The detail page for each sale shows the days on market, the gap to ask, and what made the property move. Browse the highlights below — the full archive is available on request.

{/* Stats strip */}
{totalSold}+ Recent sales shown
${(totalValue / 1_000_000).toFixed(1)}M Combined sale value
{avgDays != null ? avgDays : '—'} Avg days on market
{overAskPct != null ? overAskPct + '%' : '—'} Sold at or over ask
Filter by year {filtered.length} sales
{view === 'gallery' && (
{filtered.map(s => ( showToast(s.daysOnMarket != null ? `${s.address} — sold ${formatFullPrice(s.soldPrice)} in ${s.daysOnMarket} days` : `${s.address} — sold ${formatFullPrice(s.soldPrice)}`)} /> ))}
)} {view === 'table' && (
Property Neighbourhood Sold Specs DOM Date
{filtered.map(s => { const overAsk = s.soldPrice - s.askPrice; const overAskPct = ((overAsk / s.askPrice) * 100).toFixed(1); return (
{s.address}
{s.city}
{s.neighbourhood} {formatFullPrice(s.soldPrice)} {overAsk > 0 &&
+{overAskPct}% over ask
} {overAsk < 0 &&
{overAskPct}% under ask
}
{s.beds}bd · {s.baths}ba · {s.sqft.toLocaleString()} sf {s.daysOnMarket != null ? s.daysOnMarket + 'd' : '—'} {s.soldDate ? new Date(s.soldDate).toLocaleDateString('en-CA', { month: 'short', year: 'numeric' }) : '—'}
); })}
)}
); }; window.SoldPage = SoldPage;