← back to AbramsOS
views/neighborhood.ejs
78 lines
<%- include('partials/header', { title: 'Neighborhood Watch' }) %>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<section class="page-head">
<div>
<h1>🛡 Neighborhood Watch</h1>
<p class="subtle">Safety around a location — your Ring cameras, Nextdoor, Citizen, crime maps & registries within a chosen radius.</p>
</div>
</section>
<section class="glass" style="padding:1rem 1.25rem;margin-bottom:1rem">
<form id="nbForm" style="display:flex;gap:.6rem;flex-wrap:wrap;align-items:end">
<% if (props.length) { %>
<label>Saved property
<select id="assetPick">
<% props.forEach(p => { %><option value="<%= p.id %>" <%= assetId===p.id?'selected':'' %>><%= p.name %></option><% }) %>
<option value="">— custom —</option>
</select>
</label>
<% } %>
<label class="grow" style="min-width:240px">Address
<input id="addr" name="address" value="<%= address || '' %>" placeholder="123 Main St, City, ST" style="width:100%">
</label>
<label>Radius: <span id="radLbl"><%= radiusMi %></span> mi
<input id="radius" type="range" min="0.5" max="25" step="0.5" value="<%= radiusMi %>">
</label>
<button type="submit" class="btn primary">Update</button>
</form>
<% if (address && !loc) { %><p class="subtle" style="margin:.5rem 0 0">Couldn't pinpoint that address on the map — the links below still work by address.</p><% } %>
</section>
<% if (!address) { %>
<section class="empty glass"><p>Enter an address above, or add a property in <a href="/assets">Assets</a> to watch your home's neighborhood.</p></section>
<% } %>
<% if (loc) { %>
<div id="map" style="height:340px;border-radius:12px;margin-bottom:1rem"></div>
<% } %>
<section id="linkArea">
<% linkGroups.forEach(g => { %>
<section class="page-head" style="margin:.5rem 0 .25rem"><div><h2 style="font-size:1.1rem;margin:0"><%= g.title %></h2></div></section>
<section class="purchase-grid" style="grid-template-columns: repeat(auto-fill, minmax(280px, 1fr))">
<% g.items.forEach(it => { %>
<a class="purchase glass" href="<%= it.url %>" target="_blank" rel="noopener noreferrer" style="text-decoration:none;display:block">
<header><h3 style="margin:0"><%= it.name %> ↗</h3></header>
<% if (it.note) { %><p class="subtle" style="margin:.35rem 0 0"><%= it.note %></p><% } %>
</a>
<% }) %>
</section>
<% }) %>
</section>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
const LOC = <%- JSON.stringify(loc || null) %>;
const RADIUS = <%= radiusMi %>;
if (LOC && window.L) {
const map = L.map('map').setView([LOC.lat, LOC.lon], 14);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: '© OpenStreetMap' }).addTo(map);
L.marker([LOC.lat, LOC.lon]).addTo(map);
L.circle([LOC.lat, LOC.lon], { radius: RADIUS * 1609.34, color: '#539bf5', fillColor: '#539bf5', fillOpacity: 0.12 }).addTo(map);
setTimeout(() => map.invalidateSize(), 200);
}
// radius label + submit-as-querystring (server geocodes + rebuilds links)
const rad = document.getElementById('radius'), radLbl = document.getElementById('radLbl');
rad?.addEventListener('input', () => radLbl.textContent = rad.value);
const pick = document.getElementById('assetPick');
pick?.addEventListener('change', () => { if (pick.value) { location.href = '/neighborhood?asset=' + pick.value + '&radius=' + rad.value; } });
document.getElementById('nbForm')?.addEventListener('submit', (e) => {
e.preventDefault();
const a = document.getElementById('addr').value.trim();
location.href = '/neighborhood?address=' + encodeURIComponent(a) + '&radius=' + rad.value;
});
</script>
<%- include('partials/footer', {}) %>