import React, { useMemo, useState } from 'react'
/**
* Left panel: searchable, paginated list of conversations.
*/
export default function ConversationList({ conversations, loading, activeId, currentUserId, onSelect }) {
const [search, setSearch] = useState('')
const filtered = useMemo(() => {
const q = search.toLowerCase().trim()
if (!q) return conversations
return conversations.filter(conv => {
const label = convLabel(conv, currentUserId).toLowerCase()
const last = (conv.latest_message?.[0]?.body ?? '').toLowerCase()
return label.includes(q) || last.includes(q)
})
}, [conversations, search, currentUserId])
return (
{/* Search */}
setSearch(e.target.value)}
className="w-full rounded-lg bg-gray-100 dark:bg-gray-800 px-3 py-1.5 text-sm text-gray-900 dark:text-gray-100 placeholder-gray-400 outline-none focus:ring-2 focus:ring-blue-500"
/>
{/* List */}
{loading && (
- Loadingβ¦
)}
{!loading && filtered.length === 0 && (
-
{search ? 'No matches found.' : 'No conversations yet.'}
)}
{filtered.map(conv => (
onSelect(conv.id)}
/>
))}
)
}
function ConversationRow({ conv, isActive, currentUserId, onClick }) {
const label = convLabel(conv, currentUserId)
const lastMsg = Array.isArray(conv.latest_message) ? conv.latest_message[0] : conv.latest_message
const preview = lastMsg ? truncate(lastMsg.body, 60) : 'No messages yet'
const unread = conv.unread_count ?? 0
const myParticipant = conv.all_participants?.find(p => p.user_id === currentUserId)
const isArchived = myParticipant?.is_archived ?? false
const isPinned = myParticipant?.is_pinned ?? false
return (
)
}
// ββ Helpers ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
function convLabel(conv, currentUserId) {
if (conv.type === 'group') return conv.title ?? 'Group'
const other = conv.all_participants?.find(p => p.user_id !== currentUserId)
return other?.user?.username ?? 'Direct message'
}
function truncate(str, max) {
if (!str) return ''
return str.length > max ? str.slice(0, max) + 'β¦' : str
}
function relativeTime(iso) {
const diff = (Date.now() - new Date(iso).getTime()) / 1000
if (diff < 60) return 'now'
if (diff < 3600) return `${Math.floor(diff / 60)}m`
if (diff < 86400) return `${Math.floor(diff / 3600)}h`
return `${Math.floor(diff / 86400)}d`
}