Skip to content

Commit f9ac3a1

Browse files
committed
fix
2 parents 6b5da01 + 59aaf21 commit f9ac3a1

File tree

2 files changed

+262
-3
lines changed

2 files changed

+262
-3
lines changed

apps/dashboard/src/app/(app)/(dashboard)/support/page.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export default async function SupportPage() {
7171
]);
7272

7373
const teams = await getTeams();
74-
const team = teams?.[0];
74+
const _teamId = teams?.[0]?.id ?? undefined;
7575

7676
return (
7777
<main className="flex flex-col gap-12 pb-12">
@@ -92,7 +92,7 @@ export default async function SupportPage() {
9292
team.
9393
</p>
9494
<div className="mt-6 flex w-full flex-col items-center gap-3">
95-
{team && (
95+
{teams?.[0] && (
9696
<CustomChatButton
9797
authToken={authToken || undefined}
9898
clientId={undefined}
@@ -102,7 +102,7 @@ export default async function SupportPage() {
102102
label="Ask AI for support"
103103
networks="all"
104104
pageType="support"
105-
team={team}
105+
team={teams[0]}
106106
/>
107107
)}
108108

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/SupportCasesClient.tsx

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,156 @@
11
"use client";
22

33
import { format } from "date-fns";
4+
<<<<<<< HEAD
45
import { ArrowRightIcon, BotIcon, SendIcon } from "lucide-react";
56
import { useEffect, useRef, useState } from "react";
67
import { toast } from "sonner";
78
import type { SupportTicket } from "@/api/support";
89
import { 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+
>>>>>>> 59aaf21952093816decb52860e0d4524ad72d8a4
927
import type { Team } from "@/api/team";
1028
import { MarkdownRenderer } from "@/components/blocks/markdown-renderer";
1129
import { Reasoning } from "@/components/chat/Reasoning";
1230
import { Badge } from "@/components/ui/badge";
1331
import { Button } from "@/components/ui/button";
32+
<<<<<<< HEAD
33+
=======
34+
import { Skeleton } from "@/components/ui/skeleton";
35+
>>>>>>> 59aaf21952093816decb52860e0d4524ad72d8a4
1436
import { Textarea } from "@/components/ui/textarea";
1537
import { useDashboardRouter } from "@/lib/DashboardRouter";
1638
import { SupportAIChatCard } from "./SupportAIChatCard";
1739
import { SupportTabs } from "./SupportTabs";
40+
<<<<<<< HEAD
1841
import { 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+
>>>>>>> 59aaf21952093816decb52860e0d4524ad72d8a4
19154

20155
interface 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+
>>>>>>> 59aaf21952093816decb52860e0d4524ad72d8a4
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+
>>>>>>> 59aaf21952093816decb52860e0d4524ad72d8a4
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+
>>>>>>> 59aaf21952093816decb52860e0d4524ad72d8a4
600859
</div>
601860
)}
602861
</div>

0 commit comments

Comments
 (0)