81 lines
2.5 KiB
Svelte
81 lines
2.5 KiB
Svelte
<script lang="ts">
|
|
import { createEventDispatcher } from 'svelte';
|
|
import type { Session } from '$lib/api';
|
|
|
|
export let session: Session;
|
|
|
|
const dispatch = createEventDispatcher<{ delete: void }>();
|
|
|
|
function handleDelete(event: MouseEvent) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
dispatch('delete');
|
|
}
|
|
|
|
$: externalId = session['external-id'] || session.externalId || '';
|
|
$: updatedAt = session['updated-at'] || session.updatedAt || session['created-at'] || session.createdAt || '';
|
|
$: shortId = externalId.slice(0, 8);
|
|
|
|
function formatTime(iso: string): string {
|
|
if (!iso) return '';
|
|
const date = new Date(iso);
|
|
const now = new Date();
|
|
const diff = now.getTime() - date.getTime();
|
|
const minutes = Math.floor(diff / 60000);
|
|
const hours = Math.floor(minutes / 60);
|
|
const days = Math.floor(hours / 24);
|
|
|
|
if (days > 0) return `${days}d ago`;
|
|
if (hours > 0) return `${hours}h ago`;
|
|
if (minutes > 0) return `${minutes}m ago`;
|
|
return 'Just now';
|
|
}
|
|
|
|
const statusColors: Record<string, string> = {
|
|
idle: 'bg-zinc-600',
|
|
processing: 'bg-green-500 animate-pulse',
|
|
'awaiting-permission': 'bg-amber-500 animate-pulse'
|
|
};
|
|
|
|
$: statusColor = session.provider === 'tmux' ? 'bg-green-500' : statusColors[session.status];
|
|
|
|
const providerColors: Record<string, string> = {
|
|
claude: 'text-spice-400',
|
|
opencode: 'text-emerald-400',
|
|
tmux: 'text-cyan-400'
|
|
};
|
|
</script>
|
|
|
|
<a
|
|
href="/session/{session.id}"
|
|
class="card block hover:border-spice-500/50 transition-all active:scale-[0.98]"
|
|
>
|
|
<div class="flex items-start justify-between gap-3">
|
|
<div class="flex-1 min-w-0">
|
|
<div class="flex items-center gap-2 mb-1">
|
|
<span class="w-2 h-2 rounded-full {statusColor}"></span>
|
|
<span class="text-xs font-medium uppercase tracking-wide {providerColors[session.provider]}">
|
|
{session.provider}
|
|
</span>
|
|
</div>
|
|
|
|
<h3 class="font-medium text-zinc-100 truncate">
|
|
{session.title || `Session ${shortId}`}
|
|
</h3>
|
|
</div>
|
|
|
|
<div class="text-right flex-shrink-0 flex items-center gap-2">
|
|
<span class="text-xs text-zinc-500">{formatTime(updatedAt)}</span>
|
|
<button
|
|
on:click={handleDelete}
|
|
class="p-1 text-zinc-500 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors"
|
|
title="Delete session"
|
|
>
|
|
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</a>
|