Skip to content

Commit dc49fea

Browse files
committed
feat: more payment page styling
1 parent 233693e commit dc49fea

File tree

2 files changed

+146
-42
lines changed

2 files changed

+146
-42
lines changed

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/AdvancedSection.client.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ export function AdvancedSection({
5454
features={["Swap any token", "Cross-chain swaps"]}
5555
description="Swap tokens cross-chain with dedicated swapping endpoints."
5656
link={{
57-
href: `/team/${teamSlug}/${projectSlug}/payments/swap`,
57+
href: `https://portal.thirdweb.com/payments/swap`,
5858
label: "Setup Swaps",
59+
target: "_blank",
5960
}}
6061
/>
6162
</div>

apps/dashboard/src/app/pay/[id]/page.tsx

Lines changed: 144 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1+
import { ShieldCheckIcon } from "lucide-react";
12
import type { Metadata } from "next";
23
import Image from "next/image";
3-
import { defineChain, getContract } from "thirdweb";
4-
import { getCurrencyMetadata } from "thirdweb/extensions/erc20";
4+
import { Bridge, defineChain, toTokens } from "thirdweb";
5+
import { getChainMetadata } from "thirdweb/chains";
56
import { resolveScheme } from "thirdweb/storage";
6-
import { checksumAddress } from "thirdweb/utils";
7+
import { shortenAddress } from "thirdweb/utils";
78
import { getPaymentLink } from "@/api/universal-bridge/links";
9+
import { Badge } from "@/components/ui/badge";
810
import { NEXT_PUBLIC_THIRDWEB_API_HOST } from "@/constants/public-envs";
9-
import { API_SERVER_SECRET } from "@/constants/server-envs";
10-
import { getClientThirdwebClient } from "@/constants/thirdweb-client.client";
11+
import {
12+
API_SERVER_SECRET,
13+
DASHBOARD_THIRDWEB_SECRET_KEY,
14+
} from "@/constants/server-envs";
15+
import { getConfiguredThirdwebClient } from "@/constants/thirdweb.server";
16+
import { resolveEns } from "@/lib/ens";
1117
import { PayPageWidget } from "../components/client/PayPageWidget.client";
1218
import { payAppThirdwebClient } from "../constants";
1319

@@ -37,52 +43,149 @@ export default async function PayPage({
3743
paymentId: id,
3844
});
3945

40-
const tokenContract = getContract({
41-
address: paymentLink.destinationToken.address, // for this RPC call, use the dashboard client
42-
// eslint-disable-next-line no-restricted-syntax
43-
chain: defineChain(Number(paymentLink.destinationToken.chainId)),
44-
client: getClientThirdwebClient(undefined),
45-
});
46-
const currencyMetadataPromise = getCurrencyMetadata({
47-
contract: tokenContract,
46+
const projectMetadataPromise = getProjectMetadata(paymentLink.clientId);
47+
48+
const tokensPromise = Bridge.tokens({
49+
client: getConfiguredThirdwebClient({
50+
secretKey: DASHBOARD_THIRDWEB_SECRET_KEY,
51+
teamId: undefined,
52+
}),
53+
chainId: Number(paymentLink.destinationToken.chainId),
54+
tokenAddress: paymentLink.destinationToken.address,
4855
});
4956

50-
const projectMetadataPromise = getProjectMetadata(paymentLink.clientId);
57+
const chainPromise = getChainMetadata(
58+
defineChain(Number(paymentLink.destinationToken.chainId)),
59+
);
5160

52-
const [{ symbol, decimals, name: tokenName }, projectMetadata] =
53-
await Promise.all([currencyMetadataPromise, projectMetadataPromise]);
61+
const recipientPromise = resolveEns(
62+
paymentLink.receiver,
63+
getConfiguredThirdwebClient({
64+
secretKey: DASHBOARD_THIRDWEB_SECRET_KEY,
65+
teamId: undefined,
66+
}),
67+
);
5468

55-
const token = {
56-
address: checksumAddress(paymentLink.destinationToken.address),
57-
chainId: Number(paymentLink.destinationToken.chainId),
58-
decimals,
59-
name: tokenName,
60-
symbol,
61-
};
69+
const [tokens, projectMetadata, chain, recipientEnsOrAddress] =
70+
await Promise.all([
71+
tokensPromise,
72+
projectMetadataPromise,
73+
chainPromise,
74+
recipientPromise,
75+
]);
76+
77+
const token = tokens[0];
78+
if (!token) {
79+
throw new Error("Token not found");
80+
}
6281

6382
return (
6483
<div className="flex z-10 flex-col lg:flex-row h-full w-full">
6584
<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">
66-
<div className="flex flex-row items-center justify-center gap-4">
67-
{projectMetadata.image && (
68-
<Image
69-
src={resolveScheme({
70-
uri: projectMetadata.image,
71-
client: payAppThirdwebClient,
72-
})}
73-
alt={projectMetadata.name}
74-
width={25}
75-
height={25}
76-
className="rounded-full overflow-hidden"
77-
/>
85+
<div>
86+
<div className="flex flex-row items-center justify-start gap-4">
87+
{projectMetadata.image && (
88+
<Image
89+
src={resolveScheme({
90+
uri: projectMetadata.image,
91+
client: payAppThirdwebClient,
92+
})}
93+
alt={projectMetadata.name}
94+
width={25}
95+
height={25}
96+
className="rounded-full overflow-hidden"
97+
/>
98+
)}
99+
<h2 className="text-xl font-bold">{projectMetadata.name}</h2>
100+
</div>
101+
{projectMetadata.description && (
102+
<p className="mt-2 text-sm text-muted-foreground hidden lg:block">
103+
{projectMetadata.description}
104+
</p>
105+
)}
106+
</div>
107+
108+
<div className="hidden lg:block my-4 w-full">
109+
{paymentLink.amount && (
110+
<div className="flex flex-col gap-1 w-full my-4">
111+
<span className="text-muted-foreground text-xs">Details</span>
112+
<div className="font-medium flex-row flex justify-between items-center w-full">
113+
<div className="flex flex-row items-center gap-2">
114+
{token.iconUri && (
115+
<img
116+
src={resolveScheme({
117+
uri: token.iconUri,
118+
client: getConfiguredThirdwebClient({
119+
secretKey: DASHBOARD_THIRDWEB_SECRET_KEY,
120+
teamId: undefined,
121+
}),
122+
})}
123+
alt={token.name}
124+
width={25}
125+
height={25}
126+
className="size-5 rounded-full overflow-hidden"
127+
/>
128+
)}
129+
{toTokens(BigInt(paymentLink.amount), token.decimals)}{" "}
130+
{token.symbol}
131+
</div>
132+
{token.prices["USD"] && (
133+
<span>
134+
$
135+
{(
136+
Number(token.prices["USD"]) *
137+
Number(
138+
toTokens(BigInt(paymentLink.amount), token.decimals),
139+
)
140+
).toFixed(2)}
141+
</span>
142+
)}
143+
</div>
144+
</div>
145+
)}
146+
{chain && (
147+
<div className="flex flex-col gap-1 w-full my-4">
148+
<span className="text-muted-foreground text-xs">Network</span>
149+
<div className="font-medium flex-row flex justify-between items-center w-full">
150+
<div className="flex flex-row items-center gap-2">
151+
{chain.icon?.url && (
152+
<img
153+
src={resolveScheme({
154+
uri: chain.icon.url,
155+
client: getConfiguredThirdwebClient({
156+
secretKey: DASHBOARD_THIRDWEB_SECRET_KEY,
157+
teamId: undefined,
158+
}),
159+
})}
160+
alt={chain.name}
161+
width={chain.icon.width}
162+
height={chain.icon.height}
163+
className="size-5 rounded-full overflow-hidden"
164+
/>
165+
)}
166+
{chain.name}
167+
</div>
168+
</div>
169+
</div>
78170
)}
79-
<h2 className="text-xl font-bold">{projectMetadata.name}</h2>
171+
{recipientEnsOrAddress.ensName ||
172+
(recipientEnsOrAddress.address && (
173+
<div className="flex flex-col gap-1 w-full my-4">
174+
<span className="text-muted-foreground text-xs">Seller</span>
175+
<div className="font-medium flex-row flex justify-between items-center w-full">
176+
{recipientEnsOrAddress.ensName ??
177+
shortenAddress(recipientEnsOrAddress.address)}
178+
</div>
179+
</div>
180+
))}
181+
</div>
182+
183+
<div className="mt-auto hidden lg:block">
184+
<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">
185+
<ShieldCheckIcon className="size-3" />
186+
Secured by thirdweb
187+
</Badge>
80188
</div>
81-
{projectMetadata.description && (
82-
<p className="text-sm text-muted-foreground">
83-
{projectMetadata.description}
84-
</p>
85-
)}
86189
</header>
87190
<main className="flex justify-center p-12 w-full items-center">
88191
<PayPageWidget

0 commit comments

Comments
 (0)