diff --git a/src/components/ChatItem.tsx b/src/components/ChatItem.tsx
new file mode 100644
index 0000000..9a901a8
--- /dev/null
+++ b/src/components/ChatItem.tsx
@@ -0,0 +1,88 @@
+import { ActionIcon, Flex, Menu } from "@mantine/core";
+import {
+ IconDotsVertical,
+ IconMessages,
+ IconPencil,
+ IconPin,
+ IconPinned,
+ IconPinnedOff,
+ IconTrash
+} from "@tabler/icons-react";
+import { Link } from "@tanstack/react-location";
+import { Chat, db } from "../db";
+import { DeleteChatModal } from "./DeleteChatModal";
+import { EditChatModal } from "./EditChatModal";
+import { MainLink } from "./MainLink";
+import { notifications } from "@mantine/notifications";
+
+export function ChatItem({ chat, isActive }: { chat: Chat, isActive: boolean }) {
+ const toggleChatPin = async (chatId: string, event: React.UIEvent) => {
+ try {
+ event.preventDefault();
+ await db.chats.where({ id: chatId }).modify((chat) => {
+ chat.pinned = !chat.pinned;
+ });
+ } catch (error: any) {
+ if (error.toJSON().message === "Network Error") {
+ notifications.show({
+ title: "Error",
+ color: "red",
+ message: "No internet connection.",
+ });
+ }
+ const message = error.response?.data?.error?.message;
+ if (message) {
+ notifications.show({
+ title: "Error",
+ color: "red",
+ message,
+ });
+ }
+ }
+ };
+
+ return (
+ ({
+ marginTop: 1,
+ "&:hover, &.active": {
+ backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[6] : theme.colors.gray[1],
+ },
+ })}
+ >
+
+ : }
+ color="teal"
+ chat={chat}
+ label={chat.description}
+ />
+
+
+
+ )
+}
diff --git a/src/components/Chats.tsx b/src/components/Chats.tsx
index 5f15bf0..0fc6bd4 100644
--- a/src/components/Chats.tsx
+++ b/src/components/Chats.tsx
@@ -1,13 +1,9 @@
-import { ActionIcon, Flex, Menu } from "@mantine/core";
-import { IconDotsVertical, IconMessages } from "@tabler/icons-react";
-import { Link } from "@tanstack/react-location";
+import { Text } from "@mantine/core";
import { useLiveQuery } from "dexie-react-hooks";
import { useMemo } from "react";
import { db } from "../db";
import { useChatId } from "../hooks/useChatId";
-import { DeleteChatModal } from "./DeleteChatModal";
-import { EditChatModal } from "./EditChatModal";
-import { MainLink } from "./MainLink";
+import { ChatItem } from "./ChatItem";
export function Chats({ search }: { search: string }) {
const chatId = useChatId();
@@ -23,47 +19,25 @@ export function Chats({ search }: { search: string }) {
[chats, search]
);
+ const pinnedChats = useMemo(() => filteredChats.filter((chat) => chat.pinned), [filteredChats]);
+ const unpinnedChats = useMemo(() => filteredChats.filter((chat) => !chat.pinned), [filteredChats]);
+
return (
<>
- {filteredChats.map((chat) => (
- ({
- marginTop: 1,
- "&:hover, &.active": {
- backgroundColor:
- theme.colorScheme === "dark"
- ? theme.colors.dark[6]
- : theme.colors.gray[1],
- },
- })}
- >
-
- }
- color="teal"
- chat={chat}
- label={chat.description}
- />
-
-
-
+ {pinnedChats.length > 0 ? (
+ <>
+
+ {pinnedChats.map((chat) => (
+
+ ))}
+
+ {unpinnedChats.length > 0 ? : null}
+ >
+ ) : null}
+
+ {unpinnedChats.map((chat) => (
+
))}
>
- );
+ )
}
diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx
index 3c39330..03297b6 100644
--- a/src/components/Layout.tsx
+++ b/src/components/Layout.tsx
@@ -140,6 +140,7 @@ export function Layout() {
description: "New Chat",
totalTokens: 0,
createdAt: new Date(),
+ pinned: false,
});
navigate({ to: `/chats/${id}` });
}}
diff --git a/src/components/Prompts.tsx b/src/components/Prompts.tsx
index b2fa622..78beb3e 100644
--- a/src/components/Prompts.tsx
+++ b/src/components/Prompts.tsx
@@ -91,6 +91,7 @@ export function Prompts({
description: "New Chat",
totalTokens: 0,
createdAt: new Date(),
+ pinned: false,
});
await db.messages.add({
id: nanoid(),
diff --git a/src/db/index.ts b/src/db/index.ts
index f4f1288..9e5e9ad 100644
--- a/src/db/index.ts
+++ b/src/db/index.ts
@@ -7,6 +7,7 @@ export interface Chat {
description: string;
totalTokens: number;
createdAt: Date;
+ pinned: boolean;
}
export interface Message {