import { faExternalLink, faHand, faRightLeft, faSeedling, faShoppingCart, faTag, faTrash, faXmark, } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { useCollectionActivity, useTokenActivity, useUsersActivity, } from '@reservoir0x/reservoir-kit-ui' import LoadingSpinner from 'components/common/LoadingSpinner' import { useENSResolver, useMarketplaceChain, useTimeSince } from 'hooks' import Link from 'next/link' import { FC, useEffect, useRef } from 'react' import { useMediaQuery } from 'react-responsive' import { useIntersectionObserver } from 'usehooks-ts' import { Anchor, Box, Flex, FormatCryptoCurrency, TableCell, TableRow, Text, } from '../primitives' import { zeroAddress } from 'viem' type CollectionActivityResponse = ReturnType type CollectionActivity = CollectionActivityResponse['data'][0] export type CollectionActivityTypes = NonNullable< Exclude['0'], boolean> >['types'] type UsersActivityResponse = ReturnType type UsersActivity = UsersActivityResponse['data'][0] type ActivityResponse = CollectionActivityResponse | UsersActivityResponse export type UserActivityTypes = NonNullable< Exclude['1'], boolean> >['types'] type TokenActivityResponse = ReturnType type TokenActivity = TokenActivityResponse['data'][0] export type TokenActivityTypes = NonNullable< Exclude['1'], boolean> >['types'] type Activity = CollectionActivity | UsersActivity | TokenActivity type Source = 'token' | 'user' | 'collection' type Props = { data: ActivityResponse } type TokenActivityTableProps = { id: string activityTypes: NonNullable< Exclude['1'], boolean> >['types'] } export const TokenActivityTable: FC = ({ id, activityTypes, }) => { const data = useTokenActivity( id, { types: activityTypes, }, { revalidateOnMount: true, fallbackData: [], } ) useEffect(() => { data.mutate() return () => { data.setSize(1) } }, []) return } export const ActivityTable: FC = ({ data }) => { const loadMoreRef = useRef(null) const loadMoreObserver = useIntersectionObserver(loadMoreRef, {}) const activities = data.data useEffect(() => { const isVisible = !!loadMoreObserver?.isIntersecting if (isVisible) { data.fetchNextPage() } }, [loadMoreObserver?.isIntersecting]) return ( <> {!data.isValidating && !data.isFetchingPage && activities && activities.length === 0 ? ( No activity yet ) : ( {activities.map((activity, i) => { if (!activity) return null return ( ) })} )} {data.isValidating && ( )} ) } type ActivityTableRowProps = { source?: Source activity: Activity } type Logos = { [key: string]: JSX.Element } const logos: Logos = { transfer: , sale: , mint: , burned: , listing_canceled: , ask_cancel: , offer_canceled: , ask: , bid: , } type ActivityDescription = { [key: string]: string } const activityTypeToDesciptionMap: ActivityDescription = { ask_cancel: 'Listing Canceled', bid_cancel: 'Offer Canceled', mint: 'Mint', ask: 'List', bid: 'Offer', transfer: 'Transfer', sale: 'Sale', } const activityTypeToDesciption = (activityType: string) => { return activityTypeToDesciptionMap[activityType] || activityType } const ActivityTableRow: FC = ({ activity }) => { const isSmallDevice = useMediaQuery({ maxWidth: 700 }) const marketplaceChain = useMarketplaceChain() const blockExplorerBaseUrl = marketplaceChain?.blockExplorers?.default?.url || 'https://etherscan.io' if (!activity) { return null } let activityDescription = activityTypeToDesciption(activity?.type || '') const { displayName: toDisplayName } = useENSResolver(activity?.toAddress) const { displayName: fromDisplayName } = useENSResolver(activity?.fromAddress) if (isSmallDevice) { return ( {activity.type && logos[activity.type]} {activityDescription} {activity.price && activity.price.amount?.decimal !== 0 && activity.type && activity.type !== 'transfer' ? ( ) : ( - )} {!!activity.order?.source?.icon && ( {`${activity.order?.source?.name} )} {useTimeSince(activity?.timestamp)} {activity.txHash && ( )} {activity.fromAddress && activity.fromAddress !== zeroAddress ? ( {fromDisplayName} ) : ( - )} to {activity.toAddress && activity.toAddress !== zeroAddress ? ( {toDisplayName} ) : ( - )} ) } return ( {activity.type && logos[activity.type]} {activityDescription} {activity.price && activity.price.amount?.decimal !== 0 && activity.type && activity.type !== 'transfer' ? ( ) : ( - )} {!!activity.order?.source?.icon && ( {`${activity.order?.source?.name} )} {useTimeSince(activity?.timestamp)} {activity.txHash && ( )} {activity.fromAddress && activity.fromAddress !== zeroAddress ? ( {fromDisplayName} ) : ( - )} to {activity.toAddress && activity.toAddress !== zeroAddress ? ( {toDisplayName} ) : ( - )} ) }