11"use client" ;
22import { Spinner } from "@/components/ui/Spinner/Spinner" ;
3+ import { Button } from "@/components/ui/button" ;
4+ import { DecimalInput } from "@/components/ui/decimal-input" ;
35import { Label } from "@/components/ui/label" ;
46import { SkeletonContainer } from "@/components/ui/skeleton" ;
57import { cn } from "@/lib/utils" ;
68import { useMutation , useQuery } from "@tanstack/react-query" ;
79import { TransactionButton } from "components/buttons/TransactionButton" ;
8- import { CheckIcon , CircleIcon , XIcon } from "lucide-react" ;
10+ import { useTrack } from "hooks/analytics/useTrack" ;
11+ import { CheckIcon , CircleIcon , ExternalLinkIcon , XIcon } from "lucide-react" ;
912import { useTheme } from "next-themes" ;
13+ import Link from "next/link" ;
1014import { useState } from "react" ;
1115import { toast } from "sonner" ;
1216import {
@@ -25,7 +29,6 @@ import {
2529import { useActiveAccount , useSendTransaction } from "thirdweb/react" ;
2630import { getClaimParams } from "thirdweb/utils" ;
2731import { tryCatch } from "utils/try-catch" ;
28- import { DecimalInput } from "../../../../../../../../../../@/components/ui/decimal-input" ;
2932import { getSDKTheme } from "../../../../../../../../components/sdk-component-theme" ;
3033import { PublicPageConnectButton } from "../../../_components/PublicPageConnectButton" ;
3134import { getCurrencyMeta } from "../../_utils/getCurrencyMeta" ;
@@ -49,11 +52,29 @@ export function ClaimTokenCardUI(props: {
4952 const [ quantity , setQuantity ] = useState ( "1" ) ;
5053 const account = useActiveAccount ( ) ;
5154 const { theme } = useTheme ( ) ;
55+ const trackEvent = useTrack ( ) ;
5256 const sendClaimTx = useSendTransaction ( {
5357 payModal : {
5458 theme : getSDKTheme ( theme === "light" ? "light" : "dark" ) ,
5559 } ,
5660 } ) ;
61+ const [ successScreen , setSuccessScreen ] = useState <
62+ | undefined
63+ | {
64+ txHash : string ;
65+ }
66+ > ( undefined ) ;
67+
68+ function trackAssetBuy ( type : "attempt" | "success" | "error" ) {
69+ trackEvent ( {
70+ category : "asset" ,
71+ action : "buy" ,
72+ label : type ,
73+ contractType : "DropERC20" ,
74+ chainId : props . contract . chain . id ,
75+ } ) ;
76+ }
77+
5778 const [ stepsUI , setStepsUI ] = useState <
5879 | undefined
5980 | {
@@ -69,6 +90,8 @@ export function ClaimTokenCardUI(props: {
6990 return ;
7091 }
7192
93+ trackAssetBuy ( "attempt" ) ;
94+
7295 setStepsUI ( undefined ) ;
7396
7497 const transaction = claimTo ( {
@@ -101,6 +124,9 @@ export function ClaimTokenCardUI(props: {
101124 approve : "error" ,
102125 claim : "idle" ,
103126 } ) ;
127+
128+ trackAssetBuy ( "error" ) ;
129+
104130 console . error ( approveTxResult . error ) ;
105131 toast . error ( "Failed to approve spending" , {
106132 description : approveTxResult . error . message ,
@@ -116,7 +142,7 @@ export function ClaimTokenCardUI(props: {
116142
117143 async function sendAndConfirm ( ) {
118144 const result = await sendClaimTx . mutateAsync ( transaction ) ;
119- await waitForReceipt ( result ) ;
145+ return await waitForReceipt ( result ) ;
120146 }
121147
122148 setStepsUI ( {
@@ -130,8 +156,11 @@ export function ClaimTokenCardUI(props: {
130156 approve : approveTx ? "success" : undefined ,
131157 claim : "error" ,
132158 } ) ;
159+
160+ trackAssetBuy ( "error" ) ;
161+
133162 console . error ( claimTxResult . error ) ;
134- toast . error ( "Failed to claim tokens" , {
163+ toast . error ( "Failed to buy tokens" , {
135164 description : claimTxResult . error . message ,
136165 } ) ;
137166 return ;
@@ -142,7 +171,11 @@ export function ClaimTokenCardUI(props: {
142171 claim : "success" ,
143172 } ) ;
144173
145- toast . success ( "Tokens claimed successfully" ) ;
174+ trackAssetBuy ( "success" ) ;
175+
176+ setSuccessScreen ( {
177+ txHash : claimTxResult . data . transactionHash ,
178+ } ) ;
146179 } ,
147180 } ) ;
148181
@@ -192,6 +225,51 @@ export function ClaimTokenCardUI(props: {
192225
193226 const claimParamsData = claimParamsQuery . data ;
194227
228+ if ( successScreen ) {
229+ const explorerUrl =
230+ props . chainMetadata . explorers ?. [ 0 ] ?. url ??
231+ `https://thirdweb.com/${ props . chainMetadata . slug } ` ;
232+
233+ return (
234+ < div className = "rounded-xl border bg-card p-6" >
235+ { /* icon */ }
236+ < div className = "flex justify-center py-8" >
237+ < div className = "rounded-full border bg-background p-3" >
238+ < CheckIcon className = "size-8" />
239+ </ div >
240+ </ div >
241+
242+ < div className = "mb-12" >
243+ < h2 className = "mb-1 text-center font-bold text-xl" >
244+ Purchase Successful
245+ </ h2 >
246+ < p className = "text-center text-muted-foreground text-sm" >
247+ You have successfully purchased { quantity } { " " }
248+ { props . symbol || "tokens" }
249+ </ p >
250+ </ div >
251+
252+ < Button className = "w-full bg-muted/50" variant = "outline" asChild >
253+ < Link
254+ href = { `${ explorerUrl } /tx/${ successScreen . txHash } ` }
255+ target = "_blank"
256+ className = "gap-1.5"
257+ >
258+ View Transaction{ " " }
259+ < ExternalLinkIcon className = "size-3.5 text-muted-foreground" />
260+ </ Link >
261+ </ Button >
262+
263+ < Button
264+ onClick = { ( ) => setSuccessScreen ( undefined ) }
265+ className = "mt-3 w-full"
266+ >
267+ Buy More
268+ </ Button >
269+ </ div >
270+ ) ;
271+ }
272+
195273 return (
196274 < div className = "rounded-xl border bg-card " >
197275 < div className = "border-b px-4 py-5 lg:px-5" >
@@ -225,10 +303,12 @@ export function ClaimTokenCardUI(props: {
225303 skeletonData = { `0.00 ${ props . claimConditionCurrency . symbol } ` }
226304 loadedData = {
227305 claimParamsData
228- ? `${ toTokens (
229- claimParamsData . pricePerTokenWei ,
230- claimParamsData . decimals ,
231- ) } ${ claimParamsData . symbol } `
306+ ? claimParamsData . pricePerTokenWei === 0n
307+ ? "FREE"
308+ : `${ toTokens (
309+ claimParamsData . pricePerTokenWei ,
310+ claimParamsData . decimals ,
311+ ) } ${ claimParamsData . symbol } `
232312 : undefined
233313 }
234314 render = { ( v ) => {
@@ -251,14 +331,16 @@ export function ClaimTokenCardUI(props: {
251331 skeletonData = { "0.00 ETH" }
252332 loadedData = {
253333 claimParamsData
254- ? `${
255- Number (
256- toTokens (
257- claimParamsData . pricePerTokenWei ,
258- claimParamsData . decimals ,
259- ) ,
260- ) * Number ( quantity )
261- } ${ claimParamsData . symbol } `
334+ ? claimParamsData . pricePerTokenWei === 0n
335+ ? "FREE"
336+ : `${
337+ Number (
338+ toTokens (
339+ claimParamsData . pricePerTokenWei ,
340+ claimParamsData . decimals ,
341+ ) ,
342+ ) * Number ( quantity )
343+ } ${ claimParamsData . symbol } `
262344 : undefined
263345 }
264346 render = { ( v ) => {
0 commit comments