← 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;