● Zion Boggan
repos/Sightline/frontend/src/app/alerts/page.tsx
zionboggan.com ↗
38 lines · tsx
History for this file →
1
"use client";
2
import { useEffect, useState } from "react";
3
import Link from "next/link";
4
import { api, WatchlistHit } from "@/lib/api";
5
 
6
export default function Alerts() {
7
  const [hits, setHits] = useState<WatchlistHit[]>([]);
8
  const [err, setErr] = useState<string | null>(null);
9
 
10
  useEffect(() => {
11
    api.watchlistHits().then(setHits)
12
      .catch((e) => setErr(e.status === 401 ? "Sign in to view alerts." : String(e)));
13
  }, []);
14
 
15
  return (
16
    <div>
17
      <h1>Alert Center</h1>
18
      <p className="muted">Watchlist hits generated during ingest and backfill.</p>
19
      {err && <div className="badge danger">{err}</div>}
20
      <div className="card" style={{ marginTop: 12 }}>
21
        <table>
22
          <thead><tr><th>Plate</th><th>Matched on</th><th>Camera</th><th>When</th></tr></thead>
23
          <tbody>
24
            {hits.map((h) => (
25
              <tr key={h.id}>
26
                <td><Link href={`/search?q=${h.plate_norm}`}>{h.plate_norm}</Link></td>
27
                <td><span className="badge danger">{h.matched_on}</span></td>
28
                <td className="muted">{h.camera_id?.slice(0, 8)}</td>
29
                <td className="muted">{new Date(h.at).toLocaleString()}</td>
30
              </tr>
31
            ))}
32
            {!hits.length && !err && <tr><td colSpan={4} className="muted">No alerts.</td></tr>}
33
          </tbody>
34
        </table>
35
      </div>
36
    </div>
37
  );
38
}