From 28ea9a994bb06766a3b453d659afc43f0ace0ce9 Mon Sep 17 00:00:00 2001 From: 1sraeliteX Date: Fri, 29 May 2026 19:22:08 +0100 Subject: [PATCH] feat(profile): add Customer Support tab to Profile page (#467) - Add CustomerSupportPanel component with three sections: - Contact options (email, live chat, phone) as accessible links - FAQ accordion with 5 common questions (keyboard accessible) - Contact form with subject + message fields and success state - Extend ProfileTabId union type to include 'support' - Add supportFaqs and supportContactOptions data to profile-data.ts - Lazy-load CustomerSupportPanel via next/dynamic with skeleton fallback - Full ARIA compliance: role=tabpanel, aria-expanded, aria-controls, aria-labelledby, role=status, aria-live, role=alert - Follows existing panel patterns (SettingsPanel, AchievementsPanel) --- .../components/CustomerSupportPanel.tsx | 214 ++++++++++++++++++ src/app/profile/components/ProfileTabs.tsx | 5 + src/app/profile/profile-data.ts | 80 ++++++- 3 files changed, 298 insertions(+), 1 deletion(-) create mode 100644 src/app/profile/components/CustomerSupportPanel.tsx diff --git a/src/app/profile/components/CustomerSupportPanel.tsx b/src/app/profile/components/CustomerSupportPanel.tsx new file mode 100644 index 00000000..a812d3cd --- /dev/null +++ b/src/app/profile/components/CustomerSupportPanel.tsx @@ -0,0 +1,214 @@ +'use client'; + +import { memo, useCallback, useState } from 'react'; +import { ChevronDown, ChevronUp, Mail, MessageCircle, Phone } from 'lucide-react'; +import { supportFaqs, supportContactOptions } from '../profile-data'; + +// ── FAQ Accordion Item ──────────────────────────────────────────────────────── + +interface FaqItemProps { + id: string; + question: string; + answer: string; +} + +function FaqItem({ id, question, answer }: FaqItemProps) { + const [isOpen, setIsOpen] = useState(false); + const headingId = `faq-heading-${id}`; + const panelId = `faq-panel-${id}`; + + const toggle = useCallback(() => setIsOpen((prev) => !prev), []); + + return ( +
+

+ +

+ + +
+ ); +} + +// ── Contact Form ────────────────────────────────────────────────────────────── + +type SubmitState = 'idle' | 'submitting' | 'success' | 'error'; + +function ContactForm() { + const [submitState, setSubmitState] = useState('idle'); + const [subject, setSubject] = useState(''); + const [message, setMessage] = useState(''); + + const handleSubmit = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + setSubmitState('submitting'); + + // Simulated async submission — replace with real API call + await new Promise((resolve) => setTimeout(resolve, 1200)); + + setSubmitState('success'); + setSubject(''); + setMessage(''); + }, + [], + ); + + if (submitState === 'success') { + return ( +
+

+ ✅ Your message has been sent. We'll get back to you within 24 hours. +

+ +
+ ); + } + + return ( +
+
+ + setSubject(e.target.value)} + placeholder="Briefly describe your issue" + className="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-transparent focus:ring-2 focus:ring-blue-500" + /> +
+ +
+ +