| import React, { useState } from 'react'; |
| import { X, MessageSquare, AlertCircle, Lightbulb, HelpCircle, Star, Loader2 } from 'lucide-react'; |
| import { Language, FeedbackItem, UserAccount } from '../types'; |
| import { TRANSLATIONS } from '../constants/translations'; |
|
|
| interface FeedbackModalProps { |
| isVisible: boolean; |
| onClose: () => void; |
| language: Language; |
| user?: UserAccount; |
| onSubmit: (data: Omit<FeedbackItem, 'id' | 'timestamp'>) => Promise<void>; |
| } |
|
|
| export const FeedbackModal: React.FC<FeedbackModalProps> = ({ isVisible, onClose, language, user, onSubmit }) => { |
| const t = TRANSLATIONS[language]; |
| const [type, setType] = useState<FeedbackItem['type']>('suggestion'); |
| const [content, setContent] = useState(''); |
| const [rating, setRating] = useState(5); |
| const [isSubmitting, setIsSubmitting] = useState(false); |
|
|
| if (!isVisible) return null; |
|
|
| const handleSubmit = async (e: React.FormEvent) => { |
| e.preventDefault(); |
| if (!content.trim()) return; |
|
|
| setIsSubmitting(true); |
| try { |
| await onSubmit({ |
| userId: user?.id, |
| type, |
| rating, |
| content, |
| contact: user?.phone |
| }); |
| |
| setContent(''); |
| setRating(5); |
| setType('suggestion'); |
| } catch (error) { |
| console.error("Feedback error", error); |
| } finally { |
| setIsSubmitting(false); |
| } |
| }; |
|
|
| const getIcon = () => { |
| switch (type) { |
| case 'bug': return <AlertCircle className="w-6 h-6 text-red-500" />; |
| case 'suggestion': return <Lightbulb className="w-6 h-6 text-amber-500" />; |
| default: return <HelpCircle className="w-6 h-6 text-blue-500" />; |
| } |
| }; |
|
|
| return ( |
| <div className="fixed inset-0 z-[110] flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm animate-fade-in"> |
| <div className="bg-white rounded-2xl shadow-2xl w-full max-w-md overflow-hidden relative"> |
| <button onClick={onClose} className="absolute top-4 right-4 p-1 rounded-full hover:bg-gray-100 transition-colors z-10"> |
| <X className="w-5 h-5 text-gray-500" /> |
| </button> |
| |
| <div className="p-6"> |
| <div className="text-center mb-6"> |
| <div className="w-12 h-12 bg-rose-50 rounded-full flex items-center justify-center mx-auto mb-3 text-rose-500"> |
| <MessageSquare className="w-6 h-6" /> |
| </div> |
| <h2 className="text-xl font-bold text-gray-900">{t.feedbackTitle}</h2> |
| <p className="text-sm text-gray-500 mt-1">{t.feedbackDesc}</p> |
| </div> |
| |
| <form onSubmit={handleSubmit} className="space-y-5"> |
| {/* Rating */} |
| <div className="text-center"> |
| <label className="block text-xs font-bold text-gray-500 mb-2">{t.feedbackRating}</label> |
| <div className="flex justify-center gap-2"> |
| {[1, 2, 3, 4, 5].map((star) => ( |
| <button |
| key={star} |
| type="button" |
| onClick={() => setRating(star)} |
| className="focus:outline-none transition-transform hover:scale-110" |
| > |
| <Star className={`w-8 h-8 ${star <= rating ? 'fill-yellow-400 text-yellow-400' : 'text-gray-300'}`} /> |
| </button> |
| ))} |
| </div> |
| </div> |
| |
| {/* Type Selection */} |
| <div className="grid grid-cols-3 gap-2"> |
| <button |
| type="button" |
| onClick={() => setType('bug')} |
| className={`p-3 rounded-xl border flex flex-col items-center gap-1 transition-all ${type === 'bug' ? 'bg-red-50 border-red-200 text-red-600' : 'bg-white border-gray-200 text-gray-500 hover:bg-gray-50'}`} |
| > |
| <AlertCircle className="w-5 h-5" /> |
| <span className="text-xs font-bold">{t.feedbackTypeBug}</span> |
| </button> |
| <button |
| type="button" |
| onClick={() => setType('suggestion')} |
| className={`p-3 rounded-xl border flex flex-col items-center gap-1 transition-all ${type === 'suggestion' ? 'bg-amber-50 border-amber-200 text-amber-600' : 'bg-white border-gray-200 text-gray-500 hover:bg-gray-50'}`} |
| > |
| <Lightbulb className="w-5 h-5" /> |
| <span className="text-xs font-bold">{t.feedbackTypeSugg}</span> |
| </button> |
| <button |
| type="button" |
| onClick={() => setType('other')} |
| className={`p-3 rounded-xl border flex flex-col items-center gap-1 transition-all ${type === 'other' ? 'bg-blue-50 border-blue-200 text-blue-600' : 'bg-white border-gray-200 text-gray-500 hover:bg-gray-50'}`} |
| > |
| <HelpCircle className="w-5 h-5" /> |
| <span className="text-xs font-bold">{t.feedbackTypeOther}</span> |
| </button> |
| </div> |
| |
| {/* Content */} |
| <div> |
| <div className="relative"> |
| <textarea |
| value={content} |
| onChange={(e) => setContent(e.target.value)} |
| placeholder={t.feedbackContentPlace} |
| className="w-full p-4 rounded-xl border border-gray-200 focus:border-rose-500 focus:ring-1 focus:ring-rose-200 outline-none h-32 resize-none bg-gray-50 focus:bg-white transition-all text-sm" |
| required |
| /> |
| <div className="absolute top-3 right-3 opacity-50 pointer-events-none"> |
| {getIcon()} |
| </div> |
| </div> |
| </div> |
| |
| <button |
| type="submit" |
| disabled={isSubmitting || !content.trim()} |
| className="w-full py-3 bg-gray-900 text-white rounded-xl font-bold shadow-lg hover:bg-black transition-all flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed" |
| > |
| {isSubmitting && <Loader2 className="w-4 h-4 animate-spin" />} |
| {t.feedbackSubmit} |
| </button> |
| </form> |
| </div> |
| </div> |
| </div> |
| ); |
| }; |