← back to AbramsOS
routes/neighborhood.js
48 lines
// Neighborhood Watch — enter/pick an address + radius, get a geocoded map and real
// deep-links into Ring (cameras + Neighbors), Nextdoor, Citizen, crime maps, registries.
const express = require('express');
const db = require('../lib/db');
const nb = require('../lib/neighborhood');
const router = express.Router();
const DEV_USER_ID = 'user_steve';
async function propertyAssets(userId) {
return (await db.query(
`SELECT id, name, address, latitude, longitude FROM asset
WHERE user_id = $1 AND status = 'active' AND kind = 'property' AND address IS NOT NULL
ORDER BY current_value DESC NULLS LAST`,
[userId]
)).rows;
}
router.get('/neighborhood', async (req, res) => {
const props = await propertyAssets(DEV_USER_ID);
const radiusMi = Math.max(0.5, Math.min(25, Number(req.query.radius) || 2));
// Resolve the target address: explicit ?address, else ?asset lookup, else first property.
let address = req.query.address || null;
let assetId = req.query.asset || null;
if (!address && assetId) {
const a = props.find((p) => p.id === assetId);
if (a) address = a.address;
}
if (!address && props.length) { address = props[0].address; assetId = props[0].id; }
const loc = address ? await nb.geocode(address) : null;
const linkGroups = address ? nb.links({ address, loc, radiusMi }) : [];
res.render('neighborhood', { props, address, assetId, radiusMi, loc, linkGroups });
});
// Client-side re-geocode when the user edits the address / radius without a full reload.
router.get('/api/neighborhood/geocode', async (req, res) => {
const address = req.query.address;
if (!address) return res.status(400).json({ error: 'address required' });
const radiusMi = Math.max(0.5, Math.min(25, Number(req.query.radius) || 2));
const loc = await nb.geocode(address);
res.json({ loc, linkGroups: nb.links({ address, loc, radiusMi }) });
});
module.exports = router;