@@ -3,6 +3,7 @@ import { Spinner } from "@/components/ui/Spinner/Spinner";
3
3
import { Button } from "@/components/ui/button" ;
4
4
import { DecimalInput } from "@/components/ui/decimal-input" ;
5
5
import { Label } from "@/components/ui/label" ;
6
+ import { Progress } from "@/components/ui/progress" ;
6
7
import { SkeletonContainer } from "@/components/ui/skeleton" ;
7
8
import { cn } from "@/lib/utils" ;
8
9
import { useMutation , useQuery } from "@tanstack/react-query" ;
@@ -31,7 +32,7 @@ import {
31
32
useActiveWallet ,
32
33
useSendTransaction ,
33
34
} from "thirdweb/react" ;
34
- import { getClaimParams } from "thirdweb/utils" ;
35
+ import { getClaimParams , maxUint256 } from "thirdweb/utils" ;
35
36
import { tryCatch } from "utils/try-catch" ;
36
37
import { getSDKTheme } from "../../../../../../../../components/sdk-component-theme" ;
37
38
import { PublicPageConnectButton } from "../../../_components/PublicPageConnectButton" ;
@@ -41,6 +42,11 @@ type ActiveClaimCondition = Awaited<ReturnType<typeof getActiveClaimCondition>>;
41
42
42
43
// TODO UI improvements - show how many tokens connected wallet can claim at max
43
44
45
+ const compactNumberFormatter = new Intl . NumberFormat ( "en-US" , {
46
+ notation : "compact" ,
47
+ maximumFractionDigits : 10 ,
48
+ } ) ;
49
+
44
50
export function ClaimTokenCardUI ( props : {
45
51
contract : ThirdwebContract ;
46
52
name : string ;
@@ -304,7 +310,9 @@ export function ClaimTokenCardUI(props: {
304
310
return (
305
311
< div className = "rounded-xl border bg-card " >
306
312
< div className = "border-b px-4 py-5 lg:px-5" >
307
- < h2 className = "font-bold text-lg" > Buy { props . symbol } </ h2 >
313
+ < h2 className = "font-semibold text-lg tracking-tight" >
314
+ Buy { props . symbol }
315
+ </ h2 >
308
316
< p className = "text-muted-foreground text-sm" >
309
317
Buy tokens from the primary sale
310
318
</ p >
@@ -320,11 +328,18 @@ export function ClaimTokenCardUI(props: {
320
328
id = "token-amount"
321
329
symbol = { props . symbol }
322
330
/>
323
- { /* <p className="text-xs text-muted-foreground">Maximum purchasable: {tokenData.maxPurchasable} tokens</p> */ }
324
331
</ div >
325
332
326
333
< div className = "h-4" />
327
334
335
+ < SupplyRemaining
336
+ supplyClaimed = { props . claimCondition . supplyClaimed }
337
+ maxClaimableSupply = { props . claimCondition . maxClaimableSupply }
338
+ decimals = { props . decimals }
339
+ />
340
+
341
+ < div className = "h-4" />
342
+
328
343
< div className = "space-y-3 rounded-lg bg-muted/50 p-3" >
329
344
{ /* Price per token */ }
330
345
< div className = "flex justify-between font-medium text-sm" >
@@ -426,6 +441,42 @@ export function ClaimTokenCardUI(props: {
426
441
) ;
427
442
}
428
443
444
+ function SupplyRemaining ( props : {
445
+ supplyClaimed : bigint ;
446
+ maxClaimableSupply : bigint ;
447
+ decimals : number ;
448
+ } ) {
449
+ const isMaxClaimableSupplyUnlimited = props . maxClaimableSupply === maxUint256 ;
450
+ const supplyClaimedTokenNumber = Number (
451
+ toTokens ( props . supplyClaimed , props . decimals ) ,
452
+ ) ;
453
+ const maxClaimableSupplyTokenNumber = Number (
454
+ toTokens ( props . maxClaimableSupply , props . decimals ) ,
455
+ ) ;
456
+
457
+ const soldPercentage = isMaxClaimableSupplyUnlimited
458
+ ? 0
459
+ : ( supplyClaimedTokenNumber / maxClaimableSupplyTokenNumber ) * 100 ;
460
+
461
+ return (
462
+ < div className = "space-y-2" >
463
+ < div className = "flex items-center justify-between" >
464
+ < span className = "font-medium text-sm" > Supply Remaining</ span >
465
+ < span className = "font-bold text-sm" >
466
+ { compactNumberFormatter . format ( supplyClaimedTokenNumber ) } /{ " " }
467
+ { isMaxClaimableSupplyUnlimited
468
+ ? "Unlimited"
469
+ : compactNumberFormatter . format ( maxClaimableSupplyTokenNumber ) }
470
+ </ span >
471
+ </ div >
472
+ < Progress value = { soldPercentage } className = "h-2.5" />
473
+ < p className = "font-medium text-muted-foreground text-xs" >
474
+ { soldPercentage . toFixed ( 1 ) } % Sold
475
+ </ p >
476
+ </ div >
477
+ ) ;
478
+ }
479
+
429
480
type Status = "idle" | "pending" | "success" | "error" ;
430
481
431
482
const statusToIcon : Record < Status , React . FC < { className : string } > > = {
@@ -472,7 +523,7 @@ function PriceInput(props: {
472
523
className = "!text-2xl h-auto truncate bg-muted/50 pr-14 font-bold"
473
524
/>
474
525
{ props . symbol && (
475
- < div className = "-translate-y-1/2 absolute top-1/2 right-4 font-semibold text-base text- muted-foreground" >
526
+ < div className = "-translate-y-1/2 absolute top-1/2 right-3 font-medium text-muted-foreground text-sm " >
476
527
{ props . symbol }
477
528
</ div >
478
529
) }
0 commit comments