Feat/search conversation (#24)
* feat: Add conditional search input for conversation list * style and ux adjust --------- Co-authored-by: Tekle Ayele <tekleayele@gmail.com>
This commit is contained in:
		
							parent
							
								
									5da68bbdd4
								
							
						
					
					
						commit
						71a78172e6
					
				|  | @ -0,0 +1,37 @@ | ||||||
|  | import { IconX } from "@tabler/icons-react"; | ||||||
|  | import { FC } from "react"; | ||||||
|  | 
 | ||||||
|  | interface Props { | ||||||
|  |   searchTerm: string; | ||||||
|  |   onSearch: (searchTerm: string) => void; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const Search: FC<Props> = ({ searchTerm, onSearch }) => { | ||||||
|  |   const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||||||
|  |     onSearch(e.target.value); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const clearSearch = () => { | ||||||
|  |     onSearch(""); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <div className="relative flex items-center sm:pl-2 px-2 mb-2"> | ||||||
|  |       <input | ||||||
|  |         className="flex-1 pr-10 bg-[#202123] border border-neutral-600 text-sm rounded-lg px-4 py-2 text-white" | ||||||
|  |         type="text" | ||||||
|  |         placeholder="Search conversations..." | ||||||
|  |         value={searchTerm} | ||||||
|  |         onChange={handleSearchChange} | ||||||
|  |       /> | ||||||
|  | 
 | ||||||
|  |       {searchTerm && ( | ||||||
|  |         <IconX | ||||||
|  |           className="absolute right-4 text-neutral-300 cursor-pointer hover:text-neutral-400" | ||||||
|  |           size={24} | ||||||
|  |           onClick={clearSearch} | ||||||
|  |         /> | ||||||
|  |       )} | ||||||
|  |     </div> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  | @ -1,7 +1,8 @@ | ||||||
| import { Conversation } from "@/types"; | import { Conversation } from "@/types"; | ||||||
| import { IconArrowBarLeft, IconPlus } from "@tabler/icons-react"; | import { IconArrowBarLeft, IconPlus } from "@tabler/icons-react"; | ||||||
| import { FC } from "react"; | import { FC, useEffect, useState } from "react"; | ||||||
| import { Conversations } from "./Conversations"; | import { Conversations } from "./Conversations"; | ||||||
|  | import { Search } from "./Search"; | ||||||
| import { SidebarSettings } from "./SidebarSettings"; | import { SidebarSettings } from "./SidebarSettings"; | ||||||
| 
 | 
 | ||||||
| interface Props { | interface Props { | ||||||
|  | @ -20,12 +21,26 @@ interface Props { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selectedConversation, apiKey, onNewConversation, onToggleLightMode, onSelectConversation, onDeleteConversation, onToggleSidebar, onRenameConversation, onApiKeyChange }) => { | export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selectedConversation, apiKey, onNewConversation, onToggleLightMode, onSelectConversation, onDeleteConversation, onToggleSidebar, onRenameConversation, onApiKeyChange }) => { | ||||||
|  |   const [searchTerm, setSearchTerm] = useState<string>(""); | ||||||
|  |   const [filteredConversations, setFilteredConversations] = useState<Conversation[]>(conversations); | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (searchTerm) { | ||||||
|  |       setFilteredConversations(conversations.filter((conversation) => conversation.name.toLowerCase().includes(searchTerm.toLowerCase()))); | ||||||
|  |     } else { | ||||||
|  |       setFilteredConversations(conversations); | ||||||
|  |     } | ||||||
|  |   }, [searchTerm, conversations]); | ||||||
|  | 
 | ||||||
|   return ( |   return ( | ||||||
|     <div className={`flex flex-col bg-[#202123] min-w-full sm:min-w-[260px] sm:max-w-[260px] z-10`}> |     <div className={`flex flex-col bg-[#202123] min-w-full sm:min-w-[260px] sm:max-w-[260px] z-10`}> | ||||||
|       <div className="flex items-center h-[60px] sm:pl-2 px-2"> |       <div className="flex items-center h-[60px] sm:pl-2 px-2"> | ||||||
|         <button |         <button | ||||||
|           className="flex items-center w-full sm:w-[200px] h-[40px] rounded-lg bg-[#202123] border border-neutral-600 text-sm hover:bg-neutral-700" |           className="flex items-center w-full sm:w-[200px] h-[40px] rounded-lg bg-[#202123] border border-neutral-600 text-sm hover:bg-neutral-700" | ||||||
|           onClick={onNewConversation} |           onClick={() => { | ||||||
|  |             onNewConversation(); | ||||||
|  |             setSearchTerm(""); | ||||||
|  |           }} | ||||||
|         > |         > | ||||||
|           <IconPlus |           <IconPlus | ||||||
|             className="ml-4 mr-3" |             className="ml-4 mr-3" | ||||||
|  | @ -41,14 +56,27 @@ export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selected | ||||||
|         /> |         /> | ||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
|  |       {conversations.length > 1 && ( | ||||||
|  |         <Search | ||||||
|  |           searchTerm={searchTerm} | ||||||
|  |           onSearch={setSearchTerm} | ||||||
|  |         /> | ||||||
|  |       )} | ||||||
|  | 
 | ||||||
|       <div className="flex-1 overflow-auto"> |       <div className="flex-1 overflow-auto"> | ||||||
|         <Conversations |         <Conversations | ||||||
|           loading={loading} |           loading={loading} | ||||||
|           conversations={conversations} |           conversations={filteredConversations} | ||||||
|           selectedConversation={selectedConversation} |           selectedConversation={selectedConversation} | ||||||
|           onSelectConversation={onSelectConversation} |           onSelectConversation={onSelectConversation} | ||||||
|           onDeleteConversation={onDeleteConversation} |           onDeleteConversation={(conversation) => { | ||||||
|           onRenameConversation={onRenameConversation} |             onDeleteConversation(conversation); | ||||||
|  |             setSearchTerm(""); | ||||||
|  |           }} | ||||||
|  |           onRenameConversation={(conversation, name) => { | ||||||
|  |             onRenameConversation(conversation, name); | ||||||
|  |             setSearchTerm(""); | ||||||
|  |           }} | ||||||
|         /> |         /> | ||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue