|
|
import React, { useState } from 'react'; |
|
|
import { Chat } from '../types'; |
|
|
import { MessageSquarePlus, MessageSquare, Trash2, Moon, Sun, PanelLeftClose, PanelLeft, Search } from 'lucide-react'; |
|
|
import { useTheme } from '../contexts/ThemeContext'; |
|
|
|
|
|
interface SidebarProps { |
|
|
chats: Chat[]; |
|
|
currentChatId: string | null; |
|
|
onSelectChat: (chatId: string) => void; |
|
|
onNewChat: () => void; |
|
|
onDeleteChat: (chatId: string) => void; |
|
|
isCollapsed: boolean; |
|
|
onToggleCollapse: () => void; |
|
|
} |
|
|
|
|
|
export const Sidebar: React.FC<SidebarProps> = ({ |
|
|
chats, |
|
|
currentChatId, |
|
|
onSelectChat, |
|
|
onNewChat, |
|
|
onDeleteChat, |
|
|
isCollapsed, |
|
|
onToggleCollapse |
|
|
}) => { |
|
|
const { theme, toggleTheme } = useTheme(); |
|
|
const [searchQuery, setSearchQuery] = useState(''); |
|
|
const [isSearchOpen, setIsSearchOpen] = useState(false); |
|
|
const searchInputRef = React.useRef<HTMLInputElement>(null); |
|
|
|
|
|
|
|
|
const filteredChats = chats.filter(chat => |
|
|
chat.title.toLowerCase().includes(searchQuery.toLowerCase()) |
|
|
); |
|
|
|
|
|
|
|
|
React.useEffect(() => { |
|
|
if (isSearchOpen && searchInputRef.current) { |
|
|
searchInputRef.current.focus(); |
|
|
} |
|
|
}, [isSearchOpen]); |
|
|
|
|
|
return ( |
|
|
<div className={`${isCollapsed ? 'w-14' : 'w-72'} bg-gray-900 dark:bg-gray-100 border-r border-gray-800 dark:border-gray-300 flex flex-col h-screen transition-all duration-300`}> |
|
|
{/* Header */} |
|
|
<div className="p-2 space-y-1"> |
|
|
{!isCollapsed ? ( |
|
|
<> |
|
|
<button |
|
|
onClick={onToggleCollapse} |
|
|
className="w-full flex items-center px-3 py-2 text-gray-400 dark:text-gray-600 hover:text-gray-200 dark:hover:text-gray-900 hover:bg-gray-800 dark:hover:bg-gray-200 rounded-lg transition-all" |
|
|
title="Sidebar'ı Daralt" |
|
|
> |
|
|
<PanelLeftClose size={18} /> |
|
|
</button> |
|
|
<button |
|
|
onClick={onNewChat} |
|
|
className="w-full flex items-center gap-2 px-3 py-2.5 text-gray-200 dark:text-gray-900 hover:bg-gray-800 dark:hover:bg-gray-200 rounded-lg transition-all font-medium text-sm" |
|
|
> |
|
|
<MessageSquarePlus size={18} /> |
|
|
<span>Yeni sohbet</span> |
|
|
</button> |
|
|
{/* Search Input */} |
|
|
{!isSearchOpen ? ( |
|
|
<button |
|
|
onClick={() => setIsSearchOpen(true)} |
|
|
className="w-full flex items-center gap-2 px-3 py-2 text-gray-400 dark:text-gray-600 hover:text-gray-200 dark:hover:text-gray-900 hover:bg-gray-800 dark:hover:bg-gray-200 rounded-lg transition-all text-sm" |
|
|
> |
|
|
<Search size={18} /> |
|
|
<span>Sohbet ara</span> |
|
|
</button> |
|
|
) : ( |
|
|
<div className="relative"> |
|
|
<Search size={16} className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 dark:text-gray-600" /> |
|
|
<input |
|
|
ref={searchInputRef} |
|
|
type="text" |
|
|
placeholder="Sohbet ara..." |
|
|
value={searchQuery} |
|
|
onChange={(e) => setSearchQuery(e.target.value)} |
|
|
onBlur={() => { |
|
|
if (!searchQuery) { |
|
|
setIsSearchOpen(false); |
|
|
} |
|
|
}} |
|
|
className="w-full pl-9 pr-3 py-2 bg-gray-800 dark:bg-gray-200 text-gray-200 dark:text-gray-900 placeholder-gray-500 dark:placeholder-gray-600 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-600 dark:focus:ring-gray-400 transition-all" |
|
|
/> |
|
|
</div> |
|
|
)} |
|
|
</> |
|
|
) : ( |
|
|
<> |
|
|
<button |
|
|
onClick={onToggleCollapse} |
|
|
className="w-full flex items-center justify-center py-2.5 text-gray-400 dark:text-gray-600 hover:text-gray-200 dark:hover:text-gray-900 hover:bg-gray-800 dark:hover:bg-gray-200 rounded-lg transition-all" |
|
|
title="Sidebar'ı Genişlet" |
|
|
> |
|
|
<PanelLeft size={20} /> |
|
|
</button> |
|
|
<button |
|
|
onClick={onNewChat} |
|
|
className="w-full flex items-center justify-center py-2.5 text-gray-200 dark:text-gray-900 hover:bg-gray-800 dark:hover:bg-gray-200 rounded-lg transition-all" |
|
|
title="Yeni sohbet" |
|
|
> |
|
|
<MessageSquarePlus size={20} /> |
|
|
</button> |
|
|
</> |
|
|
)} |
|
|
</div> |
|
|
|
|
|
{} |
|
|
<div className="flex-1 overflow-y-auto px-2"> |
|
|
{chats.length === 0 ? ( |
|
|
!isCollapsed && ( |
|
|
<div className="p-6 text-center"> |
|
|
<MessageSquare size={32} className="mx-auto mb-3 text-gray-600 dark:text-gray-400" /> |
|
|
<p className="text-sm text-gray-400 dark:text-gray-600">Henüz sohbet yok</p> |
|
|
</div> |
|
|
) |
|
|
) : filteredChats.length === 0 ? ( |
|
|
!isCollapsed && ( |
|
|
<div className="p-6 text-center"> |
|
|
<Search size={32} className="mx-auto mb-3 text-gray-600 dark:text-gray-400" /> |
|
|
<p className="text-sm text-gray-400 dark:text-gray-600">Sonuç bulunamadı</p> |
|
|
</div> |
|
|
) |
|
|
) : ( |
|
|
<div className="space-y-1"> |
|
|
{filteredChats.map((chat) => ( |
|
|
<div |
|
|
key={chat.id} |
|
|
className={`group relative flex items-center ${isCollapsed ? 'justify-center py-2.5' : 'gap-2 px-3 py-2'} rounded-lg cursor-pointer transition-all ${ |
|
|
currentChatId === chat.id |
|
|
? 'bg-gray-800 dark:bg-gray-200' |
|
|
: 'hover:bg-gray-800 dark:hover:bg-gray-200' |
|
|
}`} |
|
|
onClick={() => onSelectChat(chat.id)} |
|
|
title={isCollapsed ? chat.title : ''} |
|
|
> |
|
|
<MessageSquare |
|
|
size={isCollapsed ? 20 : 16} |
|
|
className={`flex-shrink-0 ${ |
|
|
currentChatId === chat.id |
|
|
? 'text-gray-200 dark:text-gray-900' |
|
|
: 'text-gray-400 dark:text-gray-600' |
|
|
}`} |
|
|
/> |
|
|
{!isCollapsed && ( |
|
|
<> |
|
|
<div className="flex-1 min-w-0"> |
|
|
<p className="text-sm truncate text-gray-200 dark:text-gray-900"> |
|
|
{chat.title} |
|
|
</p> |
|
|
</div> |
|
|
<button |
|
|
onClick={(e) => { |
|
|
e.stopPropagation(); |
|
|
onDeleteChat(chat.id); |
|
|
}} |
|
|
className="opacity-0 group-hover:opacity-100 p-1 hover:bg-gray-700 dark:hover:bg-gray-300 text-gray-400 dark:text-gray-600 rounded transition-all" |
|
|
> |
|
|
<Trash2 size={14} /> |
|
|
</button> |
|
|
</> |
|
|
)} |
|
|
</div> |
|
|
))} |
|
|
</div> |
|
|
)} |
|
|
</div> |
|
|
|
|
|
{} |
|
|
<div className="p-2 border-t border-gray-800 dark:border-gray-300"> |
|
|
<button |
|
|
onClick={toggleTheme} |
|
|
className={`w-full flex items-center ${isCollapsed ? 'justify-center py-2.5' : 'gap-2 px-3 py-2'} text-sm text-gray-400 dark:text-gray-600 hover:text-gray-200 dark:hover:text-gray-900 hover:bg-gray-800 dark:hover:bg-gray-200 rounded-lg transition-colors`} |
|
|
title={isCollapsed ? (theme === 'light' ? 'Karanlık tema' : 'Aydınlık tema') : ''} |
|
|
> |
|
|
{theme === 'light' ? ( |
|
|
<> |
|
|
<Moon size={isCollapsed ? 20 : 16} /> |
|
|
{!isCollapsed && <span>Karanlık tema</span>} |
|
|
</> |
|
|
) : ( |
|
|
<> |
|
|
<Sun size={isCollapsed ? 20 : 16} /> |
|
|
{!isCollapsed && <span>Aydınlık tema</span>} |
|
|
</> |
|
|
)} |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
); |
|
|
}; |
|
|
|