/** Sidebar DOM helpers. */
function esc(str) {
return String(str ?? '')
.replace(/&/g, '&').replace(/</g, '<')
.replace(/>/g, '>').replace(/"/g, '"');
}
function timeLabel(iso) {
if (!iso) return '';
const d = new Date(iso);
if (isNaN(d)) return '';
const diff = Date.now() - d;
if (diff < 60_000) return 'just now';
if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m ago`;
if (diff < 86_400_000) return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
return d.toLocaleDateString();
}
export function renderProfiles(selectEl, profiles) {
selectEl.innerHTML = profiles
.map(p => `<option value="${esc(p.id)}">${esc(p.name)}</option>`)
.join('');
}
export function renderSessions(listEl, sessions, currentId, { onSelect, onDelete }) {
if (!sessions.length) {
listEl.innerHTML = '<div class="empty-sessions">No conversations yet</div>';
return;
}
listEl.innerHTML = sessions.map(s => {
const active = s.session_id === currentId ? ' active' : '';
const preview = esc(s.preview || 'No messages yet');
const name = esc(s.profile_name || s.profile_id);
const time = timeLabel(s.last_active);
return `
<div class="session-item${active}" data-id="${s.session_id}">
<div class="s-body">
<div class="s-profile">${name}</div>
<div class="s-preview">${preview}</div>
<div class="s-time">${time}</div>
</div>
<button class="btn-delete" data-id="${s.session_id}" title="Delete">×</button>
</div>`;
}).join('');
listEl.querySelectorAll('.session-item').forEach(el =>
el.addEventListener('click', () => onSelect(el.dataset.id))
);
listEl.querySelectorAll('.btn-delete').forEach(btn =>
btn.addEventListener('click', e => { e.stopPropagation(); onDelete(btn.dataset.id); })
);
}
export function updateChatHeader(headerEl, profileId, profileName) {
headerEl.innerHTML = profileId
? `<span class="profile-badge">${esc(profileId)}</span> ${esc(profileName || profileId)}`
: 'Select a profile and start a new chat';
}