| import { useState } from 'react' |
| import { Loader2, Star } from 'lucide-react' |
| import Modal from './Modal' |
| import Button from './Button' |
|
|
| const categories = ['general', 'bug', 'feature', 'other'] |
|
|
| export default function FeedbackDialog({ open, onOpenChange, onSubmit, pending }) { |
| const [rating, setRating] = useState(0) |
| const [category, setCategory] = useState('general') |
| const [message, setMessage] = useState('') |
|
|
| const submit = async () => { |
| await onSubmit({ rating, category, message }) |
| setRating(0) |
| setCategory('general') |
| setMessage('') |
| onOpenChange(false) |
| } |
|
|
| return ( |
| <Modal |
| open={open} |
| onOpenChange={onOpenChange} |
| size="sm" |
| title="Send feedback" |
| description="Let us know what is working well or what should improve next." |
| footer={ |
| <div className="flex items-center justify-end gap-2"> |
| <Button variant="ghost" onClick={() => onOpenChange(false)}> |
| Cancel |
| </Button> |
| <Button |
| variant="primary" |
| onClick={submit} |
| disabled={!rating || !message.trim()} |
| loading={pending} |
| > |
| {pending ? <Loader2 className="h-4 w-4 animate-spin" /> : null} |
| Submit |
| </Button> |
| </div> |
| } |
| > |
| <div className="space-y-5"> |
| <div> |
| <p className="mb-3 text-sm font-medium text-foreground">Rating</p> |
| <div className="flex items-center gap-2"> |
| {[1, 2, 3, 4, 5].map((value) => ( |
| <button |
| key={value} |
| type="button" |
| className={`rounded-full p-2 transition ${ |
| rating >= value ? 'text-warning' : 'text-muted-foreground' |
| }`} |
| onClick={() => setRating(value)} |
| > |
| <Star className={`h-6 w-6 ${rating >= value ? 'fill-current' : ''}`} /> |
| </button> |
| ))} |
| </div> |
| </div> |
| |
| <div> |
| <p className="mb-3 text-sm font-medium text-foreground">Category</p> |
| <div className="flex flex-wrap gap-2"> |
| {categories.map((value) => ( |
| <button |
| key={value} |
| type="button" |
| onClick={() => setCategory(value)} |
| className={`rounded-full border px-3 py-2 text-sm capitalize transition ${ |
| category === value |
| ? 'border-accent/40 bg-accent/10 text-accent' |
| : 'border-border bg-panel text-muted-foreground hover:text-foreground' |
| }`} |
| > |
| {value} |
| </button> |
| ))} |
| </div> |
| </div> |
| |
| <label className="block space-y-2"> |
| <span className="text-sm font-medium text-foreground">Message</span> |
| <textarea |
| className="min-h-[120px] w-full rounded-3xl border border-input bg-panel px-4 py-3 text-sm text-foreground outline-none transition placeholder:text-muted-foreground focus:border-accent/50 focus:ring-2 focus:ring-ring/20" |
| placeholder="What should the next upgrade improve?" |
| value={message} |
| onChange={(event) => setMessage(event.target.value)} |
| /> |
| </label> |
| </div> |
| </Modal> |
| ) |
| } |
|
|