Commit d9113fb6 authored by Jack Short's avatar Jack Short Committed by GitHub

feat: adding suspicious and pooled asset icons to cards + rarity (#4686)

* adding pooled assets and suspicious assets icons

* adding rarity

* better way to get states
parent 5dc0df21
......@@ -136,6 +136,24 @@ export const erc1155MinusButton = style([
},
])
export const rarityInfo = style([
sprinkles({
display: 'flex',
borderRadius: '4',
height: '16',
color: 'blackBlue',
background: 'lightGrayButton',
fontSize: '10',
fontWeight: 'semibold',
paddingX: '4',
}),
{
lineHeight: '12px',
letterSpacing: '0.04em',
backdropFilter: 'blur(6px)',
},
])
export const playbackSwitch = style([
sprinkles({
position: 'absolute',
......
import clsx from 'clsx'
import Column from 'components/Column'
import { MouseoverTooltip } from 'components/Tooltip'
import { Box } from 'nft/components/Box'
import * as styles from 'nft/components/collection/Card.css'
import { Row } from 'nft/components/Flex'
import { MinusIconLarge, PauseButtonIcon, PlayButtonIcon, PlusIconLarge } from 'nft/components/icons'
import {
MinusIconLarge,
PauseButtonIcon,
PlayButtonIcon,
PlusIconLarge,
PoolIcon,
RarityVerifiedIcon,
SuspiciousIcon20,
} from 'nft/components/icons'
import { body, subheadSmall } from 'nft/css/common.css'
import { themeVars, vars } from 'nft/css/sprinkles.css'
import { useIsMobile } from 'nft/hooks'
import { GenieAsset, UniformHeight, UniformHeights } from 'nft/types'
import { GenieAsset, Rarity, UniformHeight, UniformHeights } from 'nft/types'
import { fallbackProvider, putCommas } from 'nft/utils'
import {
createContext,
MouseEvent,
......@@ -20,6 +29,8 @@ import {
useState,
} from 'react'
import * as styles from './Card.css'
/* -------- ASSET CONTEXT -------- */
export interface CardContextProps {
asset: GenieAsset
......@@ -107,7 +118,6 @@ const Image = ({ uniformHeight, setUniformHeight }: ImageProps) => {
<Box display="flex" overflow="hidden">
<Box
as={'img'}
alt={asset.name || asset.tokenId}
width="full"
style={{
aspectRatio: uniformHeight === UniformHeights.notUniform ? '1' : 'auto',
......@@ -385,7 +395,11 @@ const SecondaryRow = ({ children }: { children: ReactNode }) => (
</Row>
)
const SecondaryDetails = ({ children }: { children: ReactNode }) => <Row>{children}</Row>
const SecondaryDetails = ({ children }: { children: ReactNode }) => (
<Row overflow="hidden" whiteSpace="nowrap">
{children}
</Row>
)
const SecondaryInfo = ({ children }: { children: ReactNode }) => {
return (
......@@ -517,6 +531,78 @@ const MarketplaceIcon = ({ marketplace }: { marketplace: string }) => {
)
}
/* -------- RANKING CARD -------- */
interface RankingProps {
rarity: Rarity
provider: { url?: string; rank: number }
rarityVerified: boolean
rarityLogo?: string
}
const Ranking = ({ rarity, provider, rarityVerified, rarityLogo }: RankingProps) => {
const { asset } = useCardContext()
return (
<MouseoverTooltip
text={
<Row>
<Box display="flex" marginRight="4">
<img src={rarityLogo} alt="cardLogo" width={16} />
</Box>
<Box width="full" fontSize="14">
{rarityVerified
? `Verified by ${asset.collectionName}`
: `Ranking by ${rarity.primaryProvider === 'Genie' ? fallbackProvider : rarity.primaryProvider}`}
</Box>
</Row>
}
placement="top"
>
<Box className={styles.rarityInfo}>
<Box paddingTop="2" paddingBottom="2" display="flex">
{putCommas(provider.rank)}
</Box>
<Box display="flex" height="16">
{rarityVerified ? <RarityVerifiedIcon /> : null}
</Box>
</Box>
</MouseoverTooltip>
)
}
const Suspicious = () => {
return (
<MouseoverTooltip
text={
<Box fontSize="14">
Reported for suspicious activity
<br />
on Opensea
</Box>
}
placement="top"
>
<Box display="flex" flexShrink="0" marginLeft="2">
<SuspiciousIcon20 width="20" height="20" />
</Box>
</MouseoverTooltip>
)
}
const Pool = () => {
return (
<MouseoverTooltip
text={<Box fontSize="14">This item is part of an NFT liquidity pool. Price increases as supply decreases.</Box>}
placement="top"
>
<Box display="flex" flexShrink="0" marginLeft="4" color="darkGray">
<PoolIcon width="20" height="20" />
</Box>
</MouseoverTooltip>
)
}
interface NoContentContainerProps {
uniformHeight: UniformHeight
}
......@@ -578,12 +664,15 @@ export {
Image,
InfoContainer,
MarketplaceIcon,
Pool,
PrimaryDetails,
PrimaryInfo,
PrimaryRow,
Ranking,
SecondaryDetails,
SecondaryInfo,
SecondaryRow,
Suspicious,
TertiaryInfo,
Video,
}
import { BigNumber } from '@ethersproject/bignumber'
import { useBag } from 'nft/hooks'
import { GenieAsset, UniformHeight } from 'nft/types'
import { formatWeiToDecimal } from 'nft/utils/currency'
import { isAudio } from 'nft/utils/isAudio'
import { isVideo } from 'nft/utils/isVideo'
import { GenieAsset, Markets, UniformHeight } from 'nft/types'
import { formatWeiToDecimal, isAudio, isVideo, rarityProviderLogo } from 'nft/utils'
import { MouseEvent, useMemo } from 'react'
import * as Card from './Card'
......@@ -21,6 +19,7 @@ interface CollectionAssetProps {
setUniformHeight: (u: UniformHeight) => void
mediaShouldBePlaying: boolean
setCurrentTokenPlayingMedia: (tokenId: string | undefined) => void
rarityVerified?: boolean
}
export const CollectionAsset = ({
......@@ -30,14 +29,13 @@ export const CollectionAsset = ({
setUniformHeight,
mediaShouldBePlaying,
setCurrentTokenPlayingMedia,
rarityVerified,
}: CollectionAssetProps) => {
const { addAssetToBag, removeAssetFromBag, itemsInBag, bagExpanded, toggleBag } = useBag((state) => ({
addAssetToBag: state.addAssetToBag,
removeAssetFromBag: state.removeAssetFromBag,
itemsInBag: state.itemsInBag,
bagExpanded: state.bagExpanded,
toggleBag: state.toggleBag,
}))
const addAssetToBag = useBag((state) => state.addAssetToBag)
const removeAssetFromBag = useBag((state) => state.removeAssetFromBag)
const itemsInBag = useBag((state) => state.itemsInBag)
const bagExpanded = useBag((state) => state.bagExpanded)
const toggleBag = useBag((state) => state.toggleBag)
const { quantity, isSelected } = useMemo(() => {
return {
......@@ -67,6 +65,13 @@ export const CollectionAsset = ({
}
}, [asset])
const { provider, rarityLogo } = useMemo(() => {
return {
provider: asset.rarity?.providers.find(({ provider: _provider }) => _provider === asset.rarity?.primaryProvider),
rarityLogo: rarityProviderLogo[asset.rarity?.primaryProvider ?? 0] ?? '',
}
}, [asset])
return (
<Card.Container asset={asset} selected={isSelected}>
{assetMediaType === AssetMediaType.Image ? (
......@@ -91,13 +96,23 @@ export const CollectionAsset = ({
<Card.PrimaryRow>
<Card.PrimaryDetails>
<Card.PrimaryInfo>{asset.name ? asset.name : `#${asset.tokenId}`}</Card.PrimaryInfo>
{asset.openseaSusFlag && <Card.Suspicious />}
</Card.PrimaryDetails>
{asset.rarity && provider && provider.rank && (
<Card.Ranking
rarity={asset.rarity}
provider={provider}
rarityVerified={!!rarityVerified}
rarityLogo={rarityLogo}
/>
)}
</Card.PrimaryRow>
<Card.SecondaryRow>
<Card.SecondaryDetails>
<Card.SecondaryInfo>
{notForSale ? '' : `${formatWeiToDecimal(asset.currentEthPrice)} ETH`}
</Card.SecondaryInfo>
{(asset.marketplace === Markets.NFTX || asset.marketplace === Markets.NFT20) && <Card.Pool />}
</Card.SecondaryDetails>
{asset.tokenType !== 'ERC1155' && asset.marketplace && (
<Card.MarketplaceIcon marketplace={asset.marketplace} />
......
......@@ -16,9 +16,10 @@ import { useInfiniteQuery } from 'react-query'
interface CollectionNftsProps {
contractAddress: string
rarityVerified?: boolean
}
export const CollectionNfts = ({ contractAddress }: CollectionNftsProps) => {
export const CollectionNfts = ({ contractAddress, rarityVerified }: CollectionNftsProps) => {
const traits = useCollectionFilters((state) => state.traits)
const minPrice = useCollectionFilters((state) => state.minPrice)
const maxPrice = useCollectionFilters((state) => state.maxPrice)
......@@ -127,6 +128,7 @@ export const CollectionNfts = ({ contractAddress }: CollectionNftsProps) => {
setUniformHeight={setUniformHeight}
mediaShouldBePlaying={asset.tokenId === currentTokenPlayingMedia}
setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia}
rarityVerified={rarityVerified}
/>
) : null
})}
......
......@@ -596,7 +596,7 @@ export const ShoppingCartIcon = (props: SVGProps) => (
/>
</svg>
)
export const RarityVerified = () => (
export const RarityVerifiedIcon = () => (
<svg width="17" height="17" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M4.5686 3.53439C4.74662 3.33093 5.0038 3.21423 5.27414 3.21423L10.1451 3.21423C10.4154 3.21423 10.6726 3.33093 10.8506 3.53438L13.0437 6.04077C13.3654 6.40839 13.3509 6.96139 13.0104 7.31163L8.38181 12.0724C8.01367 12.4511 7.40558 12.4511 7.03744 12.0724L2.40887 7.31163C2.06836 6.96139 2.05385 6.40839 2.37552 6.04077L4.5686 3.53439Z"
......
......@@ -74,7 +74,9 @@ const Collection = () => {
width: gridWidthOffset.interpolate((x) => `calc(100% - ${x as number}px)`),
}}
>
{contractAddress && <CollectionNfts contractAddress={contractAddress} />}
{contractAddress && (
<CollectionNfts contractAddress={contractAddress} rarityVerified={collectionStats?.rarityVerified} />
)}
</AnimatedBox>
</Row>
</Column>
......
......@@ -2,4 +2,8 @@ export * from './buildActivityAsset'
export * from './buildSellObject'
export * from './calcPoolPrice'
export * from './currency'
export * from './isAudio'
export * from './isVideo'
export * from './listNfts'
export * from './putCommas'
export * from './rarity'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment