22
33import { SingleNetworkSelector } from "@/components/blocks/NetworkSelectors" ;
44import { TokenSelector } from "@/components/blocks/TokenSelector" ;
5+ import { CopyTextButton } from "@/components/ui/CopyTextButton" ;
56import { Button } from "@/components/ui/button" ;
67import { Card , CardContent , CardHeader , CardTitle } from "@/components/ui/card" ;
78import { Input } from "@/components/ui/input" ;
89import { Label } from "@/components/ui/label" ;
10+ import { getClientThirdwebClient } from "@/constants/thirdweb-client.client" ;
911import { cn } from "@/lib/utils" ;
1012import { ChevronDownIcon , CreditCardIcon } from "lucide-react" ;
1113import { useCallback , useMemo , useState } from "react" ;
@@ -19,10 +21,22 @@ import {
1921} from "thirdweb" ;
2022import { getCurrencyMetadata } from "thirdweb/extensions/erc20" ;
2123import { resolveScheme , upload } from "thirdweb/storage" ;
24+ import { setThirdwebDomains } from "thirdweb/utils" ;
2225import { 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" ;
2336import { resolveEns } from "../../../../lib/ens" ;
37+ import { getVercelEnv } from "../../../../lib/vercel-utils" ;
2438
25- export function PaymentLinkForm ( { client } : { client : ThirdwebClient } ) {
39+ export function PaymentLinkForm ( ) {
2640 const [ chainId , setChainId ] = useState < number > ( ) ;
2741 const [ recipientAddress , setRecipientAddress ] = useState ( "" ) ;
2842 const [ tokenAddressWithChain , setTokenAddressWithChain ] = useState ( "" ) ;
@@ -32,8 +46,24 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
3246 const [ imageUri , setImageUri ] = useState < string > ( "" ) ;
3347 const [ uploadingImage , setUploadingImage ] = useState ( false ) ;
3448 const [ isLoading , setIsLoading ] = useState ( false ) ;
35- const [ error , setError ] = useState < string > ( ) ;
3649 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+ } , [ ] ) ;
3767
3868 const isFormComplete = useMemo ( ( ) => {
3969 return chainId && recipientAddress && tokenAddressWithChain && amount ;
@@ -72,7 +102,6 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
72102 const handleSubmit = useCallback (
73103 async ( e : React . FormEvent ) => {
74104 e . preventDefault ( ) ;
75- setError ( undefined ) ;
76105 setIsLoading ( true ) ;
77106
78107 try {
@@ -112,15 +141,11 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
112141 params . set ( "image" , imageUri ) ;
113142 }
114143
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!" ) ;
122147 } catch ( err ) {
123- setError ( err instanceof Error ? err . message : "An error occurred" ) ;
148+ toast . error ( err instanceof Error ? err . message : "An error occurred" ) ;
124149 } finally {
125150 setIsLoading ( false ) ;
126151 }
@@ -290,7 +315,7 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
290315 id = "title"
291316 value = { title }
292317 onChange = { ( e ) => setTitle ( e . target . value ) }
293- placeholder = "A title for your payment "
318+ placeholder = "Payment for... "
294319 className = "w-full"
295320 />
296321 </ div >
@@ -318,25 +343,35 @@ export function PaymentLinkForm({ client }: { client: ThirdwebClient }) {
318343 </ div >
319344 </ div >
320345
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 >
340375 </ div >
341376 </ form >
342377 </ CardContent >
0 commit comments