UnivAi / src /components /FeedbackPopup.tsx
oceddyyy's picture
Upload 59 files
13a0af9 verified
import { useState } from 'react';
import { motion, AnimatePresence } from 'motion/react';
import { ThumbsUp, ThumbsDown, X, MessageSquare } from 'lucide-react';
import { Button } from './ui/button';
import { Textarea } from './ui/textarea';
interface FeedbackPopupProps {
isOpen: boolean;
onClose: () => void;
messageId: string;
isUnivAiPlusMode?: boolean;
}
export function FeedbackPopup({ isOpen, onClose, messageId, isUnivAiPlusMode }: FeedbackPopupProps) {
const [feedbackType, setFeedbackType] = useState<'positive' | 'negative' | null>(null);
const [comment, setComment] = useState('');
const [isSubmitted, setIsSubmitted] = useState(false);
const handleSubmit = () => {
// Here you would typically send feedback to your backend
console.log('Feedback submitted:', { messageId, feedbackType, comment });
setIsSubmitted(true);
setTimeout(() => {
setIsSubmitted(false);
setFeedbackType(null);
setComment('');
onClose();
}, 1500);
};
const handleClose = () => {
setFeedbackType(null);
setComment('');
setIsSubmitted(false);
onClose();
};
return (
<AnimatePresence>
{isOpen && (
<>
{/* Backdrop */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50"
onClick={handleClose}
/>
{/* Popup */}
<motion.div
initial={{ opacity: 0, scale: 0.95, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.95, y: 20 }}
className={`fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 z-50 w-96 rounded-2xl border backdrop-blur-sm shadow-2xl transition-all duration-300 ${
isUnivAiPlusMode
? 'bg-gradient-to-br from-white/95 to-purple-50/95 border-purple-200/50 shadow-purple-500/20'
: 'bg-gradient-to-br from-white/95 to-red-50/95 border-red-200/50 shadow-red-500/20'
}`}
>
{/* Header */}
<div className="flex items-center justify-between p-6 border-b border-current/10">
<div className="flex items-center gap-3">
<div className={`w-10 h-10 rounded-full flex items-center justify-center transition-all duration-300 ${
isUnivAiPlusMode
? 'bg-gradient-to-r from-purple-500 to-pink-500 shadow-purple-500/30'
: 'bg-gradient-to-r from-red-500 to-orange-500 shadow-red-500/30'
}`}>
<MessageSquare className="text-white" size={20} />
</div>
<div>
<h3 className={`transition-all duration-300 ${
isUnivAiPlusMode
? 'text-purple-900 dark:text-purple-100'
: 'text-red-900 dark:text-red-100'
}`}>
Share Feedback
</h3>
<p className={`text-sm transition-all duration-300 ${
isUnivAiPlusMode
? 'text-purple-700/80 dark:text-purple-300/80'
: 'text-red-700/80 dark:text-red-300/80'
}`}>
Help us improve our responses
</p>
</div>
</div>
<Button
variant="ghost"
size="sm"
onClick={handleClose}
className={`transition-all duration-300 ${
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'
}`}
>
<X size={18} />
</Button>
</div>
{/* Content */}
<div className="p-6">
{!isSubmitted ? (
<>
{/* Rating */}
<div className="mb-4">
<p className={`text-sm mb-3 transition-all duration-300 ${
isUnivAiPlusMode
? 'text-purple-700/80 dark:text-purple-300/80'
: 'text-red-700/80 dark:text-red-300/80'
}`}>
How was this response?
</p>
<div className="flex gap-3">
<Button
variant={feedbackType === 'positive' ? 'default' : 'outline'}
size="sm"
onClick={() => setFeedbackType('positive')}
className={`flex items-center gap-2 transition-all duration-300 ${
feedbackType === 'positive'
? isUnivAiPlusMode
? 'bg-gradient-to-r from-purple-500 to-pink-500 text-white shadow-purple-500/30'
: 'bg-gradient-to-r from-red-500 to-orange-500 text-white shadow-red-500/30'
: isUnivAiPlusMode
? 'border-purple-200 text-purple-700 hover:bg-purple-50 dark:border-purple-600 dark:text-purple-300 dark:hover:bg-purple-900/30'
: 'border-red-200 text-red-700 hover:bg-red-50 dark:border-red-600 dark:text-red-300 dark:hover:bg-red-900/30'
}`}
>
<ThumbsUp size={16} />
Helpful
</Button>
<Button
variant={feedbackType === 'negative' ? 'default' : 'outline'}
size="sm"
onClick={() => setFeedbackType('negative')}
className={`flex items-center gap-2 transition-all duration-300 ${
feedbackType === 'negative'
? isUnivAiPlusMode
? 'bg-gradient-to-r from-purple-500 to-pink-500 text-white shadow-purple-500/30'
: 'bg-gradient-to-r from-red-500 to-orange-500 text-white shadow-red-500/30'
: isUnivAiPlusMode
? 'border-purple-200 text-purple-700 hover:bg-purple-50 dark:border-purple-600 dark:text-purple-300 dark:hover:bg-purple-900/30'
: 'border-red-200 text-red-700 hover:bg-red-50 dark:border-red-600 dark:text-red-300 dark:hover:bg-red-900/30'
}`}
>
<ThumbsDown size={16} />
Not helpful
</Button>
</div>
</div>
{/* Comment */}
<div className="mb-4">
<p className={`text-sm mb-2 transition-all duration-300 ${
isUnivAiPlusMode
? 'text-purple-700/80 dark:text-purple-300/80'
: 'text-red-700/80 dark:text-red-300/80'
}`}>
Additional comments (optional)
</p>
<Textarea
value={comment}
onChange={(e) => setComment(e.target.value)}
placeholder="Tell us more about your experience..."
className={`transition-all duration-300 ${
isUnivAiPlusMode
? 'border-purple-200 focus:border-purple-400 dark:border-purple-600'
: 'border-red-200 focus:border-red-400 dark:border-red-600'
}`}
rows={3}
/>
</div>
{/* Actions */}
<div className="flex gap-3 justify-end">
<Button
variant="outline"
size="sm"
onClick={handleClose}
className={`transition-all duration-300 ${
isUnivAiPlusMode
? 'border-purple-200 text-purple-700 hover:bg-purple-50 dark:border-purple-600 dark:text-purple-300 dark:hover:bg-purple-900/30'
: 'border-red-200 text-red-700 hover:bg-red-50 dark:border-red-600 dark:text-red-300 dark:hover:bg-red-900/30'
}`}
>
Cancel
</Button>
<Button
size="sm"
onClick={handleSubmit}
disabled={!feedbackType}
className={`transition-all duration-300 ${
isUnivAiPlusMode
? 'bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600 text-white shadow-purple-500/30'
: 'bg-gradient-to-r from-red-500 to-orange-500 hover:from-red-600 hover:to-orange-600 text-white shadow-red-500/30'
}`}
>
Submit Feedback
</Button>
</div>
</>
) : (
/* Success state */
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
className="text-center py-4"
>
<div className={`w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4 transition-all duration-300 ${
isUnivAiPlusMode
? 'bg-gradient-to-r from-purple-400 to-pink-500 shadow-purple-500/30'
: 'bg-gradient-to-r from-green-400 to-green-500 shadow-green-500/30'
}`}>
<ThumbsUp className="text-white" size={24} />
</div>
<h4 className={`mb-2 transition-all duration-300 ${
isUnivAiPlusMode
? 'text-purple-900 dark:text-purple-100'
: 'text-red-900 dark:text-red-100'
}`}>
Thank you!
</h4>
<p className={`text-sm transition-all duration-300 ${
isUnivAiPlusMode
? 'text-purple-700/80 dark:text-purple-300/80'
: 'text-red-700/80 dark:text-red-300/80'
}`}>
Your feedback helps us improve
</p>
</motion.div>
)}
</div>
</motion.div>
</>
)}
</AnimatePresence>
);
}