import { store } from '../store.js'; import { icon } from '../icons.js'; function relativeTime(isoString) { const now = Date.now(); const then = new Date(isoString).getTime(); const diff = Math.floor((now - then) / 1000); if (diff < 60) return 'just now'; if (diff < 3600) return `${Math.floor(diff / 60)}m ago`; if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`; if (diff < 604800) return `${Math.floor(diff / 86400)}d ago`; return new Date(isoString).toLocaleDateString(); } export class Sidebar { constructor() { this.el = null; this._mobileOpen = false; } render() { const wrapper = document.createElement('div'); wrapper.className = 'relative'; wrapper.innerHTML = this._template(); this.el = wrapper.firstElementChild; this._bindEvents(); return this.el; } _template() { const convs = store.getConversations(); const currentId = store.getCurrentConversationId(); const items = convs.map(conv => { const active = conv.id === currentId; return `
${escapeHtml(conv.title || 'New Chat')}
${relativeTime(conv.updatedAt || conv.createdAt)}
`; }).join(''); return ` `; } _bindEvents() { this.el.querySelector('#new-chat-btn').addEventListener('click', () => { document.dispatchEvent(new CustomEvent('sidebar:newchat')); }); this.el.querySelector('#conv-list').addEventListener('click', (e) => { const delBtn = e.target.closest('.delete-conv'); if (delBtn) { e.stopPropagation(); const convId = delBtn.dataset.convId; if (confirm('Delete this conversation?')) { store.deleteConversation(convId); document.dispatchEvent(new CustomEvent('sidebar:deleted', { detail: { convId } })); this.update(); } return; } const item = e.target.closest('[data-conv-id]'); if (item && !item.classList.contains('delete-conv')) { const convId = item.dataset.convId; document.dispatchEvent(new CustomEvent('sidebar:select', { detail: { convId } })); } }); } update() { const list = this.el.querySelector('#conv-list'); const convs = store.getConversations(); const currentId = store.getCurrentConversationId(); if (convs.length === 0) { list.innerHTML = '
No conversations yet.
Start a new chat!
'; return; } const items = convs.map(conv => { const active = conv.id === currentId; return `
${escapeHtml(conv.title || 'New Chat')}
${relativeTime(conv.updatedAt || conv.createdAt)}
`; }).join(''); list.innerHTML = items; } } function escapeHtml(str) { return String(str) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); }