import { useState, useRef, useEffect } from 'react' import { MessageSquareText, Send, CheckCircle2, ChevronDown } from 'lucide-react' import { PageMeta } from '@/components/common/PageMeta' import { useAuthStore } from '@/store/authStore' import { feedbackApi } from '@/api' import { cn } from '@/lib/utils' import { toast } from '@/lib/toast' // TODO: Post-session contextual feedback prompt — after completing a troubleshooting // session, show a subtle inline prompt like "How was this flow? Quick feedback →" // that opens a lightweight version of this form pre-tagged with tree/session context. const FEEDBACK_TYPES = [ { value: 'Bug Report', description: 'Something is broken or not working as expected' }, { value: 'Feature Request', description: "An idea for something new you'd like to see" }, { value: 'Usability Issue', description: 'Something works but is confusing or hard to use' }, { value: 'Documentation', description: 'Feedback on help docs, tooltips, or in-app guidance' }, { value: 'General Feedback', description: 'Anything else — thoughts, impressions, suggestions' }, ] as const export function FeedbackPage() { const user = useAuthStore(s => s.user) const [email, setEmail] = useState(user?.email ?? '') const [feedbackType, setFeedbackType] = useState('') const [message, setMessage] = useState('') const [isSubmitting, setIsSubmitting] = useState(false) const [submitted, setSubmitted] = useState(false) const [typeDropdownOpen, setTypeDropdownOpen] = useState(false) const [highlightedIndex, setHighlightedIndex] = useState(-1) const triggerRef = useRef(null) const listboxRef = useRef(null) const canSubmit = email.trim() && feedbackType && message.trim().length >= 10 const selectedType = FEEDBACK_TYPES.find(t => t.value === feedbackType) const handleSelectType = (value: string) => { setFeedbackType(value) setTypeDropdownOpen(false) setHighlightedIndex(-1) triggerRef.current?.focus() } const handleDropdownKeyDown = (e: React.KeyboardEvent) => { switch (e.key) { case 'ArrowDown': e.preventDefault() if (!typeDropdownOpen) { setTypeDropdownOpen(true) setHighlightedIndex(0) } else { setHighlightedIndex(i => (i + 1) % FEEDBACK_TYPES.length) } break case 'ArrowUp': e.preventDefault() if (!typeDropdownOpen) { setTypeDropdownOpen(true) setHighlightedIndex(FEEDBACK_TYPES.length - 1) } else { setHighlightedIndex(i => (i - 1 + FEEDBACK_TYPES.length) % FEEDBACK_TYPES.length) } break case 'Enter': case ' ': e.preventDefault() if (typeDropdownOpen && highlightedIndex >= 0) { handleSelectType(FEEDBACK_TYPES[highlightedIndex].value) } else { setTypeDropdownOpen(true) setHighlightedIndex(0) } break case 'Escape': e.preventDefault() setTypeDropdownOpen(false) setHighlightedIndex(-1) triggerRef.current?.focus() break case 'Tab': if (typeDropdownOpen && highlightedIndex >= 0) { handleSelectType(FEEDBACK_TYPES[highlightedIndex].value) } break } } useEffect(() => { if (!typeDropdownOpen) return const handleClickOutside = (e: MouseEvent) => { if ( triggerRef.current && !triggerRef.current.contains(e.target as Node) && listboxRef.current && !listboxRef.current.contains(e.target as Node) ) { setTypeDropdownOpen(false) setHighlightedIndex(-1) } } document.addEventListener('mousedown', handleClickOutside) return () => document.removeEventListener('mousedown', handleClickOutside) }, [typeDropdownOpen]) const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() if (!canSubmit || isSubmitting) return setIsSubmitting(true) try { const response = await feedbackApi.submit({ email: email.trim(), feedback_type: feedbackType, message: message.trim(), }) if (response.success) { setSubmitted(true) setFeedbackType('') setMessage('') } } catch (err: unknown) { const error = err as { response?: { data?: { detail?: string } } } toast.error(error.response?.data?.detail || 'Failed to submit feedback. Please try again.') } finally { setIsSubmitting(false) } } const handleNewFeedback = () => { setSubmitted(false) setEmail(user?.email ?? '') } return (
{/* Page header */}

Send Feedback

Help us improve ResolutionFlow. Report bugs, request features, or share your thoughts.

{submitted ? (

Thank you for your feedback!

We've received your submission and will review it shortly. Check your email for a confirmation.

) : (
{/* Email */}
setEmail(e.target.value)} placeholder="your@email.com" required className="w-full rounded-lg border border-border bg-card px-3 py-2 text-foreground placeholder:text-muted-foreground focus:border-primary focus:ring-1 focus:ring-primary/20 focus:outline-hidden" />

We'll reply to this address if we need more details.

{/* Feedback Type — custom selector with descriptions */}
{typeDropdownOpen && (
{FEEDBACK_TYPES.map((type, index) => ( ))}
)}
{/* Message */}