frontend: prevent contacts content overflowing the viewport + sync UI repo

- ContactsPage: drop whiteSpace:nowrap on the action cell; wrap the
  Edit/History/Delete/⋮ buttons in a flex container with flex-wrap so they
  reflow instead of forcing the table wider than the viewport; allow the
  name/number/email cell to break long strings.
- index.css: td word-break:break-word + table max-width:100% as a guard.
- Sync the UI repo (ContactsPage/ContactHistory/MessagesPage implicit-any
  annotations that unblock npm run build) into the frontend/ mirror.
This commit is contained in:
jp
2026-08-13 20:42:29 +01:00
parent 14855eab73
commit dddb8c3663
4 changed files with 22 additions and 16 deletions

View File

@ -15,7 +15,7 @@ export default function ContactHistory() {
</div>
{isLoading && <div className="card empty">Loading...</div>}
{error && <div className="card err">{(error as Error).message}</div>}
{data?.messages?.map((m) => (
{data?.messages?.map((m: any) => (
<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>

View File

@ -38,23 +38,23 @@ export default function ContactsPage() {
</div>
<table>
<tbody>
{data.map((c) => (
{data.map((c: any) => (
<tr key={c.id}>
<td>
<td style={{ minWidth: 0 }}>
<b>{c.name || "Unnamed"}</b><br />
<span style={{ color: "var(--text-muted)", fontSize: 13 }}>
<span style={{ color: "var(--text-muted)", fontSize: 13, overflowWrap: "anywhere", wordBreak: "break-word" }}>
{c.number_e164} {c.email && `· ${c.email}`}
</span>
</td>
<td style={{ textAlign: "right", whiteSpace: "nowrap" }}>
<a className="btn" href={`/contacts/edit/${c.id}`}>Edit</a>
{" "}
<a className="btn" href={`/contacts/history/${encodeURIComponent(c.number_e164 || c.name)}`}>History</a>
{" "}
<DeleteBtn id={c.id} name={c.name} />
<span style={{ position: "relative", display: "inline-block", marginLeft: 4 }}>
<ContactMenu number={c.number_e164} name={c.name} />
</span>
<td style={{ textAlign: "right", verticalAlign: "middle" }}>
<div style={{ display: "flex", flexWrap: "wrap", gap: 6, justifyContent: "flex-end" }}>
<a className="btn" href={`/contacts/edit/${c.id}`}>Edit</a>
<a className="btn" href={`/contacts/history/${encodeURIComponent(c.number_e164 || c.name)}`}>History</a>
<DeleteBtn id={c.id} name={c.name} />
<span style={{ position: "relative", display: "inline-block" }}>
<ContactMenu number={c.number_e164} name={c.name} />
</span>
</div>
</td>
</tr>
))}
@ -121,7 +121,7 @@ function ContactMenu({ number, name }: { number?: string; name?: string }) {
)}
<a
className="btn"
href={"https://who-called.co.uk/Number/" + lookup}
href={"https://www.google.com/search?q=uk+number+" + lookup}
target="_blank"
rel="noreferrer"
style={{ display: "block", borderRadius: 0, border: "none", width: "100%", justifyContent: "flex-start" }}

View File

@ -70,7 +70,7 @@ export default function MessagesPage() {
{isLoading && <div className="card empty">Loading...</div>}
{error && <div className="card err">{(error as Error).message}</div>}
{data?.messages?.map((m) => {
{data?.messages?.map((m: any) => {
const whoRaw = m.contact_name || m.callerid || "Unknown caller";
const num = sanitiseNumber(m.callerid);
const showAdd = !m.contact_name && num;
@ -192,7 +192,7 @@ function MsgContactMenu({ number, name, callerid }: { number?: string; name?: st
)}
<a
className="btn"
href={"https://who-called.co.uk/Number/" + lookup}
href={"https://www.google.com/search?q=uk+number+" + lookup}
target="_blank"
rel="noreferrer"
style={{ display: "block", borderRadius: 0, border: "none", width: "100%", justifyContent: "flex-start" }}

View File

@ -332,6 +332,12 @@ td {
padding: 10px 6px;
vertical-align: top;
border-bottom: 1px solid var(--border);
word-break: break-word;
}
/* Keep the contacts table (and any table) from forcing horizontal overflow */
table {
max-width: 100%;
}
tr:hover td { background: rgba(255, 255, 255, 0.01); }