import { useEffect, useState } from "react"; import { useFeatureRequestStore, type FeatureRequest } from "../stores/featureRequest.ts"; import { useAuthStore } from "../stores/auth.ts"; interface FeatureRequestsPanelProps { serverId: string; channelId?: string; onClose: () => void; } const STATUS_LABELS: Record = { open: "OPEN", planned: "PLANNED", done: "DONE", rejected: "REJECTED", }; const STATUS_COLORS: Record = { open: "text-gb-green", planned: "text-gb-yellow", done: "text-gb-aqua", rejected: "text-gb-red", }; export function FeatureRequestsPanel({ serverId, channelId, onClose }: FeatureRequestsPanelProps) { const requests = useFeatureRequestStore((s) => s.requestsByServer[serverId] || []); const fetchRequests = useFeatureRequestStore((s) => s.fetchRequests); const createRequest = useFeatureRequestStore((s) => s.createRequest); const vote = useFeatureRequestStore((s) => s.vote); const unvote = useFeatureRequestStore((s) => s.unvote); const updateStatus = useFeatureRequestStore((s) => s.updateStatus); const currentUser = useAuthStore((s) => s.user); const [showCreate, setShowCreate] = useState(false); const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); const [submitting, setSubmitting] = useState(false); const [filter, setFilter] = useState("all"); useEffect(() => { fetchRequests(serverId); }, [serverId, fetchRequests]); useEffect(() => { const handler = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", handler); return () => window.removeEventListener("keydown", handler); }, [onClose]); const handleCreate = async () => { if (!title.trim()) return; setSubmitting(true); try { await createRequest(serverId, title.trim(), description.trim(), channelId); setTitle(""); setDescription(""); setShowCreate(false); } catch { // silent } finally { setSubmitting(false); } }; const handleVote = async (fr: FeatureRequest) => { const hasVoted = currentUser ? fr.voters.includes(currentUser.id) : false; if (hasVoted) { await unvote(serverId, fr.id); } else { await vote(serverId, fr.id); } }; const filtered = filter === "all" ? requests : requests.filter((r) => r.status === filter); return (
FEATURE REQUESTS ({requests.length})
{/* Filter tabs */}
{["all", "open", "planned", "done", "rejected"].map((s) => ( ))}
{/* Create form */} {showCreate && (
setTitle(e.target.value)} placeholder="Feature title..." className="w-full bg-gb-bg-s border border-gb-bg-t text-gb-fg text-xs font-mono px-2 py-1 mb-1 outline-none focus:border-gb-orange" maxLength={255} />