Clear conversations (#53)
* Add button "Clear Conversations" * custom btn --------- Co-authored-by: Xiangxuan Liu <xiangxuan.liu@rightcapital.com>
This commit is contained in:
		
							parent
							
								
									cb0fb447a7
								
							
						
					
					
						commit
						b7803cf4ba
					
				|  | @ -0,0 +1,50 @@ | ||||||
|  | import { IconCheck, IconTrash, IconX } from "@tabler/icons-react"; | ||||||
|  | import { FC, useState } from "react"; | ||||||
|  | import { SidebarButton } from "./SidebarButton"; | ||||||
|  | 
 | ||||||
|  | interface Props { | ||||||
|  |   onClearConversations: () => void; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const ClearConversations: FC<Props> = ({ onClearConversations }) => { | ||||||
|  |   const [isConfirming, setIsConfirming] = useState<boolean>(false); | ||||||
|  | 
 | ||||||
|  |   const handleClearConversations = () => { | ||||||
|  |     onClearConversations(); | ||||||
|  |     setIsConfirming(false); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   return isConfirming ? ( | ||||||
|  |     <div className="flex hover:bg-[#343541] py-2 px-2 rounded-md cursor-pointer w-full items-center"> | ||||||
|  |       <IconTrash size={16} /> | ||||||
|  | 
 | ||||||
|  |       <div className="ml-2 flex-1 text-left text-white">Are you sure?</div> | ||||||
|  | 
 | ||||||
|  |       <div className="flex w-[40px]"> | ||||||
|  |         <IconCheck | ||||||
|  |           className="ml-auto min-w-[20px] text-neutral-400 hover:text-neutral-100" | ||||||
|  |           size={18} | ||||||
|  |           onClick={(e) => { | ||||||
|  |             e.stopPropagation(); | ||||||
|  |             handleClearConversations(); | ||||||
|  |           }} | ||||||
|  |         /> | ||||||
|  | 
 | ||||||
|  |         <IconX | ||||||
|  |           className="ml-auto min-w-[20px] text-neutral-400 hover:text-neutral-100" | ||||||
|  |           size={18} | ||||||
|  |           onClick={(e) => { | ||||||
|  |             e.stopPropagation(); | ||||||
|  |             setIsConfirming(false); | ||||||
|  |           }} | ||||||
|  |         /> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   ) : ( | ||||||
|  |     <SidebarButton | ||||||
|  |       text="Clear conversations" | ||||||
|  |       icon={<IconTrash size={16} />} | ||||||
|  |       onClick={() => setIsConfirming(true)} | ||||||
|  |     /> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | @ -18,9 +18,10 @@ interface Props { | ||||||
|   onToggleSidebar: () => void; |   onToggleSidebar: () => void; | ||||||
|   onUpdateConversation: (conversation: Conversation, data: KeyValuePair) => void; |   onUpdateConversation: (conversation: Conversation, data: KeyValuePair) => void; | ||||||
|   onApiKeyChange: (apiKey: string) => void; |   onApiKeyChange: (apiKey: string) => void; | ||||||
|  |   onClearConversations: () => void; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selectedConversation, apiKey, onNewConversation, onToggleLightMode, onSelectConversation, onDeleteConversation, onToggleSidebar, onUpdateConversation, onApiKeyChange }) => { | export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selectedConversation, apiKey, onNewConversation, onToggleLightMode, onSelectConversation, onDeleteConversation, onToggleSidebar, onUpdateConversation, onApiKeyChange, onClearConversations }) => { | ||||||
|   const [searchTerm, setSearchTerm] = useState<string>(""); |   const [searchTerm, setSearchTerm] = useState<string>(""); | ||||||
|   const [filteredConversations, setFilteredConversations] = useState<Conversation[]>(conversations); |   const [filteredConversations, setFilteredConversations] = useState<Conversation[]>(conversations); | ||||||
| 
 | 
 | ||||||
|  | @ -85,6 +86,7 @@ export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selected | ||||||
|         apiKey={apiKey} |         apiKey={apiKey} | ||||||
|         onToggleLightMode={onToggleLightMode} |         onToggleLightMode={onToggleLightMode} | ||||||
|         onApiKeyChange={onApiKeyChange} |         onApiKeyChange={onApiKeyChange} | ||||||
|  |         onClearConversations={onClearConversations} | ||||||
|       /> |       /> | ||||||
|     </div> |     </div> | ||||||
|   ); |   ); | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| import { IconMoon, IconSun } from "@tabler/icons-react"; | import { IconMoon, IconSun } from "@tabler/icons-react"; | ||||||
| import { FC } from "react"; | import { FC } from "react"; | ||||||
|  | import { ClearConversations } from "./ClearConversations"; | ||||||
| import { Key } from "./Key"; | import { Key } from "./Key"; | ||||||
| import { SidebarButton } from "./SidebarButton"; | import { SidebarButton } from "./SidebarButton"; | ||||||
| 
 | 
 | ||||||
|  | @ -8,11 +9,14 @@ interface Props { | ||||||
|   apiKey: string; |   apiKey: string; | ||||||
|   onToggleLightMode: (mode: "light" | "dark") => void; |   onToggleLightMode: (mode: "light" | "dark") => void; | ||||||
|   onApiKeyChange: (apiKey: string) => void; |   onApiKeyChange: (apiKey: string) => void; | ||||||
|  |   onClearConversations: () => void; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const SidebarSettings: FC<Props> = ({ lightMode, apiKey, onToggleLightMode, onApiKeyChange }) => { | export const SidebarSettings: FC<Props> = ({ lightMode, apiKey, onToggleLightMode, onApiKeyChange, onClearConversations }) => { | ||||||
|   return ( |   return ( | ||||||
|     <div className="flex flex-col items-center border-t border-neutral-500 px-2 py-4 text-sm space-y-2"> |     <div className="flex flex-col items-center border-t border-neutral-500 px-2 py-4 text-sm space-y-2"> | ||||||
|  |       <ClearConversations onClearConversations={onClearConversations} /> | ||||||
|  | 
 | ||||||
|       <SidebarButton |       <SidebarButton | ||||||
|         text={lightMode === "light" ? "Dark mode" : "Light mode"} |         text={lightMode === "light" ? "Dark mode" : "Light mode"} | ||||||
|         icon={lightMode === "light" ? <IconMoon size={16} /> : <IconSun size={16} />} |         icon={lightMode === "light" ? <IconMoon size={16} /> : <IconSun size={16} />} | ||||||
|  |  | ||||||
|  | @ -21,13 +21,6 @@ export default function Home() { | ||||||
|   const [messageError, setMessageError] = useState<boolean>(false); |   const [messageError, setMessageError] = useState<boolean>(false); | ||||||
|   const [modelError, setModelError] = useState<boolean>(false); |   const [modelError, setModelError] = useState<boolean>(false); | ||||||
| 
 | 
 | ||||||
|   // Close sidebar when a conversation is selected/created on mobile
 |  | ||||||
|   useEffect(() => { |  | ||||||
|     if (window.innerWidth < 640) { |  | ||||||
|       setShowSidebar(false); |  | ||||||
|     } |  | ||||||
|   }, [selectedConversation]) |  | ||||||
| 
 |  | ||||||
|   const handleSend = async (message: Message, isResend: boolean) => { |   const handleSend = async (message: Message, isResend: boolean) => { | ||||||
|     if (selectedConversation) { |     if (selectedConversation) { | ||||||
|       let updatedConversation: Conversation; |       let updatedConversation: Conversation; | ||||||
|  | @ -247,6 +240,26 @@ export default function Home() { | ||||||
|     setConversations(all); |     setConversations(all); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  |   const handleClearConversations = () => { | ||||||
|  |     setConversations([]); | ||||||
|  |     localStorage.removeItem("conversationHistory"); | ||||||
|  | 
 | ||||||
|  |     setSelectedConversation({ | ||||||
|  |       id: 1, | ||||||
|  |       name: "New conversation", | ||||||
|  |       messages: [], | ||||||
|  |       model: OpenAIModels[OpenAIModelID.GPT_3_5], | ||||||
|  |       prompt: DEFAULT_SYSTEM_PROMPT | ||||||
|  |     }); | ||||||
|  |     localStorage.removeItem("selectedConversation"); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (window.innerWidth < 640) { | ||||||
|  |       setShowSidebar(false); | ||||||
|  |     } | ||||||
|  |   }, [selectedConversation]); | ||||||
|  | 
 | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     const theme = localStorage.getItem("theme"); |     const theme = localStorage.getItem("theme"); | ||||||
|     if (theme) { |     if (theme) { | ||||||
|  | @ -329,6 +342,7 @@ export default function Home() { | ||||||
|                   onToggleSidebar={() => setShowSidebar(!showSidebar)} |                   onToggleSidebar={() => setShowSidebar(!showSidebar)} | ||||||
|                   onUpdateConversation={handleUpdateConversation} |                   onUpdateConversation={handleUpdateConversation} | ||||||
|                   onApiKeyChange={handleApiKeyChange} |                   onApiKeyChange={handleApiKeyChange} | ||||||
|  |                   onClearConversations={handleClearConversations} | ||||||
|                 /> |                 /> | ||||||
| 
 | 
 | ||||||
|                 <IconArrowBarLeft |                 <IconArrowBarLeft | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue