118 lines
3.7 KiB
Svelte
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>
|