“vinit5112”
Add all code
deb090d
import React from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
PlusIcon,
XMarkIcon,
ChatBubbleLeftIcon,
TrashIcon,
HomeIcon
} from '@heroicons/react/24/outline';
const Sidebar = ({
open,
onClose,
conversations,
activeConversationId,
onConversationSelect,
onNewChat,
onDeleteConversation,
onBackToHome,
darkMode
}) => {
const formatDate = (date) => {
const now = new Date();
const messageDate = new Date(date);
const diffTime = Math.abs(now - messageDate);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
if (diffDays === 1) return 'Today';
if (diffDays === 2) return 'Yesterday';
if (diffDays <= 7) return `${diffDays} days ago`;
return messageDate.toLocaleDateString();
};
const sidebarVariants = {
open: {
x: 0,
transition: {
type: "spring",
stiffness: 300,
damping: 30
}
},
closed: {
x: -280,
transition: {
type: "spring",
stiffness: 300,
damping: 30
}
}
};
const overlayVariants = {
open: { opacity: 1 },
closed: { opacity: 0 }
};
return (
<>
{/* Mobile Overlay */}
<AnimatePresence>
{open && (
<motion.div
variants={overlayVariants}
initial="closed"
animate="open"
exit="closed"
className="fixed inset-0 bg-black bg-opacity-50 z-40 md:hidden"
onClick={onClose}
/>
)}
</AnimatePresence>
{/* Sidebar */}
<motion.aside
variants={sidebarVariants}
initial="closed"
animate={open ? "open" : "closed"}
className={`fixed left-0 top-16 h-[calc(100vh-4rem)] w-64 z-50 ${
darkMode
? 'bg-gray-900 border-gray-700'
: 'bg-white border-gray-200'
} border-r shadow-lg flex flex-col`}
>
{/* Header */}
<div className="p-4 border-b border-gray-200 dark:border-gray-700">
<div className="flex items-center justify-between mb-4">
<h2 className="font-semibold text-lg">Conversations</h2>
<button
onClick={onClose}
className={`p-1 rounded-lg transition-colors md:hidden ${
darkMode
? 'hover:bg-gray-800 text-gray-400'
: 'hover:bg-gray-100 text-gray-500'
}`}
>
<XMarkIcon className="w-5 h-5" />
</button>
</div>
<div className="space-y-2">
<motion.button
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
onClick={onNewChat}
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg transition-colors ${
darkMode
? 'bg-gray-800 hover:bg-gray-700 text-white border-gray-600'
: 'bg-gray-50 hover:bg-gray-100 text-gray-900 border-gray-300'
} border`}
>
<PlusIcon className="w-4 h-4" />
<span className="font-medium">New Chat</span>
</motion.button>
<motion.button
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
onClick={onBackToHome}
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg transition-colors ${
darkMode
? 'bg-primary-600 hover:bg-primary-700 text-white'
: 'bg-primary-50 hover:bg-primary-100 text-primary-900 border-primary-300'
} border`}
>
<HomeIcon className="w-4 h-4" />
<span className="font-medium">Back to Home</span>
</motion.button>
</div>
</div>
{/* Conversations List */}
<div className="flex-1 overflow-y-auto p-2">
{conversations.length === 0 ? (
<div className={`text-center py-8 ${
darkMode ? 'text-gray-500' : 'text-gray-400'
}`}>
<ChatBubbleLeftIcon className="w-12 h-12 mx-auto mb-3 opacity-50" />
<p className="text-sm">No conversations yet</p>
<p className="text-xs mt-1">Start a new chat to begin</p>
</div>
) : (
<div className="space-y-1">
{conversations.map((conversation) => (
<motion.button
key={conversation.id}
whileHover={{ x: 4 }}
onClick={() => {
onConversationSelect(conversation.id);
onClose();
}}
className={`w-full text-left p-3 rounded-lg transition-all group ${
activeConversationId === conversation.id
? darkMode
? 'bg-primary-600 text-white'
: 'bg-primary-50 text-primary-900 border-primary-200'
: darkMode
? 'hover:bg-gray-800 text-gray-300'
: 'hover:bg-gray-50 text-gray-700'
}`}
>
<div className="flex items-start justify-between">
<div className="flex-1 min-w-0">
<p className="font-medium truncate text-sm">
{conversation.title}
</p>
<p className={`text-xs mt-1 ${
activeConversationId === conversation.id
? 'text-primary-200'
: darkMode
? 'text-gray-500'
: 'text-gray-500'
}`}>
{formatDate(conversation.createdAt)}
</p>
</div>
<button
onClick={(e) => {
e.stopPropagation();
if (window.confirm('Are you sure you want to delete this conversation?')) {
onDeleteConversation(conversation.id);
}
}}
className={`opacity-0 group-hover:opacity-100 p-1 rounded transition-opacity ${
darkMode
? 'hover:bg-gray-700 text-gray-400'
: 'hover:bg-gray-200 text-gray-500'
}`}
>
<TrashIcon className="w-4 h-4" />
</button>
</div>
</motion.button>
))}
</div>
)}
</div>
{/* Footer */}
<div className={`p-4 border-t ${
darkMode ? 'border-gray-700' : 'border-gray-200'
}`}>
<div className={`text-xs ${
darkMode ? 'text-gray-500' : 'text-gray-400'
}`}>
<p>CA Study Assistant v2.0</p>
<p className="mt-1">Powered by AI</p>
</div>
</div>
</motion.aside>
</>
);
};
export default Sidebar;