2
2
3
3
import { SingleNetworkSelector } from "@/components/blocks/NetworkSelectors" ;
4
4
import { TokenSelector } from "@/components/blocks/TokenSelector" ;
5
+ import { CopyTextButton } from "@/components/ui/CopyTextButton" ;
5
6
import { Button } from "@/components/ui/button" ;
6
7
import { Card , CardContent , CardHeader , CardTitle } from "@/components/ui/card" ;
7
8
import { Input } from "@/components/ui/input" ;
8
9
import { Label } from "@/components/ui/label" ;
10
+ import { getClientThirdwebClient } from "@/constants/thirdweb-client.client" ;
9
11
import { cn } from "@/lib/utils" ;
10
12
import { ChevronDownIcon , CreditCardIcon } from "lucide-react" ;
11
13
import { useCallback , useMemo , useState } from "react" ;
@@ -19,10 +21,22 @@ import {
19
21
} from "thirdweb" ;
20
22
import { getCurrencyMetadata } from "thirdweb/extensions/erc20" ;
21
23
import { resolveScheme , upload } from "thirdweb/storage" ;
24
+ import { setThirdwebDomains } from "thirdweb/utils" ;
22
25
import { FileInput } from "../../../../components/shared/FileInput" ;
26
+ import {
27
+ THIRDWEB_ANALYTICS_DOMAIN ,
28
+ THIRDWEB_BUNDLER_DOMAIN ,
29
+ THIRDWEB_INAPP_WALLET_DOMAIN ,
30
+ THIRDWEB_INSIGHT_API_DOMAIN ,
31
+ THIRDWEB_PAY_DOMAIN ,
32
+ THIRDWEB_RPC_DOMAIN ,
33
+ THIRDWEB_SOCIAL_API_DOMAIN ,
34
+ THIRDWEB_STORAGE_DOMAIN ,
35
+ } from "../../../../constants/urls" ;
23
36
import { resolveEns } from "../../../../lib/ens" ;
37
+ import { getVercelEnv } from "../../../../lib/vercel-utils" ;
24
38
25
- export function PaymentLinkForm ( { client } : { client : ThirdwebClient } ) {
39
+ export function PaymentLinkForm ( ) {
26
40
const [ chainId , setChainId ] = useState < number > ( ) ;
27
41
const [ recipientAddress , setRecipientAddress ] = useState ( "" ) ;
28
42
const [ tokenAddressWithChain , setTokenAddressWithChain ] = useState ( "" ) ;
@@ -32,8 +46,24 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
32
46
const [ imageUri , setImageUri ] = useState < string > ( "" ) ;
33
47
const [ uploadingImage , setUploadingImage ] = useState ( false ) ;
34
48
const [ isLoading , setIsLoading ] = useState ( false ) ;
35
- const [ error , setError ] = useState < string > ( ) ;
36
49
const [ showAdvanced , setShowAdvanced ] = useState ( false ) ;
50
+ const [ paymentUrl , setPaymentUrl ] = useState < string > ( "" ) ;
51
+
52
+ const client = useMemo ( ( ) => {
53
+ if ( getVercelEnv ( ) !== "production" ) {
54
+ setThirdwebDomains ( {
55
+ rpc : THIRDWEB_RPC_DOMAIN ,
56
+ pay : THIRDWEB_PAY_DOMAIN ,
57
+ storage : THIRDWEB_STORAGE_DOMAIN ,
58
+ insight : THIRDWEB_INSIGHT_API_DOMAIN ,
59
+ analytics : THIRDWEB_ANALYTICS_DOMAIN ,
60
+ inAppWallet : THIRDWEB_INAPP_WALLET_DOMAIN ,
61
+ bundler : THIRDWEB_BUNDLER_DOMAIN ,
62
+ social : THIRDWEB_SOCIAL_API_DOMAIN ,
63
+ } ) ;
64
+ }
65
+ return getClientThirdwebClient ( ) ;
66
+ } , [ ] ) ;
37
67
38
68
const isFormComplete = useMemo ( ( ) => {
39
69
return chainId && recipientAddress && tokenAddressWithChain && amount ;
@@ -72,7 +102,6 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
72
102
const handleSubmit = useCallback (
73
103
async ( e : React . FormEvent ) => {
74
104
e . preventDefault ( ) ;
75
- setError ( undefined ) ;
76
105
setIsLoading ( true ) ;
77
106
78
107
try {
@@ -112,15 +141,11 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
112
141
params . set ( "image" , imageUri ) ;
113
142
}
114
143
115
- const paymentUrl = `${ window . location . origin } /pay?${ params . toString ( ) } ` ;
116
-
117
- // Copy to clipboard
118
- await navigator . clipboard . writeText ( paymentUrl ) ;
119
-
120
- // Show success toast
121
- toast . success ( "Payment link copied to clipboard." ) ;
144
+ const url = `${ window . location . origin } /pay?${ params . toString ( ) } ` ;
145
+ setPaymentUrl ( url ) ;
146
+ toast . success ( "Payment link created!" ) ;
122
147
} catch ( err ) {
123
- setError ( err instanceof Error ? err . message : "An error occurred" ) ;
148
+ toast . error ( err instanceof Error ? err . message : "An error occurred" ) ;
124
149
} finally {
125
150
setIsLoading ( false ) ;
126
151
}
@@ -290,7 +315,7 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
290
315
id = "title"
291
316
value = { title }
292
317
onChange = { ( e ) => setTitle ( e . target . value ) }
293
- placeholder = "A title for your payment "
318
+ placeholder = "Payment for... "
294
319
className = "w-full"
295
320
/>
296
321
</ div >
@@ -318,25 +343,35 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
318
343
</ div >
319
344
</ div >
320
345
321
- { error && < div className = "text-red-500 text-sm" > { error } </ div > }
322
-
323
- < div className = "flex gap-2" >
324
- < Button
325
- type = "button"
326
- variant = "outline"
327
- className = "flex-1"
328
- disabled = { isLoading || ! isFormComplete }
329
- onClick = { handlePreview }
330
- >
331
- Preview
332
- </ Button >
333
- < Button
334
- type = "submit"
335
- className = "flex-1"
336
- disabled = { isLoading || ! isFormComplete }
337
- >
338
- { isLoading ? "Creating..." : "Create" }
339
- </ Button >
346
+ < div className = "flex flex-col space-y-4" >
347
+ { paymentUrl && (
348
+ < CopyTextButton
349
+ textToCopy = { paymentUrl }
350
+ textToShow = { paymentUrl }
351
+ tooltip = "Copy Payment Link"
352
+ className = "w-full justify-between truncate bg-background px-3 py-2"
353
+ copyIconPosition = "right"
354
+ />
355
+ ) }
356
+
357
+ < div className = "flex gap-2" >
358
+ < Button
359
+ type = "button"
360
+ variant = "outline"
361
+ className = "flex-1"
362
+ disabled = { isLoading || ! isFormComplete }
363
+ onClick = { handlePreview }
364
+ >
365
+ Preview
366
+ </ Button >
367
+ < Button
368
+ type = "submit"
369
+ className = "flex-1"
370
+ disabled = { isLoading || ! isFormComplete }
371
+ >
372
+ { isLoading ? "Creating..." : "Create" }
373
+ </ Button >
374
+ </ div >
340
375
</ div >
341
376
</ form >
342
377
</ CardContent >
0 commit comments