Sync React frontend into git

- Replace stale TanStack Router scaffold with working react-router-dom app
- Add all 9 page components + cyber theme CSS
- Remove routeTree.gen.ts, add index.css, query.ts
This commit is contained in:
jp
2026-08-13 18:22:03 +01:00
parent 41c8b65870
commit 489241b798
17 changed files with 961 additions and 59 deletions

View File

@ -0,0 +1,29 @@
import { useQuery } from "@tanstack/react-query";
import { useParams } from "react-router-dom";
import { api } from "../lib/api";
export default function ContactHistory() {
const { num } = useParams();
const { data, isLoading, error } = useQuery({ queryKey: ["history", num], queryFn: () => api.contactHistory(num || ""), enabled: !!num });
return (
<div className="wrap">
<div className="card" style={{ padding: "12px 16px" }}>
<div className="meta">
<a href="/contacts">&larr; Back to contacts</a>
{data && <> · {data.messages?.length ?? 0} message(s) from <b>{data.contact}</b></>}
</div>
</div>
{isLoading && <div className="card empty">Loading...</div>}
{error && <div className="card err">{(error as Error).message}</div>}
{data?.messages?.map((m) => (
<div key={m.id} className={"card" + (m.is_read ? "" : " unread")}>
<div className="who">{data.contact}</div>
<div className="meta">{m.time}{m.duration_fmt ? ` · ${m.duration_fmt}` : ""}</div>
<div className="sum">{m.summary || "(no speech detected)"}</div>
{m.has_audio && <audio controls preload="none" src={`/audio/${m.id}`} />}
</div>
))}
{data?.messages?.length === 0 && <div className="card empty">No voicemails from this caller yet.</div>}
</div>
);
}