fix(frontend): issues from the 10-25 Chrome sweep

- Incident detail "← Incidents" used router.back(), so arriving from Live
  or a shared link it went to the map / out of the app. Now a Link.
- Resolved incidents showed "0m elapsed" (manual resolve sets no
  resolved_at, updated_at can predate the last call): end is now the
  latest of resolved_at, updated_at and the newest call.
- Admin: the max-width toggle wrapped the tab bar, so it reflowed on every
  tab switch and left the cursor over e.g. "Close calls". Body only now.
- STT Eval sat on "Loading…" forever when a scanned page had zero matches
  but a next_cursor — the refill effect didn't depend on cursor.
- Trip event blocks used dark-only bg-indigo-950/60: unreadable in light
  mode. Theme tokens now.
- Reassign modal said "connected for the first time" on configured nodes.
- Dark-mode placeholders dimmed + italic; they read as filled-in values.

Frontend unverified locally (no Node, #207); CI build typechecks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Logan Cusano
2026-10-25 23:12:07 -04:00
co-authored by Claude Opus 5.5
parent 33056e2269
commit 94898d1af1
6 changed files with 45 additions and 17 deletions
+9 -2
View File
@@ -1169,8 +1169,10 @@ function SttEvalTab() {
// scanning", not "done", so this fires again on its own.
useEffect(() => {
if (queue.length === 0 && !exhausted) loadBatch();
// `cursor` is a dep so an empty page that advanced the cursor scans the
// next one; without it the tab sat on "Loading…" forever.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [queue.length, exhausted]);
}, [queue.length, exhausted, cursor]);
useEffect(() => {
setDraft(current ? (current.transcript_corrected || current.transcript || "") : "");
@@ -1309,7 +1311,10 @@ export default function AdminPage() {
const wide = tab === "users" || tab === "audit" || tab === "replay" || tab === "cameras" || tab === "outages";
return (
<div className={`space-y-6 ${wide ? "" : "max-w-2xl"}`}>
// The width toggle wraps the tab body only. It used to wrap the tab bar
// too, so the bar reflowed on every switch and left the cursor over
// whatever landed under it (e.g. Calls -> "Close calls").
<div className="space-y-6">
<h1 className="text-white text-xl font-bold font-mono">Admin</h1>
<div className="flex flex-wrap gap-1 bg-surface border border-line rounded-lg p-1 w-fit">
@@ -1326,6 +1331,7 @@ export default function AdminPage() {
))}
</div>
<div className={`space-y-6 ${wide ? "" : "max-w-2xl"}`}>
{tab === "features" && <FeaturesTab />}
{tab === "cameras" && <CameraProvidersTab />}
{tab === "outages" && <OutageProvidersTab />}
@@ -1335,6 +1341,7 @@ export default function AdminPage() {
{tab === "eval" && <SttEvalTab />}
{tab === "users" && <UsersTab currentUid={user?.uid ?? ""} />}
{tab === "audit" && <AuditLogTab />}
</div>
</div>
);
}