SPB Git

spb/vquant Public MIT

VibeQuant — AI-powered institutional-grade financial intelligence platform.

TypeScript 84.3% Python 11.7% JavaScript 1.6% CSS 1.5% HTML 0.7%
2.9 KB · 90 lines tsx
Raw Blame History
1/*2 * =============================================================================3 *  VibeQuant (vquant) — AI-Powered Financial Intelligence Platform4 * -----------------------------------------------------------------------------5 *  File:      client/src/components/chat/session-history.tsx6 *7 *  Author:    Simon-Pierre Boucher8 *  Contact:   contact@spboucher.ai9 *  Website:   https://www.spboucher.ai10 *  Demo:      https://www.vquant.ai11 *  License:   MIT (see LICENSE)12 *13 *  Copyright © 2026 Simon-Pierre Boucher. All rights reserved.14 * =============================================================================15 */1617import { useQuery } from "@tanstack/react-query";18import { Button } from "@/components/ui/button";19import { ScrollArea } from "@/components/ui/scroll-area";20import { Clock, MessageSquare } from "lucide-react";21import { formatDistanceToNow } from "date-fns";2223interface SessionListItem {24  sessionId: string;25  title: string;26  createdAt: string;27  updatedAt: string;28}2930interface SessionHistoryProps {31  onLoadSession: (sessionId: string) => void;32  currentSessionId: string | null;33}3435export function SessionHistory({ onLoadSession, currentSessionId }: SessionHistoryProps) {36  const { data: sessions = [], isLoading } = useQuery<SessionListItem[]>({37    queryKey: ['/api/sessions'],38  });3940  if (isLoading) {41    return (42      <div className="p-4 text-sm text-muted-foreground">43        Loading sessions...44      </div>45    );46  }4748  if (sessions.length === 0) {49    return (50      <div className="p-4 text-center">51        <MessageSquare className="w-12 h-12 mx-auto mb-3 text-muted-foreground/50" />52        <p className="text-sm text-muted-foreground">53          No conversation history yet54        </p>55      </div>56    );57  }5859  return (60    <ScrollArea className="h-full">61      <div className="p-4 space-y-2">62        <h2 className="text-sm font-semibold mb-4 text-muted-foreground uppercase tracking-wide">63          History64        </h2>65        {sessions.map((session) => (66          <Button67            key={session.sessionId}68            variant={currentSessionId === session.sessionId ? "secondary" : "ghost"}69            className="w-full justify-start text-left h-auto py-3 px-3"70            onClick={() => onLoadSession(session.sessionId)}71            data-testid={`session-${session.sessionId}`}72          >73            <div className="flex flex-col items-start w-full gap-1">74              <p className="text-sm font-medium line-clamp-2">75                {session.title}76              </p>77              <div className="flex items-center gap-1 text-xs text-muted-foreground">78                <Clock className="w-3 h-3" />79                <span>80                  {formatDistanceToNow(new Date(session.updatedAt), { addSuffix: true })}81                </span>82              </div>83            </div>84          </Button>85        ))}86      </div>87    </ScrollArea>88  );89}90