11"use client" ;
22
33import { format } from "date-fns" ;
4+ < < << << < HEAD
45import { ArrowRightIcon , BotIcon , SendIcon } from "lucide-react" ;
56import { useEffect , useRef , useState } from "react" ;
67import { toast } from "sonner" ;
78import type { SupportTicket } from "@/api/support" ;
89import { getSupportTicket , sendMessageToTicket } from "@/api/support" ;
10+ = === ===
11+ import {
12+ ArrowRightIcon ,
13+ BotIcon ,
14+ LoaderCircleIcon ,
15+ SendIcon ,
16+ } from "lucide-react" ;
17+ import dynamic from "next/dynamic" ;
18+ import { useEffect , useRef , useState } from "react" ;
19+ import { toast } from "sonner" ;
20+ import type { SupportTicket } from "@/api/support" ;
21+ import {
22+ createSupportTicket ,
23+ getSupportTicket ,
24+ sendMessageToTicket ,
25+ } from "@/api/support" ;
26+ > >>> >>> 59 aaf21952093816decb52860e0d4524ad72d8a4
927import type { Team } from "@/api/team" ;
1028import { MarkdownRenderer } from "@/components/blocks/markdown-renderer" ;
1129import { Reasoning } from "@/components/chat/Reasoning" ;
1230import { Badge } from "@/components/ui/badge" ;
1331import { Button } from "@/components/ui/button" ;
32+ < < << << < HEAD
33+ = === ===
34+ import { Skeleton } from "@/components/ui/skeleton" ;
35+ >>> >>> > 59 aaf21952093816decb52860e0d4524ad72d8a4
1436import { Textarea } from "@/components/ui/textarea" ;
1537import { useDashboardRouter } from "@/lib/DashboardRouter" ;
1638import { SupportAIChatCard } from "./SupportAIChatCard" ;
1739import { SupportTabs } from "./SupportTabs" ;
40+ < < << << < HEAD
1841import { SupportTicketForm } from "./SupportTicketForm" ;
42+ = === ===
43+ import { SupportForm_SelectInput } from "./shared/SupportForm_SelectInput" ;
44+
45+ // Dynamic imports for contact forms using named exports
46+ const ConnectSupportForm = dynamic (
47+ ( ) => import ( "./contact-forms/connect" ) . then ( ( mod ) => mod . ConnectSupportForm ) ,
48+ {
49+ loading : ( ) => < Skeleton className = "h-12" /> ,
50+ ssr : false ,
51+ } ,
52+ ) ;
53+ const EngineSupportForm = dynamic (
54+ ( ) => import ( "./contact-forms/engine" ) . then ( ( mod ) => mod . EngineSupportForm ) ,
55+ {
56+ loading : ( ) => < Skeleton className = "h-12" /> ,
57+ ssr : false ,
58+ } ,
59+ ) ;
60+ const ContractSupportForm = dynamic (
61+ ( ) =>
62+ import ( "./contact-forms/contracts" ) . then ( ( mod ) => mod . ContractSupportForm ) ,
63+ {
64+ loading : ( ) => < Skeleton className = "h-12" /> ,
65+ ssr : false ,
66+ } ,
67+ ) ;
68+ const AccountSupportForm = dynamic (
69+ ( ) => import ( "./contact-forms/account" ) . then ( ( mod ) => mod . AccountSupportForm ) ,
70+ {
71+ loading : ( ) => < Skeleton className = "h-12" /> ,
72+ ssr : false ,
73+ } ,
74+ ) ;
75+ const OtherSupportForm = dynamic (
76+ ( ) => import ( "./contact-forms/other" ) . then ( ( mod ) => mod . OtherSupportForm ) ,
77+ {
78+ loading : ( ) => < Skeleton className = "h-12" /> ,
79+ ssr : false ,
80+ } ,
81+ ) ;
82+ const PaymentsSupportForm = dynamic (
83+ ( ) =>
84+ import ( "./contact-forms/payments" ) . then ( ( mod ) => mod . PaymentsSupportForm ) ,
85+ {
86+ loading : ( ) => < Skeleton className = "h-12" /> ,
87+ ssr : false ,
88+ } ,
89+ ) ;
90+ const TokensMarketplaceSupportForm = dynamic (
91+ ( ) =>
92+ import ( "./contact-forms/tokens-marketplace" ) . then (
93+ ( mod ) => mod . TokensMarketplaceSupportForm ,
94+ ) ,
95+ {
96+ loading : ( ) => < Skeleton className = "h-12" /> ,
97+ ssr : false ,
98+ } ,
99+ ) ;
100+
101+ const productOptions = [
102+ {
103+ component : < ConnectSupportForm /> ,
104+ label : "Wallets" ,
105+ } ,
106+ {
107+ component : < EngineSupportForm /> ,
108+ label : "Transactions" ,
109+ } ,
110+ {
111+ component : < PaymentsSupportForm /> ,
112+ label : "Payments" ,
113+ } ,
114+ {
115+ component : < ContractSupportForm /> ,
116+ label : "Contracts" ,
117+ } ,
118+ {
119+ component : < TokensMarketplaceSupportForm /> ,
120+ label : "Tokens / Marketplace" ,
121+ } ,
122+ {
123+ component : < AccountSupportForm /> ,
124+ label : "Account" ,
125+ } ,
126+ {
127+ component : < OtherSupportForm /> ,
128+ label : "Other" ,
129+ } ,
130+ ] ;
131+
132+ function ProductAreaSelection ( props : {
133+ productLabel : string ;
134+ setProductLabel : ( val : string ) => void ;
135+ } ) {
136+ const { productLabel, setProductLabel } = props ;
137+
138+ return (
139+ < div className = "flex flex-col gap-6" >
140+ < SupportForm_SelectInput
141+ formLabel = "What do you need help with?"
142+ name = "product"
143+ onValueChange = { setProductLabel }
144+ options = { productOptions . map ( ( o ) => o . label ) }
145+ promptText = "Brief description of your issue"
146+ required = { true }
147+ value = { productLabel }
148+ />
149+ { productOptions . find ( ( o ) => o . label === productLabel ) ?. component }
150+ </ div >
151+ ) ;
152+ }
153+ >>> > >>> 59 aaf21952093816decb52860e0d4524ad72d8a4
19154
20155interface SupportCasesClientProps {
21156 tickets : SupportTicket [ ] ;
@@ -59,7 +194,13 @@ export default function SupportCasesClient({
59194 // Form states
60195 const [ showCreateForm , setShowCreateForm ] = useState ( false ) ;
61196 const [ productLabel , setProductLabel ] = useState ( "" ) ;
197+ < < << << < HEAD
62198 const [ _isSubmittingForm , _setIsSubmittingFormm ] = useState ( false ) ;
199+ = === ===
200+ const [ isSubmittingForm , setIsSubmittingForm ] = useState ( false ) ;
201+ const formRef = useRef < HTMLFormElement > ( null ) ;
202+ const _formContainerRef = useRef < HTMLDivElement > ( null ) ;
203+ > >>> >>> 59 aaf21952093816decb52860e0d4524ad72d8a4
63204
64205 const selectedCase =
65206 selectedCaseDetails || tickets . find ( ( c ) => c . id === selectedCaseId ) ;
@@ -160,6 +301,82 @@ export default function SupportCasesClient({
160301 }
161302 } , [ showAIChat ] ) ;
162303
304+ < < << << < HEAD
305+ = === ===
306+ const handleFormSubmit = async ( e : React . FormEvent ) => {
307+ e . preventDefault ( ) ;
308+
309+ if ( ! productLabel ) {
310+ toast . error ( "Please select what you need help with" ) ;
311+ return ;
312+ }
313+
314+ if ( ! formRef . current ) return ;
315+ const formData = new FormData ( formRef . current ) ;
316+ const description = formData . get ( "markdown" ) as string ;
317+
318+ if ( ! description ?. trim ( ) ) {
319+ toast . error ( "Please provide a description" ) ;
320+ return ;
321+ }
322+
323+ setIsSubmittingForm ( true ) ;
324+
325+ try {
326+ // Get all extra fields from the form
327+ const extraFields = Array . from ( formData . entries ( ) ) . filter ( ( [ key ] ) =>
328+ key . startsWith ( "extraInfo_" ) ,
329+ ) ;
330+
331+ // Format the message
332+ let formattedMessage = `Email: ${ String ( team . billingEmail ?? "-" ) } \nName: ${ String ( team . name ?? "-" ) } \nProduct: ${ String ( productLabel ?? "-" ) } ` ;
333+
334+ // Add all extra fields above the message
335+ if ( extraFields . length > 0 ) {
336+ extraFields . forEach ( ( [ key , value ] ) => {
337+ if ( value ) {
338+ const fieldName = key . replace ( "extraInfo_" , "" ) . replace ( / _ / g, " " ) ;
339+ formattedMessage += `\n${ fieldName } : ${ String ( value ) } ` ;
340+ }
341+ } ) ;
342+ }
343+
344+ formattedMessage += `\nMessage:\n${ String ( description ?? "-" ) } ` ;
345+
346+ if ( conversationId ) {
347+ formattedMessage += `\n\n---\nAI Conversation ID: ${ conversationId } ` ;
348+ }
349+
350+ await createSupportTicket ( {
351+ message : formattedMessage ,
352+ teamSlug : team . slug ,
353+ title : `${ productLabel } Issue - ${ team . billingEmail } (${ team . billingPlan } )` ,
354+ } ) ;
355+
356+ // Add success message to chat
357+ const successMsg = {
358+ content :
359+ "Great! Your support case has been created successfully. Our technical team will review it and get back to you soon. You can continue chatting with me if you have any other questions." ,
360+ id : Date . now ( ) ,
361+ isUser : false ,
362+ timestamp : new Date ( ) . toISOString ( ) ,
363+ isSuccessMessage : true ,
364+ } ;
365+
366+ setChatMessages ( ( msgs ) => [ ...msgs , successMsg ] ) ;
367+ setShowCreateForm ( false ) ;
368+ setProductLabel ( "" ) ;
369+
370+ toast . success ( "Support ticket created successfully!" ) ;
371+ } catch ( error ) {
372+ console . error ( "Error creating support ticket:" , error ) ;
373+ toast . error ( "Failed to create support ticket. Please try again." ) ;
374+ } finally {
375+ setIsSubmittingForm ( false ) ;
376+ }
377+ } ;
378+
379+ > >>> >>> 59 aaf21952093816decb52860e0d4524ad72d8a4
163380 const handleSelectCase = async ( ticketId : string ) => {
164381 setSelectedCaseId ( ticketId ) ;
165382 setSelectedCaseDetails ( null ) ;
@@ -577,6 +794,7 @@ export default function SupportCasesClient({
577794 </ p >
578795 </ div >
579796
797+ < < << << < HEAD
580798 < SupportTicketForm
581799 team = { team }
582800 productLabel = { productLabel }
@@ -597,6 +815,47 @@ export default function SupportCasesClient({
597815 ] ) ;
598816 } }
599817 />
818+ =======
819+ < form
820+ onSubmit = { handleFormSubmit }
821+ ref = { formRef }
822+ className = "space-y-4"
823+ >
824+ < ProductAreaSelection
825+ productLabel = { productLabel }
826+ setProductLabel = { setProductLabel }
827+ />
828+
829+ { /* Submit Buttons */ }
830+ < div className = "flex justify-end gap-3 pt-2" >
831+ < Button
832+ type = "button"
833+ variant = "outline"
834+ onClick = { ( ) => setShowCreateForm ( false ) }
835+ className = "border-[#333333] bg-[#0A0A0A] text-white hover:bg-[#333333] hover:text-white"
836+ size = "sm"
837+ disabled = { isSubmittingForm }
838+ >
839+ Cancel
840+ </ Button >
841+ < Button
842+ type = "submit"
843+ className = "bg-[#2663EB] hover:bg-[#2663EB]/80 text-white transition-opacity"
844+ size = "sm"
845+ disabled = { isSubmittingForm }
846+ >
847+ { isSubmittingForm ? (
848+ < >
849+ < LoaderCircleIcon className = "animate-spin w-4 h-4 mr-2 inline" />
850+ Creating...
851+ </ >
852+ ) : (
853+ "Create Support Case"
854+ ) }
855+ </ Button >
856+ </ div >
857+ </ form >
858+ >>> >>> > 59 aaf21952093816decb52860e0d4524ad72d8a4
600859 </ div >
601860 ) }
602861 </ div >
0 commit comments