File size: 4,160 Bytes
5fc68b0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136f9cf
5fc68b0
 
 
 
 
136f9cf
 
5fc68b0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136f9cf
5fc68b0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12621bc
 
136f9cf
5fc68b0
12621bc
5fc68b0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// src/components/sidebar/app-sidebar.tsx
import {
  Sidebar,
  SidebarContent,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarMenu,
  SidebarMenuItem,
  SidebarMenuButton,
  SidebarHeader,
} from "@/components/ui/sidebar";
import { routes } from "@/routes";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { MessageSquare, Plus, Trash2 } from "lucide-react";
import { Button } from "../ui/button";
import { useLiveQuery } from "dexie-react-hooks";
import { ChatHistoryDB } from "@/lib/chat/memory";
import { useState } from "react";
import { toast } from "sonner";
import { IChatSession } from "@/lib/chat/types";

export function AppSidebar() {
  const location = useLocation();
  const navigate = useNavigate();
  const chats = useLiveQuery(async () => {
    const sessions = await ChatHistoryDB.getInstance().sessions.toArray();
    return sessions.sort((a: IChatSession, b: IChatSession) => b.updatedAt - a.updatedAt);
  });
  const [hoveringId, setHoveringId] = useState<string | null>(null);

  return (
    <Sidebar>
      <SidebarHeader className="flex flex-row items-center justify-between border-b">
        <span className="text-lg font-bold">Sheer</span>
        <Link to="/chat/new">
          <Button variant="ghost" size="icon">
            <Plus />
          </Button>
        </Link>
      </SidebarHeader>
      <SidebarContent className="gap-0">
        <SidebarGroup>
          <SidebarGroupLabel>Application</SidebarGroupLabel>
          <SidebarGroupContent>
            <SidebarMenu>
              {routes.map((route) => (
                <SidebarMenuItem key={route.path}>
                  <SidebarMenuButton
                    asChild
                    isActive={location.pathname === route.path}
                  >
                    <Link to={route.path}>
                      {route.icon}
                      <span>{route.label}</span>
                    </Link>
                  </SidebarMenuButton>
                </SidebarMenuItem>
              ))}
            </SidebarMenu>
          </SidebarGroupContent>
        </SidebarGroup>
        <SidebarGroup>
          <SidebarGroupLabel>Chats</SidebarGroupLabel>
          <SidebarGroupContent>
            <SidebarMenu>
              {chats?.map((chat: IChatSession) => (
                <SidebarMenuItem key={chat.id}>
                    <SidebarMenuButton
                      asChild
                      isActive={location.pathname === `/chat/${chat.id}`}
                      className="flex flex-row items-center justify-between overflow-hidden"
                      onMouseEnter={() => setHoveringId(chat.id)}
                      onMouseLeave={() => setHoveringId(null)}
                    >
                      <Link to={`/chat/${chat.id}`} className="flex w-full items-center">
                        <div className="flex min-w-0 flex-1 items-center gap-2">
                          <MessageSquare className="h-4 w-4 shrink-0" />
                          <span className="truncate">{chat.name}</span>
                        </div>
                        <button 
                          className={`ml-2 shrink-0 transition-transform duration-200 hover:text-destructive ${
                            hoveringId === chat.id || location.pathname === `/chat/${chat.id}` 
                              ? 'translate-x-0' 
                              : 'translate-x-[200%]'
                          }`}
                          onClick={(e) => {
                            e.preventDefault();
                            ChatHistoryDB.getInstance().sessions.delete(chat.id);
                            toast.success("Chat deleted");
                            return navigate("/chat/new");
                          }}
                        >
                          <Trash2 className="h-4 w-4" />
                        </button>
                      </Link>
                    </SidebarMenuButton>
                </SidebarMenuItem>
              ))}
            </SidebarMenu>
          </SidebarGroupContent>
        </SidebarGroup>
      </SidebarContent>
    </Sidebar>
  );
}