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
235 changes: 121 additions & 114 deletions apps/dashboard/src/app/pay/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ShieldCheckIcon } from "lucide-react";
import type { Metadata } from "next";
import { ThemeProvider } from "next-themes";
import { Bridge, defineChain, toTokens } from "thirdweb";
import { getChainMetadata } from "thirdweb/chains";
import { shortenAddress } from "thirdweb/utils";
Expand Down Expand Up @@ -80,131 +81,137 @@ export default async function PayPage({
}

return (
<div className="flex z-10 flex-col lg:flex-row h-full w-full">
<header className="min-w-full lg:min-w-[500px] border-b lg:border-r lg:h-full bg-card flex flex-col gap-4 items-start p-4 lg:p-8">
<div>
<div className="flex flex-row items-center justify-start gap-4">
{projectMetadata.image && (
<img
src={
resolveSchemeWithErrorHandler({
uri: projectMetadata.image,
client: payAppThirdwebClient,
}) || ""
}
alt={projectMetadata.name}
width={25}
height={25}
className="rounded-full overflow-hidden"
/>
<ThemeProvider
forcedTheme={theme === "light" ? "light" : "dark"}
attribute="class"
disableTransitionOnChange
enableSystem={false}
>
<div className="flex z-10 flex-col lg:flex-row h-full w-full">
<header className="min-w-full lg:min-w-[500px] border-b lg:border-r lg:h-full bg-card flex flex-col gap-4 items-start p-4 lg:p-8">
<div>
<div className="flex flex-row items-center justify-start gap-4">
{projectMetadata.image && (
<img
src={
resolveSchemeWithErrorHandler({
uri: projectMetadata.image,
client: payAppThirdwebClient,
}) || ""
}
alt={projectMetadata.name}
width={25}
height={25}
className="rounded-full overflow-hidden"
/>
)}
<h2 className="text-xl font-bold">{projectMetadata.name}</h2>
</div>
{projectMetadata.description && (
<p className="mt-2 text-sm text-muted-foreground">
{projectMetadata.description}
</p>
)}
<h2 className="text-xl font-bold">{projectMetadata.name}</h2>
</div>
{projectMetadata.description && (
<p className="mt-2 text-sm text-muted-foreground">
{projectMetadata.description}
</p>
)}
</div>

<div className="hidden lg:block my-4 w-full">
{paymentLink.amount && (
<div className="flex flex-col gap-1 w-full my-4">
<span className="text-muted-foreground text-xs">Details</span>
<div className="font-medium flex-row flex justify-between items-center w-full">
<div className="flex flex-row items-center gap-2">
{token.iconUri && (
<img
src={resolveSchemeWithErrorHandler({
uri: token.iconUri,
client: getConfiguredThirdwebClient({
secretKey: DASHBOARD_THIRDWEB_SECRET_KEY,
teamId: undefined,
}),
})}
alt={token.name}
width={25}
height={25}
className="size-5 rounded-full overflow-hidden"
/>
)}
{toTokens(BigInt(paymentLink.amount), token.decimals)}{" "}
{token.symbol}
</div>
{token.prices.USD && (
<span>
$
{(
Number(token.prices.USD) *
Number(
toTokens(BigInt(paymentLink.amount), token.decimals),
)
).toFixed(2)}
</span>
)}
</div>
</div>
)}
{chain && (
<div className="flex flex-col gap-1 w-full my-4">
<span className="text-muted-foreground text-xs">Network</span>
<div className="font-medium flex-row flex justify-between items-center w-full">
<div className="flex flex-row items-center gap-2">
{chain.icon?.url && (
<img
src={resolveSchemeWithErrorHandler({
uri: chain.icon.url,
client: getConfiguredThirdwebClient({
secretKey: DASHBOARD_THIRDWEB_SECRET_KEY,
teamId: undefined,
}),
})}
alt={chain.name}
width={chain.icon.width}
height={chain.icon.height}
className="size-5 rounded-full overflow-hidden"
/>
<div className="hidden lg:block my-4 w-full">
{paymentLink.amount && (
<div className="flex flex-col gap-1 w-full my-4">
<span className="text-muted-foreground text-xs">Details</span>
<div className="font-medium flex-row flex justify-between items-center w-full">
<div className="flex flex-row items-center gap-2">
{token.iconUri && (
<img
src={resolveSchemeWithErrorHandler({
uri: token.iconUri,
client: getConfiguredThirdwebClient({
secretKey: DASHBOARD_THIRDWEB_SECRET_KEY,
teamId: undefined,
}),
})}
alt={token.name}
width={25}
height={25}
className="size-5 rounded-full overflow-hidden"
/>
)}
{toTokens(BigInt(paymentLink.amount), token.decimals)}{" "}
{token.symbol}
</div>
{token.prices.USD && (
<span>
$
{(
Number(token.prices.USD) *
Number(
toTokens(BigInt(paymentLink.amount), token.decimals),
)
).toFixed(2)}
</span>
)}
{chain.name}
</div>
</div>
</div>
)}
{recipientEnsOrAddress.ensName ||
(recipientEnsOrAddress.address && (
)}
{chain && (
<div className="flex flex-col gap-1 w-full my-4">
<span className="text-muted-foreground text-xs">Seller</span>
<span className="text-muted-foreground text-xs">Network</span>
<div className="font-medium flex-row flex justify-between items-center w-full">
{recipientEnsOrAddress.ensName ??
shortenAddress(recipientEnsOrAddress.address)}
<div className="flex flex-row items-center gap-2">
{chain.icon?.url && (
<img
src={resolveSchemeWithErrorHandler({
uri: chain.icon.url,
client: getConfiguredThirdwebClient({
secretKey: DASHBOARD_THIRDWEB_SECRET_KEY,
teamId: undefined,
}),
})}
alt={chain.name}
width={chain.icon.width}
height={chain.icon.height}
className="size-5 rounded-full overflow-hidden"
/>
)}
{chain.name}
</div>
</div>
</div>
))}
</div>
)}
{recipientEnsOrAddress.ensName ||
(recipientEnsOrAddress.address && (
<div className="flex flex-col gap-1 w-full my-4">
<span className="text-muted-foreground text-xs">Seller</span>
<div className="font-medium flex-row flex justify-between items-center w-full">
{recipientEnsOrAddress.ensName ??
shortenAddress(recipientEnsOrAddress.address)}
</div>
</div>
))}
Comment on lines +180 to +189
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix the conditional rendering logic.

The current conditional has a logic error that will render the ENS name as raw text instead of within the styled JSX structure when an ENS name exists.

Current behavior:

  • If ensName is truthy: renders the string directly (breaks UI)
  • If ensName is falsy but address exists: renders the JSX (correct)

Apply this diff to fix the logic:

-            {recipientEnsOrAddress.ensName ||
-              (recipientEnsOrAddress.address && (
+            {(recipientEnsOrAddress.ensName || recipientEnsOrAddress.address) && (
                 <div className="flex flex-col gap-1 w-full my-4">
                   <span className="text-muted-foreground text-xs">Seller</span>
                   <div className="font-medium flex-row flex justify-between items-center w-full">
                     {recipientEnsOrAddress.ensName ??
                       shortenAddress(recipientEnsOrAddress.address)}
                   </div>
                 </div>
-              ))}
+             )}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{recipientEnsOrAddress.ensName ||
(recipientEnsOrAddress.address && (
<div className="flex flex-col gap-1 w-full my-4">
<span className="text-muted-foreground text-xs">Seller</span>
<div className="font-medium flex-row flex justify-between items-center w-full">
{recipientEnsOrAddress.ensName ??
shortenAddress(recipientEnsOrAddress.address)}
</div>
</div>
))}
{(recipientEnsOrAddress.ensName || recipientEnsOrAddress.address) && (
<div className="flex flex-col gap-1 w-full my-4">
<span className="text-muted-foreground text-xs">Seller</span>
<div className="font-medium flex-row flex justify-between items-center w-full">
{recipientEnsOrAddress.ensName ??
shortenAddress(recipientEnsOrAddress.address)}
</div>
</div>
)}
🤖 Prompt for AI Agents
In apps/dashboard/src/app/pay/[id]/page.tsx around lines 180 to 189, the
top-level conditional currently returns the raw ensName string when ensName is
truthy instead of rendering the styled JSX; change the conditional so that the
JSX block is rendered whenever either ensName or address exists (e.g., check
recipientEnsOrAddress.ensName || recipientEnsOrAddress.address), and inside that
JSX use {recipientEnsOrAddress.ensName ??
shortenAddress(recipientEnsOrAddress.address)} to display the ENS name or the
shortened address.

</div>

<div className="mt-auto hidden lg:block">
<Badge className="flex items-center gap-1.5 bg-purple-100 text-purple-800 border-purple-200 dark:bg-purple-950 dark:text-purple-300 dark:border-purple-800">
<ShieldCheckIcon className="size-3" />
Secured by thirdweb
</Badge>
</div>
</header>
<main className="flex justify-center p-12 w-full items-center">
<PayPageWidget
amount={paymentLink.amount ? BigInt(paymentLink.amount) : undefined}
chainId={Number(paymentLink.destinationToken.chainId)}
clientId={undefined} // Payment links don't need to use the same client ID to be executed
image={paymentLink.imageUrl}
name={paymentLink.title}
paymentLinkId={id}
purchaseData={paymentLink.purchaseData}
recipientAddress={paymentLink.receiver}
redirectUri={redirectUri}
theme={theme}
token={token}
/>
</main>
</div>
<div className="mt-auto hidden lg:block">
<Badge className="flex items-center gap-1.5 bg-purple-100 text-purple-800 border-purple-200 dark:bg-purple-950 dark:text-purple-300 dark:border-purple-800">
<ShieldCheckIcon className="size-3" />
Secured by thirdweb
</Badge>
</div>
</header>
<main className="flex justify-center p-12 w-full items-center">
<PayPageWidget
amount={paymentLink.amount ? BigInt(paymentLink.amount) : undefined}
chainId={Number(paymentLink.destinationToken.chainId)}
clientId={undefined} // Payment links don't need to use the same client ID to be executed
image={paymentLink.imageUrl}
name={paymentLink.title}
paymentLinkId={id}
purchaseData={paymentLink.purchaseData}
recipientAddress={paymentLink.receiver}
redirectUri={redirectUri}
token={token}
/>
</main>
</div>
</ThemeProvider>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client";
import { payAppThirdwebClient } from "app/pay/constants";
import { useTheme } from "next-themes";
import { useEffect } from "react";
import { createThirdwebClient, NATIVE_TOKEN_ADDRESS, toTokens } from "thirdweb";
import { AutoConnect, CheckoutWidget } from "thirdweb/react";
import { checksumAddress } from "thirdweb/utils";
Expand All @@ -11,6 +10,7 @@ import {
reportPaymentLinkBuySuccessful,
} from "@/analytics/report";
import { useV5DashboardChain } from "@/hooks/chains/v5-adapter";
import { getSDKTheme } from "@/utils/sdk-component-theme";

export function PayPageWidget({
chainId,
Expand All @@ -21,7 +21,6 @@ export function PayPageWidget({
name,
image,
redirectUri,
theme,
purchaseData,
clientId,
}: {
Expand All @@ -34,17 +33,10 @@ export function PayPageWidget({
image?: string;
redirectUri?: string;
clientId: string | undefined;
theme?: "light" | "dark";
purchaseData: Record<string, unknown> | undefined;
}) {
const { theme: browserTheme, setTheme } = useTheme();
const { theme } = useTheme();

// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
if (theme) {
setTheme(theme);
}
}, [theme, setTheme]);
const chain = useV5DashboardChain(chainId);

return (
Expand All @@ -55,6 +47,7 @@ export function PayPageWidget({
}
/>
<CheckoutWidget
theme={getSDKTheme(theme === "light" ? "light" : "dark")}
connectOptions={{
wallets: [
createWallet("io.metamask"),
Expand Down Expand Up @@ -87,7 +80,6 @@ export function PayPageWidget({
paymentLinkId={paymentLinkId}
purchaseData={purchaseData}
seller={checksumAddress(recipientAddress)}
theme={theme ?? (browserTheme === "light" ? "light" : "dark")}
tokenAddress={
token.address === NATIVE_TOKEN_ADDRESS
? undefined
Expand Down
14 changes: 3 additions & 11 deletions apps/dashboard/src/app/pay/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import "@workspace/ui/global.css";
import { Inter } from "next/font/google";
import { ThemeProvider } from "next-themes";
import { cn } from "@/lib/utils";
import { PayProviders } from "./components/client/Providers.client";

Expand All @@ -24,16 +23,9 @@ export default async function PayLayout({
)}
>
<PayProviders>
<ThemeProvider
attribute="class"
defaultTheme="dark"
disableTransitionOnChange
enableSystem={false}
>
<div className="relative mx-auto flex h-full w-full items-center justify-center overflow-x-hidden overflow-y-scroll">
{children}
</div>
</ThemeProvider>
<div className="relative mx-auto flex h-full w-full items-center justify-center overflow-x-hidden overflow-y-scroll">
{children}
</div>
</PayProviders>
</body>
</html>
Expand Down
Loading
Loading