import { CheckCircleIcon, ClockIcon, CurrencyDollarIcon, PhotoIcon, PuzzlePieceIcon, UsersIcon } from "@heroicons/react/24/outline"; import { BLOCK_EXPLORER_URL } from "@hey/data/constants"; import { tokens } from "@hey/data/tokens"; import formatAddress from "@hey/helpers/formatAddress"; import getAccount from "@hey/helpers/getAccount"; import { isRepost } from "@hey/helpers/postHelpers"; import { type AnyPostFragment, type SimpleCollectActionFragment, useCollectActionQuery } from "@hey/indexer"; import { useCounter } from "@uidotdev/usehooks"; import dayjs from "dayjs"; import plur from "plur"; import { type Dispatch, type SetStateAction, useMemo, useState } from "react"; import { Link } from "react-router"; import CountdownTimer from "@/components/Shared/CountdownTimer"; import Loader from "@/components/Shared/Loader"; import PostExecutors from "@/components/Shared/Modal/PostExecutors"; import Slug from "@/components/Shared/Slug"; import { H3, H4, HelpTooltip, Modal, Tooltip, WarningMessage } from "@/components/Shared/UI"; import getTokenImage from "@/helpers/getTokenImage"; import humanize from "@/helpers/humanize"; import nFormatter from "@/helpers/nFormatter"; import CollectActionButton from "./CollectActionButton"; import Splits from "./Splits"; interface CollectActionBodyProps { post: AnyPostFragment; setShowCollectModal: Dispatch>; } const CollectActionBody = ({ post, setShowCollectModal }: CollectActionBodyProps) => { const [showCollectorsModal, setShowCollectorsModal] = useState(false); const targetPost = isRepost(post) ? post?.repostOf : post; const [collects, { increment }] = useCounter(targetPost.stats.collects); const { data, loading } = useCollectActionQuery({ variables: { request: { post: post.id } } }); // Memoize expensive calculations to prevent unnecessary re-renders const enabledTokens = useMemo(() => { return tokens.map((t) => t.symbol); }, []); // Extract data safely with optional chaining const targetAction = useMemo(() => { return data?.post?.__typename === "Post" ? data?.post.actions.find( (action) => action.__typename === "SimpleCollectAction" ) : data?.post?.__typename === "Repost" ? data?.post?.repostOf?.actions.find( (action) => action.__typename === "SimpleCollectAction" ) : null; }, [data]); const collectAction = targetAction as SimpleCollectActionFragment; const endTimestamp = collectAction?.endsAt; const collectLimit = useMemo( () => Number(collectAction?.collectLimit || 0), [collectAction] ); const amount = useMemo( () => Number.parseFloat(collectAction?.payToCollect?.price?.value || "0"), [collectAction] ); const currency = collectAction?.payToCollect?.price?.asset?.symbol; const recipients = collectAction?.payToCollect?.recipients || []; const percentageCollected = useMemo(() => { return collectLimit > 0 ? (collects / collectLimit) * 100 : 0; }, [collects, collectLimit]); const isTokenEnabled = useMemo(() => { return enabledTokens?.includes(currency || ""); }, [enabledTokens, currency]); const isSaleEnded = useMemo(() => { return endTimestamp ? new Date(endTimestamp).getTime() / 1000 < new Date().getTime() / 1000 : false; }, [endTimestamp]); const isAllCollected = useMemo(() => { return collectLimit ? collects >= collectLimit : false; }, [collectLimit, collects]); const totalRevenue = useMemo(() => { return amount * collects; }, [amount, collects]); const heyFee = useMemo(() => { return (amount * 0.025).toFixed(2); }, [amount]); if (loading) { return ; } return ( <> {collectLimit ? (
) : null}
{isAllCollected ? ( This collection has been sold out
} /> ) : isSaleEnded ? ( This collection has ended
} /> ) : null}

{targetPost.__typename} by{" "}

{amount ? (
{isTokenEnabled ? ( {currency} ) : ( )}

{amount}

{currency}
Hey
~{heyFee} {currency} (2.5%)
) : null}
{collectLimit && !isAllCollected ? (
{collectLimit - collects} available
) : null}
{endTimestamp && !isAllCollected ? (
{isSaleEnded ? "Sale ended on:" : "Sale ends:"} {isSaleEnded ? ( `${dayjs(endTimestamp).format("MMM D, YYYY, h:mm A")}` ) : ( )}
) : null} {collectAction.address ? (
Token: {formatAddress(collectAction.address)}
) : null} {amount ? (
Revenue: {nFormatter(totalRevenue)} {currency}
) : null} {recipients.length > 1 ? : null}
{ increment(); setShowCollectModal(false); }} post={targetPost} postAction={collectAction} />
setShowCollectorsModal(false)} show={showCollectorsModal} title="Collectors" > ); }; export default CollectActionBody;