import { useState } from "react"; import { Card, CardContent } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogFooter } from "@/components/ui/dialog"; import { Plus, ThumbsUp, MessageSquare, TrendingUp, Clock, Bug, Lightbulb, Wrench, ArrowUpDown, LogIn, LogOut } from "lucide-react"; import { toast } from "sonner"; import { useAuth, useSaasMutation } from "@/hooks/use-tygarun"; import Sidebar from "@/components/Sidebar"; import Header from "@/components/Header"; interface FeedbackItem { id: number; user: string; userInitials: string; userColor: string; text: string; category: string; categoryColor: string; categoryIcon: string; votes: number; status: string; statusColor: string; date: string; comments: number; } const feedbackData: FeedbackItem[] = [ { id: 1, user: "Elena Martinez", userInitials: "EM", userColor: "bg-blue-500", text: "The roadmap board needs a timeline view option. It would be so much easier to visualize dependencies and deadlines in a Gantt-style layout.", category: "Feature", categoryColor: "bg-blue-100 text-blue-700", categoryIcon: "lightbulb", votes: 34, status: "Under Review", statusColor: "bg-amber-100 text-amber-700", date: "Apr 10, 2026", comments: 8 }, { id: 2, user: "James Chen", userInitials: "JC", userColor: "bg-emerald-500", text: "Exporting reports to PDF cuts off long feature descriptions. The page margins seem too wide and text wraps incorrectly in the generated document.", category: "Bug", categoryColor: "bg-red-100 text-red-700", categoryIcon: "bug", votes: 28, status: "In Progress", statusColor: "bg-blue-100 text-blue-700", date: "Apr 9, 2026", comments: 5 }, { id: 3, user: "Taylor Pham", userInitials: "TP", userColor: "bg-violet-500", text: "Would love the ability to link related feedback items together. Sometimes multiple users report the same issue in different ways.", category: "Feature", categoryColor: "bg-blue-100 text-blue-700", categoryIcon: "lightbulb", votes: 45, status: "Planned", statusColor: "bg-slate-100 text-slate-700", date: "Apr 8, 2026", comments: 12 }, { id: 4, user: "Lisa Wang", userInitials: "LW", userColor: "bg-sky-500", text: "The notification emails could include more context. Right now they just say a feature was updated but not what changed specifically.", category: "Improvement", categoryColor: "bg-amber-100 text-amber-700", categoryIcon: "wrench", votes: 19, status: "Under Review", statusColor: "bg-amber-100 text-amber-700", date: "Apr 7, 2026", comments: 3 }, { id: 5, user: "David Park", userInitials: "DP", userColor: "bg-indigo-500", text: "Dashboard widgets sometimes show stale data after switching between views. A manual refresh button or auto-refresh interval would fix this.", category: "Bug", categoryColor: "bg-red-100 text-red-700", categoryIcon: "bug", votes: 22, status: "In Progress", statusColor: "bg-blue-100 text-blue-700", date: "Apr 6, 2026", comments: 6 }, { id: 6, user: "Amy Foster", userInitials: "AF", userColor: "bg-pink-500", text: "It would be great if the feature voting page had a search and filter option. With hundreds of features, scrolling through all of them is tedious.", category: "Improvement", categoryColor: "bg-amber-100 text-amber-700", categoryIcon: "wrench", votes: 37, status: "Planned", statusColor: "bg-slate-100 text-slate-700", date: "Apr 5, 2026", comments: 9 }, ]; const categoryIcons: Record = { bug: Bug, lightbulb: Lightbulb, wrench: Wrench, }; export default function FeedbackPage() { const [sortBy, setSortBy] = useState<"votes" | "newest" | "trending">("votes"); const [dialogOpen, setDialogOpen] = useState(false); const [items, setItems] = useState(feedbackData); const [fbTitle, setFbTitle] = useState(""); const [fbDesc, setFbDesc] = useState(""); const [fbCategory, setFbCategory] = useState("feature"); // Login is LIVE via tyga.run auth; voting + feedback submission use surveys (seed until live) const { user, isSignedIn, signin, signout } = useAuth(); const { mutate: submitFeedback } = useSaasMutation("surveys", "/responses"); const { mutate: castVote } = useSaasMutation("surveys", "/responses"); const [authOpen, setAuthOpen] = useState(false); const [authEmail, setAuthEmail] = useState(""); const [authPassword, setAuthPassword] = useState(""); const [authBusy, setAuthBusy] = useState(false); const handleSignin = async (e: React.FormEvent) => { e.preventDefault(); setAuthBusy(true); try { await signin(authEmail, authPassword); toast.success("Signed in! Your votes now count."); setAuthOpen(false); setAuthEmail(""); setAuthPassword(""); } catch (err) { toast.error("Sign in failed. Check your credentials."); } finally { setAuthBusy(false); } }; const handleVote = async (id: number) => { if (!isSignedIn) { setAuthOpen(true); toast("Sign in to vote"); return; } setItems(prev => prev.map(item => item.id === id ? { ...item, votes: item.votes + 1 } : item)); try { await castVote({ feedbackId: id, type: "upvote" }); toast("Vote recorded!"); } catch (err) { toast.error("Could not record vote."); } }; const handleSubmit = async () => { if (!isSignedIn) { setAuthOpen(true); toast("Sign in to submit feedback"); return; } try { await submitFeedback({ title: fbTitle, description: fbDesc, category: fbCategory }); toast.success("Feedback submitted successfully!"); setDialogOpen(false); setFbTitle(""); setFbDesc(""); setFbCategory("feature"); } catch (err) { toast.error("Could not submit feedback."); } }; const sorted = [...items].sort((a, b) => { if (sortBy === "votes") return b.votes - a.votes; if (sortBy === "newest") return new Date(b.date).getTime() - new Date(a.date).getTime(); return (b.votes + b.comments * 2) - (a.votes + a.comments * 2); }); return (
{/* ── Page Header ── */}

Feedback

Collect and prioritize user feedback

{/* Auth control — login is LIVE via tyga.run */} {isSignedIn ? ( ) : ( Sign in to vote
setAuthEmail(e.target.value)} placeholder="you@company.com" required />
setAuthPassword(e.target.value)} placeholder="Password" required />
)} {/* Sort Options */}
{(["votes", "newest", "trending"] as const).map((option) => ( ))}
{/* Submit Feedback Dialog */} Submit Feedback
setFbTitle(e.target.value)} placeholder="Brief summary of your feedback" />