Files
llm-multiverse-ui/src/lib/components/SessionSidebar.svelte
shahondin1624 19c3c2bcdc feat: add session history sidebar with delete and navigation
- SessionSidebar component listing past sessions sorted by recency
- Session title preview and relative date display
- Click to switch sessions, delete with confirmation
- Added deleteSession method to session store
- Integrated sidebar into chat page layout

Closes #12

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 11:55:58 +01:00

82 lines
2.6 KiB
Svelte

<script lang="ts">
import { sessionStore } from '$lib/stores/sessions.svelte';
let {
onSelectSession,
onNewChat
}: { onSelectSession: (id: string) => void; onNewChat: () => void } = $props();
let confirmDeleteId: string | null = $state(null);
const sessions = $derived(sessionStore.getAllSessions());
const activeId = $derived(sessionStore.activeSessionId);
function handleDelete(e: MouseEvent, id: string) {
e.stopPropagation();
if (confirmDeleteId === id) {
sessionStore.deleteSession(id);
confirmDeleteId = null;
if (sessionStore.activeSessionId) {
onSelectSession(sessionStore.activeSessionId);
}
} else {
confirmDeleteId = id;
}
}
function formatDate(date: Date): string {
const now = new Date();
const diff = now.getTime() - date.getTime();
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
if (days === 0) return 'Today';
if (days === 1) return 'Yesterday';
if (days < 7) return `${days} days ago`;
return date.toLocaleDateString();
}
</script>
<aside class="flex h-full w-64 flex-col border-r border-gray-200 bg-gray-50">
<div class="border-b border-gray-200 p-3">
<button
type="button"
onclick={onNewChat}
class="w-full rounded-lg bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700"
>
+ New Chat
</button>
</div>
<div class="flex-1 overflow-y-auto">
{#if sessions.length === 0}
<p class="p-4 text-center text-sm text-gray-400">No sessions yet</p>
{:else}
{#each sessions as session (session.id)}
<div
role="button"
tabindex="0"
onclick={() => onSelectSession(session.id)}
onkeydown={(e) => { if (e.key === 'Enter') onSelectSession(session.id); }}
class="group flex w-full cursor-pointer items-start gap-2 border-b border-gray-100 px-3 py-3 text-left hover:bg-gray-100
{activeId === session.id ? 'bg-blue-50 border-l-2 border-l-blue-500' : ''}"
>
<div class="min-w-0 flex-1">
<p class="truncate text-sm font-medium text-gray-900">{session.title}</p>
<p class="mt-0.5 text-xs text-gray-500">{formatDate(session.createdAt)}</p>
</div>
<button
type="button"
onclick={(e) => handleDelete(e, session.id)}
class="shrink-0 rounded p-1 text-xs opacity-0 group-hover:opacity-100
{confirmDeleteId === session.id
? 'bg-red-100 text-red-600'
: 'text-gray-400 hover:bg-gray-200 hover:text-gray-600'}"
title={confirmDeleteId === session.id ? 'Click again to confirm' : 'Delete session'}
>
{confirmDeleteId === session.id ? '✓' : '✕'}
</button>
</div>
{/each}
{/if}
</div>
</aside>