File size: 3,307 Bytes
212c959 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | 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>
)
}
|