Spaces:
Runtime error
Runtime error
File size: 4,724 Bytes
0971cc4 |
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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
"use client";
import { useEffect, useState } from "react";
import { Pencil2Icon } from "@radix-ui/react-icons";
import { Message } from "ai/react";
import Image from "next/image";
import OllamaLogo from "../../public/ollama.png";
import { ChatOptions } from "./chat/chat-options";
import SidebarTabs from "./sidebar-tabs";
import Link from "next/link";
interface SidebarProps {
isCollapsed: boolean;
onClick?: () => void;
isMobile: boolean;
chatId: string;
setChatId: React.Dispatch<React.SetStateAction<string>>;
chatOptions: ChatOptions;
setChatOptions: React.Dispatch<React.SetStateAction<ChatOptions>>;
}
interface Chats {
[key: string]: { chatId: string; messages: Message[] }[];
}
export function Sidebar({
isCollapsed,
isMobile,
chatId,
setChatId,
chatOptions,
setChatOptions,
}: SidebarProps) {
const [localChats, setLocalChats] = useState<Chats>({});
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
setLocalChats(getLocalstorageChats());
const handleStorageChange = () => {
setLocalChats(getLocalstorageChats());
};
window.addEventListener("storage", handleStorageChange);
return () => {
window.removeEventListener("storage", handleStorageChange);
};
}, [chatId]);
const getLocalstorageChats = (): Chats => {
const chats = Object.keys(localStorage).filter((key) =>
key.startsWith("chat_")
);
if (chats.length === 0) {
setIsLoading(false);
}
// Map through the chats and return an object with chatId and messages
const chatObjects = chats.map((chat) => {
const item = localStorage.getItem(chat);
return item
? { chatId: chat, messages: JSON.parse(item) }
: { chatId: "", messages: [] };
});
// Sort chats by the createdAt date of the first message of each chat
chatObjects.sort((a, b) => {
const aDate = new Date(a.messages[0].createdAt);
const bDate = new Date(b.messages[0].createdAt);
return bDate.getTime() - aDate.getTime();
});
const groupChatsByDate = (
chats: { chatId: string; messages: Message[] }[]
) => {
const today = new Date();
const yesterday = new Date(today);
yesterday.setDate(yesterday.getDate() - 1);
const groupedChats: Chats = {};
chats.forEach((chat) => {
const createdAt = new Date(chat.messages[0].createdAt ?? "");
const diffInDays = Math.floor(
(today.getTime() - createdAt.getTime()) / (1000 * 3600 * 24)
);
let group: string;
if (diffInDays === 0) {
group = "Today";
} else if (diffInDays === 1) {
group = "Yesterday";
} else if (diffInDays <= 7) {
group = "Previous 7 Days";
} else if (diffInDays <= 30) {
group = "Previous 30 Days";
} else {
group = "Older";
}
if (!groupedChats[group]) {
groupedChats[group] = [];
}
groupedChats[group].push(chat);
});
return groupedChats;
};
setIsLoading(false);
const groupedChats = groupChatsByDate(chatObjects);
return groupedChats;
};
const handleDeleteChat = (chatId: string) => {
localStorage.removeItem(chatId);
setLocalChats(getLocalstorageChats());
};
return (
<div
data-collapsed={isCollapsed}
className="relative justify-between group bg-accent/20 dark:bg-card/35 flex flex-col h-full gap-4 data-[collapsed=true]:p-0 data-[collapsed=true]:hidden"
>
<div className="sticky left-0 right-0 top-0 z-20 p-1 rounded-sm m-2">
<Link
className="flex w-full h-10 text-sm font-medium items-center
border border-input bg-background hover:bg-accent hover:text-accent-foreground
px-2 py-2 rounded-sm"
href="/"
onClick={() => {
setChatId("");
}}
>
<div className="flex gap-3 p-2 items-center justify-between w-full">
<div className="flex align-start gap-2">
{!isCollapsed && !isMobile && (
<Image
src={OllamaLogo}
alt="AI"
width={14}
height={14}
className="dark:invert 2xl:block"
/>
)}
<span>New chat</span>
</div>
<Pencil2Icon className="w-4 h-4" />
</div>
</Link>
</div>
<SidebarTabs
isLoading={isLoading}
localChats={localChats}
selectedChatId={chatId}
chatOptions={chatOptions}
setChatOptions={setChatOptions}
handleDeleteChat={handleDeleteChat}
/>
</div>
);
}
|