Skip to content

[TOOL-4687] Dashboard: Show Special Price UI in claim tokens card #7284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
ChevronRightIcon,
ExternalLinkIcon,
} from "lucide-react";
import { useEffect, useState } from "react";
import { useState } from "react";
import { type ThirdwebClient, type ThirdwebContract, toTokens } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
import {
Expand Down Expand Up @@ -171,7 +171,7 @@ function RecentTransfersUI(props: {
<Button
variant="outline"
size="sm"
disabled={props.isPending || props.data.length === 0}
disabled={props.isPending || props.data.length < props.rowsPerPage}
className="gap-1.5 bg-background"
onClick={() => props.setPage(props.page + 1)}
>
Expand Down Expand Up @@ -213,7 +213,6 @@ export function RecentTransfers(props: {
}) {
const rowsPerPage = 10;
const [page, setPage] = useState(0);
const [hasFetchedOnce, setHasFetchedOnce] = useState(false);

const tokenQuery = useTokenTransfers({
chainId: props.clientContract.chain.id,
Expand All @@ -222,18 +221,11 @@ export function RecentTransfers(props: {
limit: rowsPerPage,
});

// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
if (!tokenQuery.isPending) {
setHasFetchedOnce(true);
}
}, [tokenQuery.isPending]);

return (
<div>
<RecentTransfersUI
data={tokenQuery.data ?? []}
isPending={tokenQuery.isPending && !hasFetchedOnce}
isPending={tokenQuery.isPending}
rowsPerPage={rowsPerPage}
client={props.clientContract.client}
tokenMetadata={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { TransactionButton } from "components/buttons/TransactionButton";
import { useTrack } from "hooks/analytics/useTrack";
import {
CheckIcon,
CircleAlertIcon,
CircleIcon,
ExternalLinkIcon,
InfinityIcon,
Expand Down Expand Up @@ -40,6 +41,7 @@ import {
} from "thirdweb/react";
import { getClaimParams, maxUint256 } from "thirdweb/utils";
import { tryCatch } from "utils/try-catch";
import { ToolTipLabel } from "../../../../../../../../../../@/components/ui/tooltip";
import { getSDKTheme } from "../../../../../../../../components/sdk-component-theme";
import { PublicPageConnectButton } from "../../../_components/PublicPageConnectButton";
import { getCurrencyMeta } from "../../_utils/getCurrencyMeta";
Expand Down Expand Up @@ -222,23 +224,23 @@ export function ClaimTokenCardUI(props: {
},
});

const publicPrice = {
pricePerTokenWei: props.claimCondition.pricePerToken,
currencyAddress: props.claimCondition.currency,
decimals: props.claimConditionCurrency.decimals,
symbol: props.claimConditionCurrency.symbol,
};

const claimParamsQuery = useQuery({
queryKey: ["claim-params", props.contract.address, account?.address],
queryFn: async () => {
const defaultPricing = {
pricePerTokenWei: props.claimCondition.pricePerToken,
currencyAddress: props.claimCondition.currency,
decimals: props.claimConditionCurrency.decimals,
symbol: props.claimConditionCurrency.symbol,
};

if (!account) {
return defaultPricing;
return publicPrice;
}

const merkleRoot = props.claimCondition.merkleRoot;
if (!merkleRoot || merkleRoot === padHex("0x", { size: 32 })) {
return defaultPricing;
return publicPrice;
}

const claimParams = await getClaimParams({
Expand Down Expand Up @@ -313,6 +315,11 @@ export function ClaimTokenCardUI(props: {
);
}

const isShowingCustomPrice =
claimParamsData &&
(claimParamsData.pricePerTokenWei !== publicPrice.pricePerTokenWei ||
claimParamsData.currencyAddress !== publicPrice.currencyAddress);

return (
<div className="rounded-xl border bg-card ">
<div className="border-b px-4 py-5 lg:px-5">
Expand Down Expand Up @@ -348,25 +355,22 @@ export function ClaimTokenCardUI(props: {

<div className="space-y-3 rounded-lg bg-muted/50 p-3">
{/* Price per token */}
<div className="flex justify-between font-medium text-sm">
<span>Price per token</span>

<SkeletonContainer
skeletonData={`0.00 ${props.claimConditionCurrency.symbol}`}
loadedData={
claimParamsData
? claimParamsData.pricePerTokenWei === 0n
? "FREE"
: `${toTokens(
claimParamsData.pricePerTokenWei,
claimParamsData.decimals,
)} ${claimParamsData.symbol}`
: undefined
}
render={(v) => {
return <span className="">{v}</span>;
}}
/>
<div className="flex items-start justify-between font-medium text-sm">
<span className="flex items-center gap-2">
Price per token
{isShowingCustomPrice && (
<ToolTipLabel label="Your connected wallet address is added in the allowlist and is getting a special price">
<CircleAlertIcon className="size-3.5 text-muted-foreground" />
</ToolTipLabel>
)}
</span>

<div className="flex flex-col items-end gap-1">
{isShowingCustomPrice && (
<TokenPrice data={publicPrice} strikethrough={true} />
)}
<TokenPrice data={claimParamsData} strikethrough={false} />
</div>
</div>

{/* Quantity */}
Expand Down Expand Up @@ -447,6 +451,43 @@ export function ClaimTokenCardUI(props: {
);
}

function TokenPrice(props: {
strikethrough: boolean;
data:
| {
pricePerTokenWei: bigint;
decimals: number;
symbol: string;
}
| undefined;
}) {
return (
<SkeletonContainer
skeletonData={"0.00 ETH"}
loadedData={
props.data
? props.data.pricePerTokenWei === 0n
? "FREE"
: `${toTokens(
props.data.pricePerTokenWei,
props.data.decimals,
)} ${props.data.symbol}`
: undefined
}
render={(v) => {
if (props.strikethrough) {
return (
<s className="font-medium text-muted-foreground text-sm line-through decoration-muted-foreground/50">
{v}
</s>
);
}
return <span className="font-medium text-foreground text-sm">{v}</span>;
}}
/>
);
}

function SupplyRemaining(props: {
supplyClaimed: bigint;
maxClaimableSupply: bigint;
Expand Down
Loading