// ─────────────────────────────────────────────────────────
// Small helpers (kept on window so other modules can use them)
// ─────────────────────────────────────────────────────────
const STATE_LABEL = {
disconnected: 'disconnected',
need_setup: 'needs setup',
ready: 'ready',
bridge_offline: 'bridge offline',
};
const fmtClock = (ts) => {
const d = new Date(ts);
return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false });
};
const fmtClockMs = (ts) => {
const d = new Date(ts);
const t = d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false });
return t + '.' + String(d.getMilliseconds()).padStart(3, '0');
};
const sortChats = (chats) => [...chats].sort((a, b) => {
const la = a.messages[a.messages.length - 1]?.ts || a.created_at || 0;
const lb = b.messages[b.messages.length - 1]?.ts || b.created_at || 0;
return lb - la;
});
window.STATE_LABEL = STATE_LABEL;
window.fmtClock = fmtClock;
window.fmtClockMs = fmtClockMs;
window.sortChats = sortChats;
// ─────────────────────────────────────────────────────────
// StatusPill
// ─────────────────────────────────────────────────────────
function StatusPill({ state }) {
return (
{STATE_LABEL[state] || state}
);
}
window.StatusPill = StatusPill;
// ─────────────────────────────────────────────────────────
// ContactModal — handles both "new chat" and "edit name"
// ─────────────────────────────────────────────────────────
function ContactModal({ mode, initial, onClose, onSave }) {
// In edit mode, if name == number we treat the existing name as blank.
const initialName = (initial && initial.name !== initial.number) ? initial.name : '';
const [number, setNumber] = React.useState(initial?.number || '');
const [name, setName] = React.useState(initialName);
const firstField = React.useRef(null);
React.useEffect(() => { firstField.current?.focus(); }, []);
const numberEditable = mode !== 'edit';
const normalise = (s) => {
const trimmed = s.trim();
if (!trimmed) return '';
return trimmed.replace(/[\s-]/g, '');
};
const submit = () => {
const n = normalise(number);
if (!n) return;
onSave(n, name.trim() || null);
};
const isEdit = mode === 'edit';
return (
e.stopPropagation()}>
{isEdit ? 'Edit contact' : 'New chat'}
{isEdit
? 'Rename this contact, or give a previously unknown number a name.'
: 'Start a conversation with a phone number. Chats also appear automatically when an SMS or call comes in.'}