Skip to content

Commit 7087b3f

Browse files
committed
Dashboard: add nebula chat on support page, update CTAs (#6862)
<!-- ## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes" If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000): ## Notes for the reviewer Anything important to call out? Be sure to also clarify these in your comments. ## How to test Unit tests, playground, etc. --> <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on enhancing the `FloatingChat` component by renaming it to `NebulaChatButton` and adding support for a new `support` page type. It also updates various components and their usage across the application to reflect this change. ### Detailed summary - Renamed `NebulaFloatingChatButton` to `NebulaChatButton`. - Added `support` as a new value for the `pageType` property. - Updated imports and component usage to reflect the new name. - Added `isFloating` prop to `NebulaChatButton`. - Modified `SupportPage` to utilize `NebulaChatButton` for support inquiries. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent bb554e5 commit 7087b3f

File tree

6 files changed

+98
-40
lines changed

6 files changed

+98
-40
lines changed

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/layout.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import Link from "next/link";
1919
import { redirect } from "next/navigation";
2020
import { getThirdwebClient } from "../../../../../../@/constants/thirdweb.server";
2121
import { mapV4ChainToV5Chain } from "../../../../../../contexts/map-chains";
22-
import { NebulaFloatingChatButton } from "../../../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
22+
import { NebulaChatButton } from "../../../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
2323
import {
2424
getAuthToken,
2525
getAuthTokenWalletAddress,
@@ -99,7 +99,8 @@ The following is the user's message:
9999

100100
return (
101101
<>
102-
<NebulaFloatingChatButton
102+
<NebulaChatButton
103+
isFloating={true}
103104
pageType="chain"
104105
authToken={authToken ?? undefined}
105106
label="Ask AI about this chain"

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/layout.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { localhost } from "thirdweb/chains";
88
import { getContractMetadata } from "thirdweb/extensions/common";
99
import { isAddress, isContractDeployed } from "thirdweb/utils";
1010
import { shortenIfAddress } from "utils/usedapp-external";
11-
import { NebulaFloatingChatButton } from "../../../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
11+
import { NebulaChatButton } from "../../../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
1212
import {
1313
getAuthToken,
1414
getAuthTokenWalletAddress,
@@ -114,7 +114,8 @@ The following is the user's message:`;
114114
teamsAndProjects={teamsAndProjects}
115115
client={client}
116116
>
117-
<NebulaFloatingChatButton
117+
<NebulaChatButton
118+
isFloating={true}
118119
pageType="contract"
119120
authToken={authToken ?? undefined}
120121
label="Ask AI about this contract"

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

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Button } from "@/components/ui/button";
22
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
3+
import { getThirdwebClient } from "@/constants/thirdweb.server";
34
import { BookOpenIcon, ChevronRightIcon } from "lucide-react";
45
import type { Metadata } from "next";
56
import Image from "next/image";
@@ -9,6 +10,11 @@ import contractsIcon from "../../../../../public/assets/support/contracts.png";
910
import engineIcon from "../../../../../public/assets/support/engine.png";
1011
import miscIcon from "../../../../../public/assets/support/misc.svg";
1112
import connectIcon from "../../../../../public/assets/support/wallets.png";
13+
import { NebulaChatButton } from "../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
14+
import {
15+
getAuthToken,
16+
getAuthTokenWalletAddress,
17+
} from "../../api/lib/getAuthToken";
1218

1319
export const metadata: Metadata = {
1420
title: "thirdweb Support",
@@ -112,7 +118,26 @@ const HELP_PRODUCTS = [
112118
},
113119
] as const;
114120

115-
export default function SupportPage() {
121+
export default async function SupportPage() {
122+
const [authToken, accountAddress] = await Promise.all([
123+
getAuthToken(),
124+
getAuthTokenWalletAddress(),
125+
]);
126+
127+
const client = getThirdwebClient({
128+
jwt: authToken,
129+
teamId: undefined,
130+
});
131+
132+
const supportPromptPrefix =
133+
"You are a Customer Success Agent at thirdweb, assisting customers with blockchain and Web3-related issues. Use the following details to craft a professional, empathetic response: ";
134+
const examplePrompts = [
135+
"ERC20 - Transfer Amount Exceeds Allowance",
136+
"Replacement transaction underpriced / Replacement fee too low",
137+
"Nonce too low: next nonce #, tx nonce #",
138+
"Nonce too high",
139+
];
140+
116141
return (
117142
<main className="flex flex-col gap-12 pb-12">
118143
<div className="bg-gradient-to-b from-card/0 to-card py-20">
@@ -127,12 +152,37 @@ export default function SupportPage() {
127152
How can we help?
128153
</h1>
129154
<p className="text-center text-lg text-muted-foreground">
130-
Our dedicated support team is here to help you with any questions
131-
or issues you may have. Contact us today and let us assist you.
155+
Get instant answers with Nebula AI, our onchain support assistant.
156+
Still need help? You can also create a support case to reach our
157+
team.
132158
</p>
133-
<Button variant="default" className="mt-6" size="lg" asChild>
134-
<Link href="/support/create-ticket">Get Support</Link>
135-
</Button>
159+
<div className="mt-6 flex w-full flex-col items-center gap-3">
160+
<NebulaChatButton
161+
isFloating={false}
162+
pageType="support"
163+
authToken={authToken ?? undefined}
164+
label="Ask Nebula AI for support"
165+
client={client}
166+
nebulaParams={{
167+
messagePrefix: supportPromptPrefix,
168+
chainIds: [],
169+
wallet: accountAddress ?? undefined,
170+
}}
171+
examplePrompts={examplePrompts.map((prompt) => ({
172+
title: prompt,
173+
message: prompt,
174+
}))}
175+
/>
176+
177+
<Link
178+
href="/support/create-ticket"
179+
target="_blank"
180+
rel="noreferrer"
181+
className="text-muted-foreground text-sm hover:underline"
182+
>
183+
Open a support case
184+
</Link>
185+
</div>
136186
</div>
137187
</header>
138188
</div>

apps/dashboard/src/app/nebula-app/(app)/components/FloatingChat/FloatingChat.stories.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@ import type { Meta, StoryObj } from "@storybook/react";
22
import { storybookThirdwebClient } from "stories/utils";
33
import { ThirdwebProvider } from "thirdweb/react";
44
import { examplePrompts } from "../../data/examplePrompts";
5-
import { NebulaFloatingChatButton } from "./FloatingChat";
5+
import { NebulaChatButton } from "./FloatingChat";
66

77
const meta = {
88
title: "Nebula/FloatingChat",
9-
component: NebulaFloatingChatButton,
9+
component: NebulaChatButton,
1010
decorators: [
1111
(Story) => (
1212
<ThirdwebProvider>
1313
<Story />
1414
</ThirdwebProvider>
1515
),
1616
],
17-
} satisfies Meta<typeof NebulaFloatingChatButton>;
17+
} satisfies Meta<typeof NebulaChatButton>;
1818

1919
export default meta;
20-
type Story = StoryObj<typeof NebulaFloatingChatButton>;
20+
type Story = StoryObj<typeof NebulaChatButton>;
2121

2222
export const LoggedIn: Story = {
2323
args: {

apps/dashboard/src/app/nebula-app/(app)/components/FloatingChat/FloatingChat.tsx

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ import { NebulaIcon } from "../../icons/NebulaIcon";
2121

2222
const LazyFloatingChatContent = lazy(() => import("./FloatingChatContent"));
2323

24-
export function NebulaFloatingChatButton(props: {
25-
pageType: "chain" | "contract";
24+
export function NebulaChatButton(props: {
25+
pageType: "chain" | "contract" | "support";
2626
authToken: string | undefined;
2727
examplePrompts: ExamplePrompt[];
2828
label: string;
2929
client: ThirdwebClient;
30+
isFloating: boolean;
3031
nebulaParams:
3132
| {
3233
messagePrefix: string;
@@ -47,25 +48,30 @@ export function NebulaFloatingChatButton(props: {
4748

4849
return (
4950
<>
50-
{!isOpen && (
51-
<div className="fixed right-6 bottom-6 z-50 flex items-center gap-1.5">
52-
<Button
53-
onClick={() => {
54-
setIsOpen(true);
55-
setHasBeenOpened(true);
56-
trackEvent({
57-
category: "floating_nebula",
58-
action: "click",
59-
label: "open",
60-
page: props.pageType,
61-
});
62-
}}
63-
variant="default"
64-
className="gap-2 rounded-full"
65-
>
66-
<NebulaIcon className="size-4" />
67-
{props.label}
68-
</Button>
51+
<div
52+
className={cn(
53+
"flex items-center gap-1.5",
54+
props.isFloating && "fixed right-6 bottom-6 z-50",
55+
)}
56+
>
57+
<Button
58+
onClick={() => {
59+
setIsOpen(true);
60+
setHasBeenOpened(true);
61+
trackEvent({
62+
category: "floating_nebula",
63+
action: "click",
64+
label: "open",
65+
page: props.pageType,
66+
});
67+
}}
68+
variant="default"
69+
className="gap-2 rounded-full"
70+
>
71+
<NebulaIcon className="size-4" />
72+
{props.label}
73+
</Button>
74+
{props.isFloating && (
6975
<Button
7076
variant="outline"
7177
className="size-10 rounded-full bg-card p-0"
@@ -81,8 +87,8 @@ export function NebulaFloatingChatButton(props: {
8187
>
8288
<XIcon className="size-4" />
8389
</Button>
84-
</div>
85-
)}
90+
)}
91+
</div>
8692

8793
<NebulaChatUIContainer
8894
onClose={closeModal}
@@ -104,7 +110,7 @@ function NebulaChatUIContainer(props: {
104110
hasBeenOpened: boolean;
105111
authToken: string | undefined;
106112
examplePrompts: ExamplePrompt[];
107-
pageType: "chain" | "contract";
113+
pageType: "chain" | "contract" | "support";
108114
client: ThirdwebClient;
109115
nebulaParams:
110116
| {

apps/dashboard/src/app/nebula-app/(app)/components/FloatingChat/FloatingChatContent.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default function FloatingChatContent(props: {
2525
authToken: string | undefined;
2626
client: ThirdwebClient;
2727
examplePrompts: ExamplePrompt[];
28-
pageType: "chain" | "contract";
28+
pageType: "chain" | "contract" | "support";
2929
nebulaParams:
3030
| {
3131
messagePrefix: string;
@@ -52,7 +52,7 @@ export default function FloatingChatContent(props: {
5252
function FloatingChatContentLoggedIn(props: {
5353
authToken: string;
5454
client: ThirdwebClient;
55-
pageType: "chain" | "contract";
55+
pageType: "chain" | "contract" | "support";
5656
examplePrompts: ExamplePrompt[];
5757
nebulaParams:
5858
| {

0 commit comments

Comments
 (0)