UnivAi / src /components /Message.tsx
oceddyyy's picture
Upload 59 files
13a0af9 verified
import { useState } from 'react';
import { motion } from 'motion/react';
import { Bot, User, Crown, Sparkles, MessageSquare } from 'lucide-react';
import { Button } from './ui/button';
import { FeedbackPopup } from './FeedbackPopup';
export interface MessageProps {
content: string;
isUser: boolean;
timestamp: Date;
isPlusResponse?: boolean;
isUnivAiPlusMode?: boolean;
}
export function Message({ content, isUser, timestamp, isPlusResponse, isUnivAiPlusMode }: MessageProps) {
const [showFeedback, setShowFeedback] = useState(false);
return (
<>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
className={`flex items-start gap-3 mb-4 ${isUser ? 'flex-row-reverse' : 'flex-row'}`}
>
<div className={`
flex-shrink-0 w-10 h-10 rounded-full flex items-center justify-center relative transition-all duration-300
${isUser
? isUnivAiPlusMode
? 'bg-gradient-to-r from-purple-500 to-purple-600 text-white shadow-lg shadow-purple-500/30'
: 'bg-gradient-to-r from-red-500 to-red-600 text-white shadow-lg shadow-red-500/30'
: isPlusResponse
? 'bg-gradient-to-r from-purple-400 to-pink-500 text-white shadow-lg shadow-purple-500/30'
: isUnivAiPlusMode
? 'bg-gradient-to-r from-purple-400 to-pink-500 text-white shadow-lg shadow-purple-500/30'
: 'bg-gradient-to-r from-yellow-400 to-orange-500 text-white shadow-lg shadow-yellow-500/30'
}
`}>
{isUser ? (
<User size={20} />
) : isPlusResponse ? (
<Crown size={20} />
) : isUnivAiPlusMode ? (
<Crown size={20} />
) : (
<Bot size={20} />
)}
{/* Premium indicator sparkle */}
{isPlusResponse && (
<motion.div
initial={{ scale: 0, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
className="absolute -top-1 -right-1 w-4 h-4 bg-gradient-to-r from-amber-400 to-yellow-500 rounded-full flex items-center justify-center"
>
<Sparkles size={10} className="text-white" />
</motion.div>
)}
</div>
<div className={`flex flex-col max-w-[70%] ${isUser ? 'items-end' : 'items-start'}`}>
{/* Premium response indicator - moved outside and above the message bubble */}
{isPlusResponse && (
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
className="flex items-center gap-1 px-3 py-1 mb-2 bg-gradient-to-r from-purple-500 to-pink-500 text-white text-xs rounded-full shadow-lg mr-4"
>
<Crown size={12} />
<span>Premium Response</span>
</motion.div>
)}
<div className={`
px-4 py-3 rounded-2xl backdrop-blur-sm border shadow-sm transition-all duration-300 relative
${isUser
? isUnivAiPlusMode
? 'bg-gradient-to-r from-purple-50 to-purple-100 border-purple-200 text-purple-900 ml-4'
: 'bg-gradient-to-r from-red-50 to-red-100 border-red-200 text-red-900 ml-4'
: isPlusResponse
? 'bg-gradient-to-r from-purple-50 via-pink-50 to-amber-50 border-purple-300 text-purple-900 mr-4 shadow-lg shadow-purple-200/50'
: isUnivAiPlusMode
? 'bg-gradient-to-r from-white to-purple-50 border-purple-200 text-purple-900 mr-4'
: 'bg-gradient-to-r from-white to-yellow-50 border-yellow-200 text-red-900 mr-4'
}
`}>
<p className="whitespace-pre-wrap">
{content}
</p>
</div>
<div className={`flex items-center gap-2 mt-1 px-2 ${isUser ? 'flex-row-reverse' : 'flex-row'}`}>
<span className={`text-xs transition-all duration-300 ${
isUnivAiPlusMode
? 'text-purple-600/60'
: 'text-red-600/60'
}`}>
{timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
{isPlusResponse && <span className="ml-2 text-purple-600/80">• Premium</span>}
</span>
{/* Feedback button for bot responses */}
{!isUser && (
<Button
variant="ghost"
size="sm"
onClick={() => setShowFeedback(true)}
className={`text-xs p-1 h-6 transition-all duration-300 opacity-60 hover:opacity-100 ${
isUnivAiPlusMode
? 'hover:bg-purple-100 text-purple-600 dark:hover:bg-purple-900/30 dark:text-purple-400'
: 'hover:bg-red-100 text-red-600 dark:hover:bg-red-900/30 dark:text-red-400'
}`}
>
<MessageSquare size={12} />
</Button>
)}
</div>
</div>
</motion.div>
{/* Feedback Popup */}
<FeedbackPopup
isOpen={showFeedback}
onClose={() => setShowFeedback(false)}
messageId={`msg-${timestamp.getTime()}`}
isUnivAiPlusMode={isUnivAiPlusMode}
/>
</>
);
}