nexus-5-frontend-3/src/lib/components/chat/ConversationList.svelte
2026-01-26 11:30:40 -05:00

118 lines
3.7 KiB
Svelte

<script lang="ts">
import { chat } from '$lib/stores/chat.svelte';
interface Props {
onClose: () => void;
}
let { onClose }: Props = $props();
function selectConversation(id: string) {
chat.selectConversation(id);
onClose();
}
function startNew() {
chat.startNewConversation();
onClose();
}
function formatDate(dateStr: string): string {
const date = new Date(dateStr);
const now = new Date();
const diffMs = now.getTime() - date.getTime();
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
if (diffDays === 0) {
return date.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
} else if (diffDays === 1) {
return 'Yesterday';
} else if (diffDays < 7) {
return date.toLocaleDateString([], { weekday: 'short' });
} else {
return date.toLocaleDateString([], { month: 'short', day: 'numeric' });
}
}
</script>
<div class="flex h-full flex-col">
<div class="flex items-center justify-between border-b border-gray-200 p-4 dark:border-gray-700">
<h3 class="font-semibold text-gray-900 dark:text-white">Conversations</h3>
<button
type="button"
onclick={onClose}
class="rounded-lg p-1 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700"
aria-label="Close"
>
<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="flex-1 overflow-y-auto">
<!-- New conversation button -->
<button
type="button"
onclick={startNew}
class="flex w-full items-center gap-3 border-b border-gray-100 px-4 py-3 text-left hover:bg-gray-50 dark:border-gray-800 dark:hover:bg-gray-700/50"
>
<div
class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary-100 text-primary-600 dark:bg-primary-900/30 dark:text-primary-400"
>
<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
</svg>
</div>
<div>
<p class="font-medium text-gray-900 dark:text-white">New Conversation</p>
<p class="text-xs text-gray-500 dark:text-gray-400">Start fresh</p>
</div>
</button>
<!-- Conversation list -->
{#each chat.conversations as conversation (conversation.id)}
<button
type="button"
onclick={() => selectConversation(conversation.id)}
class="flex w-full items-center gap-3 border-b border-gray-100 px-4 py-3 text-left hover:bg-gray-50 dark:border-gray-800 dark:hover:bg-gray-700/50 {conversation.id ===
chat.activeConversationId
? 'bg-primary-50 dark:bg-primary-900/20'
: ''}"
>
<div
class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400"
>
<svg
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
/>
</svg>
</div>
<div class="min-w-0 flex-1">
<p class="truncate font-medium text-gray-900 dark:text-white">
{conversation.title || 'New Conversation'}
</p>
<p class="text-xs text-gray-500 dark:text-gray-400">
{formatDate(conversation.updated_at || conversation.created_at)}
</p>
</div>
</button>
{/each}
{#if chat.conversations.length === 0}
<div class="p-4 text-center text-sm text-gray-500 dark:text-gray-400">
No conversations yet
</div>
{/if}
</div>
</div>