69 lines
1.8 KiB
TypeScript
69 lines
1.8 KiB
TypeScript
/**
|
|
* ChatWidget Component
|
|
* Floating button to toggle chat panel
|
|
*/
|
|
|
|
import React, { useEffect } from 'react';
|
|
import { MessageCircle, X } from 'lucide-react';
|
|
import { useChatStore } from '../../stores/chatStore';
|
|
import { ChatPanel } from './ChatPanel';
|
|
|
|
export const ChatWidget: React.FC = () => {
|
|
const { isOpen, toggleChat, loadSessions } = useChatStore();
|
|
|
|
// Load sessions on mount if authenticated
|
|
useEffect(() => {
|
|
const token = localStorage.getItem('token');
|
|
if (token) {
|
|
loadSessions().catch(err => {
|
|
console.error('Failed to load chat sessions:', err);
|
|
});
|
|
}
|
|
}, [loadSessions]);
|
|
|
|
return (
|
|
<>
|
|
{/* Floating button */}
|
|
<button
|
|
onClick={toggleChat}
|
|
className={`
|
|
fixed bottom-6 right-6 z-40
|
|
w-14 h-14
|
|
bg-gradient-to-br from-blue-500 to-purple-600
|
|
text-white
|
|
rounded-full
|
|
shadow-lg
|
|
flex items-center justify-center
|
|
transition-all duration-300
|
|
hover:scale-110
|
|
active:scale-95
|
|
focus:outline-none
|
|
focus:ring-4
|
|
focus:ring-blue-500/50
|
|
${isOpen ? 'rotate-90' : 'rotate-0'}
|
|
`}
|
|
title={isOpen ? 'Close chat' : 'Open AI Copilot'}
|
|
>
|
|
{isOpen ? (
|
|
<X className="w-6 h-6" />
|
|
) : (
|
|
<MessageCircle className="w-6 h-6" />
|
|
)}
|
|
|
|
{/* Pulse animation when closed */}
|
|
{!isOpen && (
|
|
<>
|
|
<span className="absolute inset-0 rounded-full bg-blue-500 animate-ping opacity-20" />
|
|
<span className="absolute inset-0 rounded-full bg-blue-500 animate-pulse opacity-10" />
|
|
</>
|
|
)}
|
|
</button>
|
|
|
|
{/* Chat Panel */}
|
|
<ChatPanel />
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default ChatWidget;
|