← back to Commercialrealestate
condos: surface FHA expiration date as a toggleable grid column
4edfac90e7ecb411c2b00ecb2673d493a49e9a44 · 2026-08-07 15:35:30 -0700 · Steve Abrams
Extract the matched FHA cert's expiration (MM/DD/YYYY) server-side from
warrant_source (listings) and expiration_date (FHA directory) and expose it as
fha_expiration_date on /api/condos and /api/fha-condos; add a default-off
'FHA expires' column in condos.html.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M public/condos.htmlM scripts/serve.js
Diff
commit 4edfac90e7ecb411c2b00ecb2673d493a49e9a44
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Aug 7 15:35:30 2026 -0700
condos: surface FHA expiration date as a toggleable grid column
Extract the matched FHA cert's expiration (MM/DD/YYYY) server-side from
warrant_source (listings) and expiration_date (FHA directory) and expose it as
fha_expiration_date on /api/condos and /api/fha-condos; add a default-off
'FHA expires' column in condos.html.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
public/condos.html | 4 ++++
scripts/serve.js | 15 ++++++++++++---
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/public/condos.html b/public/condos.html
index ae78101..8b3770d 100644
--- a/public/condos.html
+++ b/public/condos.html
@@ -212,6 +212,10 @@ function statusBadge(s){
const FIELDS=[
{k:'project_name',l:'Project', col:1},
{k:'warrantable_status', l:'Warrantability', badge:1, col:1},
+ // FHA-approval expiration (MM/DD/YYYY) — the date warrantability lapses / lapsed. Surfaced by the
+ // server from warrant_source (listings) or expiration_date (FHA directory). Plain string, not date:1
+ // (the value is date-only, so the datetime formatter would tack on a bogus "12:00 AM").
+ {k:'fha_expiration_date', l:'FHA expires', col:1},
{k:'city', l:'City', col:1},
{k:'hoa', l:'HOA/mo', money:1, col:1, suf:'/mo'},
{k:'beds', l:'Beds', col:1},
diff --git a/scripts/serve.js b/scripts/serve.js
index 06062f1..671421a 100644
--- a/scripts/serve.js
+++ b/scripts/serve.js
@@ -712,6 +712,15 @@ function fhaEffectiveSignal(c, today) {
return (exp < today) ? 'fha_expired' : 'fha_approved';
}
+// Surface the matched FHA cert's expiration as a clean MM/DD/YYYY string so condos.html can show it
+// as a toggleable grid column. The date already rides inside warrant_source ("...exp MM/DD/YYYY" for
+// approved, "...Expired MM/DD/YYYY (expired)" for lapsed) on listings, and in expiration_date on the
+// raw FHA directory rows — both dirty. Extract the first MM/DD/YYYY, dropping any suffix. Read-only.
+function fhaExpiryOf(v) {
+ const m = String(v || '').match(/(\d{2})\/(\d{2})\/(\d{4})/);
+ return m ? m[0] : '';
+}
+
// Normalize scrape placeholder strings ("N/A", "Unknown", "None", "TBD", "-") in an attribution
// field to null, so a placeholder never renders as a real broker/firm (a clickable "N/A" drill-link)
// or counts as a distinct firm in filters. Real values pass through untouched.
@@ -854,7 +863,7 @@ app.get('/api/condos', async (req, res) => {
FROM condo_card ${where} ORDER BY (status='active') DESC, created_at DESC LIMIT 5000`, args);
if (r.rows.length) {
const today = new Date(); today.setHours(0, 0, 0, 0);
- let rows = r.rows.map(c => overlayBroker({ ...c, warrantable_status: listingEffectiveWarrant(c, today), broker_name: cleanAttr(c.broker_name), firm_name: cleanAttr(c.firm_name) }));
+ let rows = r.rows.map(c => overlayBroker({ ...c, warrantable_status: listingEffectiveWarrant(c, today), fha_expiration_date: fhaExpiryOf(c.warrant_source || (c.warrant_signals && c.warrant_signals.source)), broker_name: cleanAttr(c.broker_name), firm_name: cleanAttr(c.firm_name) }));
if (status && status !== 'all') rows = rows.filter(c => c.warrantable_status === status);
return res.json({ condos: rows, label: CONDO_LABEL, source: 'db' });
}
@@ -865,7 +874,7 @@ app.get('/api/condos', async (req, res) => {
const file = path.join(ROOT, 'data', 'condos-redfin.json');
const { condos = [] } = JSON.parse(fs.readFileSync(file, 'utf8'));
const today = new Date(); today.setHours(0, 0, 0, 0);
- let rows = condos.map(c => overlayBroker({ ...c, warrantable_status: listingEffectiveWarrant(c, today), broker_name: cleanAttr(c.broker_name), firm_name: cleanAttr(c.firm_name) }));
+ let rows = condos.map(c => overlayBroker({ ...c, warrantable_status: listingEffectiveWarrant(c, today), fha_expiration_date: fhaExpiryOf(c.warrant_source || (c.warrant_signals && c.warrant_signals.source)), broker_name: cleanAttr(c.broker_name), firm_name: cleanAttr(c.firm_name) }));
if (status && status !== 'all') rows = rows.filter(c => c.warrantable_status === status);
return res.json({ condos: rows, label: CONDO_LABEL, source: 'snapshot' });
} catch (e) {
@@ -957,7 +966,7 @@ app.get('/api/fha-condos', (req, res) => {
if (q) rows = rows.filter(c => (c.project_name + ' ' + c.city + ' ' + c.zip + ' ' + c.address).toLowerCase().includes(q));
// Normalize the ALL-CAPS HUD city names + repair the "CANADA"/91011 truncation for display,
// consistent with Panel 7 (fixCity, defined below). Non-mutating — the source JSON is untouched.
- const out = rows.slice(0, 400).map(c => ({ ...c, city: fixCity(c.city, c.zip), warrant_signal: fhaEffectiveSignal(c, today) }));
+ const out = rows.slice(0, 400).map(c => ({ ...c, city: fixCity(c.city, c.zip), warrant_signal: fhaEffectiveSignal(c, today), fha_expiration_date: fhaExpiryOf(c.expiration_date) }));
res.json({ label: meta.label, count: rows.length, condos: out });
} catch (e) { res.status(502).json({ error: String(e.message).split('\n')[0], condos: [] }); }
});
← c992532 CRCP: fleet-wide day/night toggle + legibility pass across a
·
back to Commercialrealestate
·
condos: add color-coded 'Days to expiry' field (live calc fr 41ae00f →