From 5b8536837d53f0bcb94bdd0ad0063c6292b292c2 Mon Sep 17 00:00:00 2001 From: Akshay Date: Fri, 7 Nov 2025 09:09:41 +0530 Subject: [PATCH 1/3] feat(help): Add comprehensive support features for user assistance - Implement new API routes for contact and bug report submissions - Add server-side handling for support ticket creation in Supabase - Enhance help page with dynamic contact and bug report forms - Implement form validation and error handling for support requests - Add state management for contact and bug report form interactions - Create quick action buttons for user support engagement - Improve user experience with responsive and interactive support features --- app/api/support/bug-report/route.ts | 42 +++++ app/api/support/contact/route.ts | 42 +++++ app/protected/help/page.tsx | 270 ++++++++++++++++++++++++++-- 3 files changed, 336 insertions(+), 18 deletions(-) create mode 100644 app/api/support/bug-report/route.ts create mode 100644 app/api/support/contact/route.ts diff --git a/app/api/support/bug-report/route.ts b/app/api/support/bug-report/route.ts new file mode 100644 index 00000000..8e32dc5c --- /dev/null +++ b/app/api/support/bug-report/route.ts @@ -0,0 +1,42 @@ +import { NextRequest, NextResponse } from 'next/server' +import { createClient } from '@/lib/supabase/server' + +export async function POST(request: NextRequest) { + try { + const supabase = await createClient() + + // Get authenticated user + const { data: { user }, error: authError } = await supabase.auth.getUser() + + if (authError || !user) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + } + + const { title, description } = await request.json() + + if (!title || !description) { + return NextResponse.json({ error: 'Title and description are required' }, { status: 400 }) + } + + // Insert bug report into database + const { error: insertError } = await supabase + .from('support_tickets') + .insert({ + user_id: user.id, + type: 'bug', + subject: title, + message: description, + status: 'open', + }) + + if (insertError) { + console.error('Error creating bug report:', insertError) + return NextResponse.json({ error: 'Failed to submit bug report' }, { status: 500 }) + } + + return NextResponse.json({ success: true, message: 'Bug report submitted successfully' }) + } catch (error) { + console.error('Error in bug report API:', error) + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) + } +} diff --git a/app/api/support/contact/route.ts b/app/api/support/contact/route.ts new file mode 100644 index 00000000..34f94240 --- /dev/null +++ b/app/api/support/contact/route.ts @@ -0,0 +1,42 @@ +import { NextRequest, NextResponse } from 'next/server' +import { createClient } from '@/lib/supabase/server' + +export async function POST(request: NextRequest) { + try { + const supabase = await createClient() + + // Get authenticated user + const { data: { user }, error: authError } = await supabase.auth.getUser() + + if (authError || !user) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + } + + const { subject, message } = await request.json() + + if (!subject || !message) { + return NextResponse.json({ error: 'Subject and message are required' }, { status: 400 }) + } + + // Insert contact request into database + const { error: insertError } = await supabase + .from('support_tickets') + .insert({ + user_id: user.id, + type: 'contact', + subject, + message, + status: 'open', + }) + + if (insertError) { + console.error('Error creating support ticket:', insertError) + return NextResponse.json({ error: 'Failed to submit contact request' }, { status: 500 }) + } + + return NextResponse.json({ success: true, message: 'Contact request submitted successfully' }) + } catch (error) { + console.error('Error in contact API:', error) + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) + } +} diff --git a/app/protected/help/page.tsx b/app/protected/help/page.tsx index eda45c57..82af08b1 100644 --- a/app/protected/help/page.tsx +++ b/app/protected/help/page.tsx @@ -1,6 +1,7 @@ 'use client' import React, { useState } from 'react' +import Link from 'next/link' import { Input } from '@/components/ui/input' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' @@ -162,6 +163,18 @@ const faqCategories = [ export default function HelpPage() { const [searchQuery, setSearchQuery] = useState('') const [filteredFaqs, setFilteredFaqs] = useState(faqCategories) + const [showContactForm, setShowContactForm] = useState(false) + const [showBugForm, setShowBugForm] = useState(false) + + // Contact form state + const [contactSubject, setContactSubject] = useState('') + const [contactMessage, setContactMessage] = useState('') + const [contactSubmitting, setContactSubmitting] = useState(false) + + // Bug form state + const [bugTitle, setBugTitle] = useState('') + const [bugDescription, setBugDescription] = useState('') + const [bugSubmitting, setBugSubmitting] = useState(false) const handleSearch = (query: string) => { setSearchQuery(query) @@ -182,6 +195,84 @@ export default function HelpPage() { setFilteredFaqs(filtered) } + const handleQuickAction = (action: string) => { + if (action === 'contact') { + setShowContactForm(true) + } else if (action === 'bug') { + setShowBugForm(true) + } + } + + const handleContactSubmit = async () => { + if (!contactSubject.trim() || !contactMessage.trim()) { + alert('Please fill in all fields') + return + } + + setContactSubmitting(true) + + try { + const response = await fetch('/api/support/contact', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + subject: contactSubject, + message: contactMessage, + }), + }) + + if (response.ok) { + alert('Message sent successfully! We\'ll get back to you soon.') + setContactSubject('') + setContactMessage('') + setShowContactForm(false) + } else { + const error = await response.json() + alert(error.error || 'Failed to send message. Please try again.') + } + } catch (error) { + console.error('Error sending contact message:', error) + alert('Failed to send message. Please try again.') + } finally { + setContactSubmitting(false) + } + } + + const handleBugSubmit = async () => { + if (!bugTitle.trim() || !bugDescription.trim()) { + alert('Please fill in all fields') + return + } + + setBugSubmitting(true) + + try { + const response = await fetch('/api/support/bug-report', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + title: bugTitle, + description: bugDescription, + }), + }) + + if (response.ok) { + alert('Bug report submitted successfully! Thank you for helping us improve.') + setBugTitle('') + setBugDescription('') + setShowBugForm(false) + } else { + const error = await response.json() + alert(error.error || 'Failed to submit bug report. Please try again.') + } + } catch (error) { + console.error('Error submitting bug report:', error) + alert('Failed to submit bug report. Please try again.') + } finally { + setBugSubmitting(false) + } + } + return (
{/* Header */} @@ -218,23 +309,49 @@ export default function HelpPage() {

Quick Actions

- {quickActions.map((action, index) => ( - - -
-
- -
-
- {action.title} - - {action.description} - -
-
-
-
- ))} + {quickActions.map((action, index) => { + if (action.href) { + return ( + + + +
+
+ +
+
+ {action.title} + + {action.description} + +
+
+
+
+ + ) + } + + return ( +
handleQuickAction(action.action || '')}> + + +
+
+ +
+
+ {action.title} + + {action.description} + +
+
+
+
+
+ ) + })}
)} @@ -318,7 +435,10 @@ export default function HelpPage() {

Saturday: 10:00 AM - 4:00 PM IST

- @@ -351,6 +471,120 @@ export default function HelpPage() { )} + + {/* Contact Support Dialog */} + {showContactForm && ( +
setShowContactForm(false)}> + e.stopPropagation()}> + + + + Contact Support + + + Send us a message and we'll get back to you soon + + + +
+ + setContactSubject(e.target.value)} + disabled={contactSubmitting} + className="bg-zinc-800 border-zinc-700 text-white placeholder:text-zinc-500" + /> +
+
+ +