diff --git a/src/components/ConnectionSidebar.tsx b/src/components/ConnectionSidebar.tsx
index 8f89d96..cce2a12 100644
--- a/src/components/ConnectionSidebar.tsx
+++ b/src/components/ConnectionSidebar.tsx
@@ -203,6 +203,7 @@ const ConnectionSidebar = () => {
)
))}
+ {/* TODO(steven): remove this after we finish left sidebar */}
diff --git a/src/components/ConversationTabsView.tsx b/src/components/ConversationTabsView.tsx
new file mode 100644
index 0000000..eec3333
--- /dev/null
+++ b/src/components/ConversationTabsView.tsx
@@ -0,0 +1,131 @@
+import { useState } from "react";
+import { useTranslation } from "react-i18next";
+import { useConnectionStore, useConversationStore, useLayoutStore } from "@/store";
+import { Conversation } from "@/types";
+import Icon from "./Icon";
+import Dropdown, { DropdownItem } from "./kit/Dropdown";
+import UpdateConversationModal from "./UpdateConversationModal";
+
+interface ConversationTabProps {
+ conversation: Conversation;
+ selected: boolean;
+ onClick: (conversation: Conversation) => void;
+ onEdit: (conversation: Conversation) => void;
+ onDelete: (conversation: Conversation) => void;
+}
+
+const ConversationTab = (props: ConversationTabProps) => {
+ const { conversation, selected, onClick, onEdit, onDelete } = props;
+ const { t } = useTranslation();
+
+ return (
+
onClick(conversation)}
+ >
+
{conversation.title}
+
+
+
+ }
+ >
+
+ onEdit(conversation)}
+ >
+
+ {t("common.edit")}
+
+ onDelete(conversation)}
+ >
+
+ {t("common.delete")}
+
+
+
+
+ );
+};
+
+const ConversationTabsView = () => {
+ const { t } = useTranslation();
+ const layoutStore = useLayoutStore();
+ const connectionStore = useConnectionStore();
+ const conversationStore = useConversationStore();
+ const [updateConversationModalContext, setUpdateConversationModalContext] = useState
(undefined);
+ const currentConnectionCtx = connectionStore.currentConnectionCtx;
+ const conversationList = conversationStore.conversationList.filter(
+ (conversation) =>
+ conversation.connectionId === currentConnectionCtx?.connection.id &&
+ conversation.databaseName === currentConnectionCtx?.database?.name
+ );
+
+ const handleCreateConversation = () => {
+ if (!currentConnectionCtx) {
+ conversationStore.createConversation();
+ } else {
+ conversationStore.createConversation(currentConnectionCtx.connection.id, currentConnectionCtx.database?.name);
+ }
+ };
+
+ const handleConversationClick = (conversation: Conversation) => {
+ conversationStore.setCurrentConversationId(conversation.id);
+ if (layoutStore.isMobileView) {
+ layoutStore.toggleSidebar(false);
+ }
+ };
+
+ const handleEditConversation = (conversation: Conversation) => {
+ setUpdateConversationModalContext(conversation);
+ };
+
+ const handleDeleteConversation = (conversation: Conversation) => {
+ conversationStore.clearConversation((item) => item.id !== conversation.id);
+ if (conversationStore.currentConversationId === conversation.id) {
+ conversationStore.setCurrentConversationId(undefined);
+ }
+ };
+
+ return (
+ <>
+
+
+ {conversationList.map((conversation) => {
+ return (
+
+ );
+ })}
+
+
0 && "ml-2"}`}>
+
+
+
+
+ {updateConversationModalContext && (
+ setUpdateConversationModalContext(undefined)} conversation={updateConversationModalContext} />
+ )}
+ >
+ );
+};
+
+export default ConversationTabsView;
diff --git a/src/components/ConversationView/Header.tsx b/src/components/ConversationView/Header.tsx
index 8145bc2..b8b7e65 100644
--- a/src/components/ConversationView/Header.tsx
+++ b/src/components/ConversationView/Header.tsx
@@ -5,6 +5,7 @@ import { hasFeature } from "@/utils";
import Icon from "../Icon";
import GitHubStarBadge from "../GitHubStarBadge";
import SchemaDrawer from "../SchemaDrawer";
+import ConversationTabsView from "../ConversationTabsView";
interface Props {
className?: string;
@@ -25,36 +26,41 @@ const Header = (props: Props) => {
return (
<>
-
-
-
- {title}
-
-
-
{title}
-
-
-
-
- {hasFeature("debug") && (
-