Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import Link from "next/link";
import { redirect } from "next/navigation";
import { getThirdwebClient } from "../../../../../../@/constants/thirdweb.server";
import { mapV4ChainToV5Chain } from "../../../../../../contexts/map-chains";
import { NebulaFloatingChatButton } from "../../../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
import { NebulaChatButton } from "../../../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
import {
getAuthToken,
getAuthTokenWalletAddress,
Expand Down Expand Up @@ -99,7 +99,8 @@ The following is the user's message:

return (
<>
<NebulaFloatingChatButton
<NebulaChatButton
isFloating={true}
pageType="chain"
authToken={authToken ?? undefined}
label="Ask AI about this chain"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { localhost } from "thirdweb/chains";
import { getContractMetadata } from "thirdweb/extensions/common";
import { isAddress, isContractDeployed } from "thirdweb/utils";
import { shortenIfAddress } from "utils/usedapp-external";
import { NebulaFloatingChatButton } from "../../../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
import { NebulaChatButton } from "../../../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
import {
getAuthToken,
getAuthTokenWalletAddress,
Expand Down Expand Up @@ -114,7 +114,8 @@ The following is the user's message:`;
teamsAndProjects={teamsAndProjects}
client={client}
>
<NebulaFloatingChatButton
<NebulaChatButton
isFloating={true}
pageType="contract"
authToken={authToken ?? undefined}
label="Ask AI about this contract"
Expand Down
62 changes: 56 additions & 6 deletions apps/dashboard/src/app/(app)/(dashboard)/support/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { getThirdwebClient } from "@/constants/thirdweb.server";
import { BookOpenIcon, ChevronRightIcon } from "lucide-react";
import type { Metadata } from "next";
import Image from "next/image";
Expand All @@ -9,6 +10,11 @@ import contractsIcon from "../../../../../public/assets/support/contracts.png";
import engineIcon from "../../../../../public/assets/support/engine.png";
import miscIcon from "../../../../../public/assets/support/misc.svg";
import connectIcon from "../../../../../public/assets/support/wallets.png";
import { NebulaChatButton } from "../../../nebula-app/(app)/components/FloatingChat/FloatingChat";
import {
getAuthToken,
getAuthTokenWalletAddress,
} from "../../api/lib/getAuthToken";

export const metadata: Metadata = {
title: "thirdweb Support",
Expand Down Expand Up @@ -112,7 +118,26 @@ const HELP_PRODUCTS = [
},
] as const;

export default function SupportPage() {
export default async function SupportPage() {
const [authToken, accountAddress] = await Promise.all([
getAuthToken(),
getAuthTokenWalletAddress(),
]);

const client = getThirdwebClient({
jwt: authToken,
teamId: undefined,
});

const supportPromptPrefix =
"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: ";
const examplePrompts = [
"ERC20 - Transfer Amount Exceeds Allowance",
"Replacement transaction underpriced / Replacement fee too low",
"Nonce too low: next nonce #, tx nonce #",
"Nonce too high",
];

return (
<main className="flex flex-col gap-12 pb-12">
<div className="bg-gradient-to-b from-card/0 to-card py-20">
Expand All @@ -127,12 +152,37 @@ export default function SupportPage() {
How can we help?
</h1>
<p className="text-center text-lg text-muted-foreground">
Our dedicated support team is here to help you with any questions
or issues you may have. Contact us today and let us assist you.
Get instant answers with Nebula AI, our onchain support assistant.
Still need help? You can also create a support case to reach our
team.
</p>
<Button variant="default" className="mt-6" size="lg" asChild>
<Link href="/support/create-ticket">Get Support</Link>
</Button>
<div className="mt-6 flex w-full flex-col items-center gap-3">
<NebulaChatButton
isFloating={false}
pageType="support"
authToken={authToken ?? undefined}
label="Ask Nebula AI for support"
client={client}
nebulaParams={{
messagePrefix: supportPromptPrefix,
chainIds: [],
wallet: accountAddress ?? undefined,
}}
examplePrompts={examplePrompts.map((prompt) => ({
title: prompt,
message: prompt,
}))}
/>

<Link
href="/support/create-ticket"
target="_blank"
rel="noreferrer"
className="text-muted-foreground text-sm hover:underline"
>
Open a support case
</Link>
</div>
</div>
</header>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ import type { Meta, StoryObj } from "@storybook/react";
import { storybookThirdwebClient } from "stories/utils";
import { ThirdwebProvider } from "thirdweb/react";
import { examplePrompts } from "../../data/examplePrompts";
import { NebulaFloatingChatButton } from "./FloatingChat";
import { NebulaChatButton } from "./FloatingChat";

const meta = {
title: "Nebula/FloatingChat",
component: NebulaFloatingChatButton,
component: NebulaChatButton,
decorators: [
(Story) => (
<ThirdwebProvider>
<Story />
</ThirdwebProvider>
),
],
} satisfies Meta<typeof NebulaFloatingChatButton>;
} satisfies Meta<typeof NebulaChatButton>;

export default meta;
type Story = StoryObj<typeof NebulaFloatingChatButton>;
type Story = StoryObj<typeof NebulaChatButton>;

export const LoggedIn: Story = {
args: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ import { NebulaIcon } from "../../icons/NebulaIcon";

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

export function NebulaFloatingChatButton(props: {
pageType: "chain" | "contract";
export function NebulaChatButton(props: {
pageType: "chain" | "contract" | "support";
authToken: string | undefined;
examplePrompts: ExamplePrompt[];
label: string;
client: ThirdwebClient;
isFloating: boolean;
nebulaParams:
| {
messagePrefix: string;
Expand All @@ -47,25 +48,30 @@ export function NebulaFloatingChatButton(props: {

return (
<>
{!isOpen && (
<div className="fixed right-6 bottom-6 z-50 flex items-center gap-1.5">
<Button
onClick={() => {
setIsOpen(true);
setHasBeenOpened(true);
trackEvent({
category: "floating_nebula",
action: "click",
label: "open",
page: props.pageType,
});
}}
variant="default"
className="gap-2 rounded-full"
>
<NebulaIcon className="size-4" />
{props.label}
</Button>
<div
className={cn(
"flex items-center gap-1.5",
props.isFloating && "fixed right-6 bottom-6 z-50",
)}
>
<Button
onClick={() => {
setIsOpen(true);
setHasBeenOpened(true);
trackEvent({
category: "floating_nebula",
action: "click",
label: "open",
page: props.pageType,
});
}}
variant="default"
className="gap-2 rounded-full"
>
<NebulaIcon className="size-4" />
{props.label}
</Button>
{props.isFloating && (
<Button
variant="outline"
className="size-10 rounded-full bg-card p-0"
Expand All @@ -81,8 +87,8 @@ export function NebulaFloatingChatButton(props: {
>
<XIcon className="size-4" />
</Button>
</div>
)}
)}
</div>

<NebulaChatUIContainer
onClose={closeModal}
Expand All @@ -104,7 +110,7 @@ function NebulaChatUIContainer(props: {
hasBeenOpened: boolean;
authToken: string | undefined;
examplePrompts: ExamplePrompt[];
pageType: "chain" | "contract";
pageType: "chain" | "contract" | "support";
client: ThirdwebClient;
nebulaParams:
| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default function FloatingChatContent(props: {
authToken: string | undefined;
client: ThirdwebClient;
examplePrompts: ExamplePrompt[];
pageType: "chain" | "contract";
pageType: "chain" | "contract" | "support";
nebulaParams:
| {
messagePrefix: string;
Expand All @@ -52,7 +52,7 @@ export default function FloatingChatContent(props: {
function FloatingChatContentLoggedIn(props: {
authToken: string;
client: ThirdwebClient;
pageType: "chain" | "contract";
pageType: "chain" | "contract" | "support";
examplePrompts: ExamplePrompt[];
nebulaParams:
| {
Expand Down
Loading