feat(portal): tile headline is Leq, not Lp; note live-map for M2

Lp (instantaneous) twitches every reading and makes a poor at-a-glance headline;
Leq (energy-average) is the stable, standard sound-monitoring/compliance metric.
Overview tiles now lead with Leq. Design doc: live project map (status-colored
pins + current-reading popups) recorded as an M2 item; headline-metric rationale
noted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 03:33:42 +00:00
parent 0103917870
commit b971d19068
2 changed files with 15 additions and 6 deletions
+5 -5
View File
@@ -20,8 +20,8 @@
</div>
<div class="text-xs text-gray-400 mt-0.5 truncate">{{ loc.address or loc.project_name or '' }}</div>
<div class="mt-3 flex items-baseline gap-1">
<span class="loc-lp text-3xl font-bold text-seismo-orange">--</span>
<span class="text-sm text-gray-400">dB Lp</span>
<span class="loc-leq text-3xl font-bold text-seismo-orange">--</span>
<span class="text-sm text-gray-400">dB Leq</span>
</div>
<div class="loc-fresh text-xs text-gray-500 mt-1">&nbsp;</div>
</a>
@@ -51,7 +51,7 @@ function fmtAgo(iso) {
async function loadTile(loc) {
const el = document.querySelector(`.loc-tile[data-loc="${loc.id}"]`);
if (!el) return;
const lp = el.querySelector('.loc-lp'), badge = el.querySelector('.loc-badge'),
const leq = el.querySelector('.loc-leq'), badge = el.querySelector('.loc-badge'),
fresh = el.querySelector('.loc-fresh');
try {
const j = await (await fetch(`/portal/api/location/${encodeURIComponent(loc.id)}/live`)).json();
@@ -60,10 +60,10 @@ async function loadTile(loc) {
if (!d) {
badge.textContent = j.reason === 'no_device' ? 'No device' : 'Offline';
badge.className = 'loc-badge shrink-0 px-2 py-0.5 text-xs rounded-full bg-slate-700 text-gray-300';
lp.textContent = '--'; fresh.innerHTML = '&nbsp;';
leq.textContent = '--'; fresh.innerHTML = '&nbsp;';
return;
}
lp.textContent = (d.lp == null || d.lp === '') ? '--' : d.lp;
leq.textContent = (d.leq == null || d.leq === '') ? '--' : d.leq;
const measuring = d.measurement_state === 'Start' || d.measurement_state === 'Measure';
badge.textContent = measuring ? '● Live' : 'Stopped';
badge.className = 'loc-badge shrink-0 px-2 py-0.5 text-xs rounded-full ' +