"use client";
import { useState } from "react";
import {
Lightbulb,
Send,
Loader2,
Check,
Sparkles,
Bug,
Zap,
Puzzle,
HelpCircle,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Separator } from "@/components/ui/separator";
import { cn } from "@/lib/utils";
type Category = {
id: string;
label: string;
icon: React.ElementType;
};
const categories: Category[] = [
{ id: "feature", label: "New Feature", icon: Sparkles },
{ id: "improvement", label: "Improvement", icon: Zap },
{ id: "integration", label: "Integration", icon: Puzzle },
{ id: "bug", label: "Bug Fix", icon: Bug },
{ id: "other", label: "Other", icon: HelpCircle },
];
type Impact = "low" | "medium" | "high" | "critical";
export const title = "React Dialog Block Feature Request";
export default function DialogFeatureRequest() {
const [open, setOpen] = useState(false);
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [category, setCategory] = useState<string>("");
const [impact, setImpact] = useState<Impact>("medium");
const [email, setEmail] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
const [ticketId, setTicketId] = useState("");
const handleSubmit = async () => {
if (!title || !description || !category) return;
setIsSubmitting(true);
await new Promise((resolve) => setTimeout(resolve, 1500));
// Generate mock ticket ID
setTicketId(`FR-${Math.random().toString(36).substring(2, 8).toUpperCase()}`);
setIsSubmitting(false);
setIsSubmitted(true);
};
const handleClose = () => {
setOpen(false);
setTimeout(() => {
setTitle("");
setDescription("");
setCategory("");
setImpact("medium");
setEmail("");
setIsSubmitted(false);
setTicketId("");
}, 200);
};
const isValid = title.trim().length >= 5 && description.trim().length >= 20 && category;
if (isSubmitted) {
return (
<Dialog open={open} onOpenChange={setOpen}>
<div className="flex min-h-[350px] items-center justify-center">
<DialogTrigger asChild>
<Button variant="outline">
<Lightbulb className="mr-2 h-4 w-4" />
Request Feature
</Button>
</DialogTrigger>
</div>
<DialogContent className="sm:max-w-md">
<div className="flex flex-col items-center justify-center py-8 text-center">
<div className="flex h-12 w-12 items-center justify-center rounded-full border-2 border-primary">
<Check className="h-6 w-6 text-primary" />
</div>
<h3 className="mt-4 text-lg font-semibold">Request Submitted!</h3>
<p className="mt-1 text-sm text-muted-foreground">
Thank you for your feedback. We've received your feature request.
</p>
<div className="mt-4 rounded-lg border p-3">
<p className="text-xs text-muted-foreground">Tracking ID</p>
<p className="font-mono font-semibold">{ticketId}</p>
</div>
{email && (
<p className="mt-4 text-xs text-muted-foreground">
We'll send updates to {email}
</p>
)}
<Button onClick={handleClose} className="mt-6">
Done
</Button>
</div>
</DialogContent>
</Dialog>
);
}
return (
<Dialog open={open} onOpenChange={setOpen}>
<div className="flex min-h-[350px] items-center justify-center">
<DialogTrigger asChild>
<Button variant="outline">
<Lightbulb className="mr-2 h-4 w-4" />
Request Feature
</Button>
</DialogTrigger>
</div>
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<Lightbulb className="h-5 w-5" />
Request a Feature
</DialogTitle>
<DialogDescription>
Share your ideas to help us improve the product.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
{/* Title */}
<div className="space-y-2">
<Label htmlFor="feature-title">
Feature Title <span className="text-destructive">*</span>
</Label>
<Input
id="feature-title"
placeholder="Brief title for your feature request"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
{title && title.length < 5 && (
<p className="text-xs text-muted-foreground">
Title should be at least 5 characters
</p>
)}
</div>
{/* Category */}
<div className="space-y-2">
<Label>
Category <span className="text-destructive">*</span>
</Label>
<Select value={category} onValueChange={setCategory}>
<SelectTrigger>
<SelectValue placeholder="Select a category" />
</SelectTrigger>
<SelectContent>
{categories.map((cat) => (
<SelectItem key={cat.id} value={cat.id}>
<div className="flex items-center gap-2">
<cat.icon className="h-4 w-4" />
{cat.label}
</div>
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{/* Description */}
<div className="space-y-2">
<Label htmlFor="feature-description">
Description <span className="text-destructive">*</span>
</Label>
<Textarea
id="feature-description"
placeholder="Describe the feature, the problem it solves, and how you'd use it..."
value={description}
onChange={(e) => setDescription(e.target.value)}
rows={4}
/>
<div className="flex items-center justify-between">
<p className="text-xs text-muted-foreground">
{description.length < 20
? `At least ${20 - description.length} more characters needed`
: "Good description length"}
</p>
<span className="text-xs text-muted-foreground">
{description.length}/500
</span>
</div>
</div>
<Separator />
{/* Impact */}
<div className="space-y-2">
<Label>How important is this to you?</Label>
<RadioGroup
value={impact}
onValueChange={(v) => setImpact(v as Impact)}
className="flex gap-4"
>
{[
{ value: "low", label: "Nice to have" },
{ value: "medium", label: "Important" },
{ value: "high", label: "Very important" },
{ value: "critical", label: "Critical" },
].map((option) => (
<label
key={option.value}
className={cn(
"flex items-center gap-2 rounded-lg border px-3 py-2 cursor-pointer transition-colors",
impact === option.value
? "border-primary"
: "hover:border-primary/50"
)}
>
<RadioGroupItem value={option.value} />
<span className="text-xs">{option.label}</span>
</label>
))}
</RadioGroup>
</div>
{/* Email (optional) */}
<div className="space-y-2">
<Label htmlFor="feature-email">
Email <Badge variant="secondary" className="ml-2 text-xs">Optional</Badge>
</Label>
<Input
id="feature-email"
type="email"
placeholder="[email protected]"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<p className="text-xs text-muted-foreground">
Get notified when this feature is implemented
</p>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={handleClose}>
Cancel
</Button>
<Button onClick={handleSubmit} disabled={!isValid || isSubmitting}>
{isSubmitting ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Submitting...
</>
) : (
<>
<Send className="mr-2 h-4 w-4" />
Submit Request
</>
)}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}