Commit a70ef432 authored by lynn's avatar lynn Committed by GitHub

feat: unlisted view my nft cards (#5129)

* init

* it's working with jack's card.tsx components

* add nft details on cards for view my nfts

* listed cards ready for review

* remove unnecessary code

* updated radius

* first round charlie comments

* respond all comments

* fix

* remove floor price when not on sell mode
parent 6edc7378
import graphql from 'babel-plugin-relay/macro'
import { parseEther } from 'ethers/lib/utils'
import { WalletAsset } from 'nft/types'
import { useLazyLoadQuery, usePaginationFragment } from 'react-relay'
......@@ -136,10 +137,24 @@ export function useNftBalanceQuery(
)
const walletAssets: WalletAsset[] = data.nftBalances?.edges?.map((queryAsset: NftBalanceQueryAsset) => {
const asset = queryAsset.node.ownedAsset
const ethPrice = parseEther(
asset?.listings?.edges[0]?.node.price.value?.toLocaleString('fullwide', { useGrouping: false }) ?? '0'
).toString()
return {
id: asset?.id,
image_url: asset?.image?.url,
image_preview_url: asset?.smallImage?.url,
imageUrl: asset?.image?.url,
smallImageUrl: asset?.smallImage?.url,
notForSale: asset?.listings?.edges?.length === 0,
animationUrl: asset?.animationUrl,
susFlag: asset?.suspiciousFlag,
priceInfo: asset?.listings
? {
ETHPrice: ethPrice,
baseAsset: 'ETH',
baseDecimals: '18',
basePrice: ethPrice,
}
: undefined,
name: asset?.name,
tokenId: asset?.tokenId,
asset_contract: {
......@@ -149,6 +164,7 @@ export function useNftBalanceQuery(
description: asset?.description,
image_url: asset?.collection?.image?.url,
payout_address: queryAsset?.node?.listingFees?.[0]?.payoutAddress,
tokenType: asset?.collection?.nftContracts?.[0].standard,
},
collection: asset?.collection,
collectionIsVerified: asset?.collection?.isVerified,
......
......@@ -27,7 +27,7 @@ const ProfileAssetRow = ({ asset }: { asset: WalletAsset }) => {
>
<img className={styles.removeIcon} src={'/nft/svgs/minusCircle.svg'} alt="Remove item" />
</Box>
<img className={styles.tagAssetImage} src={asset.image_url} alt={asset.name} />
<img className={styles.tagAssetImage} src={asset.imageUrl} alt={asset.name} />
</div>
<Column gap="4" overflow="hidden" flexWrap="nowrap">
<Box overflow="hidden" textOverflow="ellipsis" whiteSpace="nowrap" className={subhead}>
......
......@@ -142,7 +142,7 @@ export const getListings = (sellAssets: WalletAsset[]): [CollectionRow[], Listin
sellAssets.forEach((asset) => {
asset.marketplaces?.forEach((marketplace: ListingMarket) => {
const newListing = {
images: [asset.image_preview_url, marketplace.icon],
images: [asset.smallImageUrl, marketplace.icon],
name: asset.name || `#${asset.tokenId}`,
status: ListingStatus.DEFINED,
asset,
......
......@@ -25,6 +25,7 @@ export const notSelectedCard = style([
sprinkles({
backgroundColor: 'backgroundSurface',
borderColor: 'backgroundOutline',
borderRadius: '14',
}),
{
':hover': {
......@@ -45,6 +46,7 @@ export const selectedCard = style([
borderWidth: '3px',
}),
{
borderRadius: '18px',
':hover': {
backgroundColor: themeVars.colors.stateOverlayHover,
},
......
import { BigNumber } from '@ethersproject/bignumber'
import clsx from 'clsx'
import { MouseoverTooltip } from 'components/Tooltip'
import { Box } from 'nft/components/Box'
......@@ -9,12 +10,15 @@ import {
PlusIconLarge,
PoolIcon,
RarityVerifiedIcon,
VerifiedIcon,
} from 'nft/components/icons'
import { body, bodySmall } from 'nft/css/common.css'
import { body, bodySmall, buttonTextSmall, subhead, subheadSmall } from 'nft/css/common.css'
import { themeVars } from 'nft/css/sprinkles.css'
import { useIsMobile } from 'nft/hooks'
import { GenieAsset, Rarity, UniformHeight, UniformHeights } from 'nft/types'
import { GenieAsset, Rarity, UniformHeight, UniformHeights, WalletAsset } from 'nft/types'
import { isAudio, isVideo } from 'nft/utils'
import { fallbackProvider, putCommas } from 'nft/utils'
import { floorFormatter } from 'nft/utils/numbers'
import {
createContext,
MouseEvent,
......@@ -29,12 +33,13 @@ import {
import { AlertTriangle } from 'react-feather'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { colors } from 'theme/colors'
import * as styles from './Card.css'
/* -------- ASSET CONTEXT -------- */
export interface CardContextProps {
asset: GenieAsset
asset: GenieAsset | WalletAsset
hovered: boolean
selected: boolean
href: string
......@@ -45,25 +50,54 @@ export interface CardContextProps {
const CardContext = createContext<CardContextProps | undefined>(undefined)
const BORDER_RADIUS = '12'
const useCardContext = () => {
const context = useContext(CardContext)
if (!context) throw new Error('Must use context inside of provider')
return context
}
const baseHref = (asset: GenieAsset) => `/#/nfts/asset/${asset.address}/${asset.tokenId}?origin=collection`
export enum AssetMediaType {
Image,
Video,
Audio,
}
const useNotForSale = (asset: GenieAsset) =>
useMemo(() => {
let notForSale = true
notForSale = asset.notForSale || BigNumber.from(asset.priceInfo ? asset.priceInfo.ETHPrice : 0).lt(0)
return notForSale
}, [asset])
const useAssetMediaType = (asset: GenieAsset | WalletAsset) =>
useMemo(() => {
let assetMediaType = AssetMediaType.Image
if (asset.animationUrl) {
if (isAudio(asset.animationUrl)) {
assetMediaType = AssetMediaType.Audio
} else if (isVideo(asset.animationUrl)) {
assetMediaType = AssetMediaType.Video
}
}
return assetMediaType
}, [asset])
const baseHref = (asset: GenieAsset | WalletAsset) =>
'address' in asset ? `/#/nfts/asset/${asset.address}/${asset.tokenId}?origin=collection` : '/nfts/profile'
const DetailsLinkContainer = styled.a`
display: flex;
flex-shrink: 0;
text-decoration: none;
color: ${({ theme }) => theme.textSecondary};
font-size: 14px;
line-height: 20px;
weight: 400;
:hover {
color: ${({ theme }) => theme.accentAction};
opacity: ${({ theme }) => theme.opacity.hover};
}
:focus {
opacity: ${({ theme }) => theme.opacity.click};
}
`
......@@ -85,7 +119,7 @@ const Erc1155ControlsRow = styled.div`
const Erc1155ControlsContainer = styled.div`
display: flex;
border: 1px solid ${({ theme }) => theme.backgroundOutline};
border-radius: 12px 12px 12px 12px;
border-radius: ${BORDER_RADIUS}px;
overflow: hidden;
`
......@@ -124,14 +158,15 @@ const StyledImageContainer = styled.div`
/* -------- ASSET CARD -------- */
interface CardProps {
asset: GenieAsset
asset: GenieAsset | WalletAsset
selected: boolean
addAssetToBag: () => void
removeAssetFromBag: () => void
children: ReactNode
onClick?: () => void
}
const Container = ({ asset, selected, addAssetToBag, removeAssetFromBag, children }: CardProps) => {
const Container = ({ asset, selected, addAssetToBag, removeAssetFromBag, children, onClick }: CardProps) => {
const [hovered, toggleHovered] = useReducer((s) => !s, false)
const [href, setHref] = useState(baseHref(asset))
......@@ -155,26 +190,28 @@ const Container = ({ asset, selected, addAssetToBag, removeAssetFromBag, childre
if (hovered && assetRef.current?.matches(':hover') === false) toggleHovered()
}, [hovered])
const handleAssetInBag = (e: MouseEvent) => {
if (!asset.notForSale) {
e.preventDefault()
!selected ? addAssetToBag() : removeAssetFromBag()
}
}
return (
<CardContext.Provider value={providerValue}>
<Box
position={'relative'}
ref={assetRef}
borderRadius={'20'}
borderBottomLeftRadius={'12'}
borderBottomRightRadius={'12'}
borderRadius={BORDER_RADIUS}
borderBottomLeftRadius={BORDER_RADIUS}
borderBottomRightRadius={BORDER_RADIUS}
className={selected ? styles.selectedCard : styles.notSelectedCard}
draggable={false}
onMouseEnter={() => toggleHovered()}
onMouseLeave={() => toggleHovered()}
transition="250"
cursor={asset.notForSale ? 'default' : 'pointer'}
onClick={(e: MouseEvent) => {
if (!asset.notForSale) {
e.preventDefault()
!selected ? addAssetToBag() : removeAssetFromBag()
}
}}
onClick={onClick ?? handleAssetInBag}
>
{children}
</Box>
......@@ -188,8 +225,8 @@ const ImageContainer = ({ children }: { children: ReactNode }) => (
/* -------- CARD IMAGE -------- */
interface ImageProps {
uniformHeight: UniformHeight
setUniformHeight: (height: UniformHeight) => void
uniformHeight?: UniformHeight
setUniformHeight?: (height: UniformHeight) => void
}
const Image = ({ uniformHeight, setUniformHeight }: ImageProps) => {
......@@ -199,11 +236,11 @@ const Image = ({ uniformHeight, setUniformHeight }: ImageProps) => {
const isMobile = useIsMobile()
if (noContent) {
return <NoContentContainer uniformHeight={uniformHeight} />
return <NoContentContainer uniformHeight={uniformHeight ?? UniformHeights.unset} />
}
return (
<Box display="flex" overflow="hidden" borderTopLeftRadius="20" borderTopRightRadius="20">
<Box display="flex" overflow="hidden" borderTopLeftRadius={BORDER_RADIUS} borderTopRightRadius={BORDER_RADIUS}>
<Box
as={'img'}
width="full"
......@@ -216,11 +253,13 @@ const Image = ({ uniformHeight, setUniformHeight }: ImageProps) => {
draggable={false}
onError={() => setNoContent(true)}
onLoad={(e) => {
if (setUniformHeight) {
if (uniformHeight === UniformHeights.unset) {
setUniformHeight(e.currentTarget.clientHeight)
} else if (uniformHeight !== UniformHeights.notUniform && e.currentTarget.clientHeight !== uniformHeight) {
setUniformHeight(UniformHeights.notUniform)
}
}
setLoaded(true)
}}
className={clsx(hovered && !isMobile && styles.cardImageHover, !loaded && styles.loadingBackground)}
......@@ -230,8 +269,8 @@ const Image = ({ uniformHeight, setUniformHeight }: ImageProps) => {
}
interface MediaProps {
uniformHeight: UniformHeight
setUniformHeight: (u: UniformHeight) => void
uniformHeight?: UniformHeight
setUniformHeight?: (u: UniformHeight) => void
shouldPlay: boolean
setCurrentTokenPlayingMedia: (tokenId: string | undefined) => void
}
......@@ -270,7 +309,7 @@ const Video = ({ uniformHeight, setUniformHeight, shouldPlay, setCurrentTokenPla
draggable={false}
onError={() => setNoContent(true)}
onLoad={() => {
if (uniformHeight !== UniformHeights.notUniform) {
if (setUniformHeight && uniformHeight !== UniformHeights.notUniform) {
setUniformHeight(UniformHeights.notUniform)
}
......@@ -347,7 +386,7 @@ const Audio = ({ uniformHeight, setUniformHeight, shouldPlay, setCurrentTokenPla
}
if (noContent) {
return <NoContentContainer uniformHeight={uniformHeight} />
return <NoContentContainer uniformHeight={uniformHeight ?? UniformHeights.unset} />
}
return (
......@@ -366,11 +405,16 @@ const Audio = ({ uniformHeight, setUniformHeight, shouldPlay, setCurrentTokenPla
draggable={false}
onError={() => setNoContent(true)}
onLoad={(e) => {
if (setUniformHeight) {
if (uniformHeight === UniformHeights.unset) {
setUniformHeight(e.currentTarget.clientHeight)
} else if (uniformHeight !== UniformHeights.notUniform && e.currentTarget.clientHeight !== uniformHeight) {
} else if (
uniformHeight !== UniformHeights.notUniform &&
e.currentTarget.clientHeight !== uniformHeight
) {
setUniformHeight(UniformHeights.notUniform)
}
}
setImageLoaded(true)
}}
className={clsx(hovered && !isMobile && styles.cardImageHover, !imageLoaded && styles.loadingBackground)}
......@@ -453,6 +497,51 @@ const InfoContainer = ({ children }: { children: ReactNode }) => {
)
}
const TruncatedTextRow = styled(Row)`
padding: 2px;
white-space: nowrap;
text-overflow: ellipsis;
display: block;
overflow: hidden;
`
interface ProfileNftDetailsProps {
asset: WalletAsset
isSellMode: boolean
}
const ProfileNftDetails = ({ asset, isSellMode }: ProfileNftDetailsProps) => {
const assetName = () => {
if (!asset.name && !asset.tokenId) return
return !!asset.name ? asset.name : `#${asset.tokenId}`
}
return (
<Box overflow="hidden" width="full" flexWrap="nowrap">
<Row justifyItems="flex-start">
<TruncatedTextRow className={bodySmall} style={{ color: themeVars.colors.textSecondary }}>
{!!asset.asset_contract.name && <span>{asset.asset_contract.name}</span>}
</TruncatedTextRow>
{asset.collectionIsVerified && <VerifiedIcon height="16px" width="16px" fill={colors.magentaVibrant} />}
</Row>
<Row justifyItems="flex-start">
<TruncatedTextRow
className={subheadSmall}
style={{
color: themeVars.colors.textPrimary,
}}
>
{assetName()}
</TruncatedTextRow>
{asset.susFlag && <Suspicious />}
</Row>
<TruncatedTextRow className={subhead} style={{ color: themeVars.colors.textSecondary }}>
{!!asset.floorPrice && isSellMode && <span>{`${floorFormatter(asset.floorPrice)} ETH Floor`}</span>}
</TruncatedTextRow>
</Box>
)
}
const PrimaryRow = ({ children }: { children: ReactNode }) => (
<Row gap="8" justifyContent="space-between">
{children}
......@@ -570,7 +659,7 @@ const DetailsLink = () => {
e.stopPropagation()
}}
>
Details
<Box className={buttonTextSmall}>Details</Box>
</DetailsLinkContainer>
)
}
......@@ -598,7 +687,10 @@ const Ranking = ({ rarity, provider, rarityVerified, rarityLogo }: RankingProps)
</Box>
<Box width="full" className={bodySmall}>
{rarityVerified
? `Verified by ${asset.collectionName}`
? `Verified by ${
('collectionName' in asset && asset.collectionName) ||
('asset_contract' in asset && asset.asset_contract?.name)
}`
: `Ranking by ${rarity.primaryProvider === 'Genie' ? fallbackProvider : rarity.primaryProvider}`}
</Box>
</Row>
......@@ -716,6 +808,7 @@ export {
PrimaryDetails,
PrimaryInfo,
PrimaryRow,
ProfileNftDetails,
Ranking,
SecondaryDetails,
SecondaryInfo,
......@@ -723,5 +816,7 @@ export {
Suspicious,
SUSPICIOUS_TEXT,
TertiaryInfo,
useAssetMediaType,
useNotForSale,
Video,
}
import { BigNumber } from '@ethersproject/bignumber'
import { sendAnalyticsEvent } from 'analytics'
import { EventName, PageName } from 'analytics/constants'
import { useTrace } from 'analytics/Trace'
import { useBag } from 'nft/hooks'
import { GenieAsset, Markets, UniformHeight } from 'nft/types'
import { formatWeiToDecimal, isAudio, isVideo, rarityProviderLogo } from 'nft/utils'
import { formatWeiToDecimal, rarityProviderLogo } from 'nft/utils'
import { useCallback, useMemo } from 'react'
import { useAssetMediaType, useNotForSale } from './Card'
import { AssetMediaType } from './Card'
import * as Card from './Card'
enum AssetMediaType {
Image,
Video,
Audio,
}
interface CollectionAssetProps {
asset: GenieAsset
isMobile: boolean
......@@ -53,24 +48,8 @@ export const CollectionAsset = ({
}
}, [asset, itemsInBag])
const { notForSale, assetMediaType } = useMemo(() => {
let notForSale = true
let assetMediaType = AssetMediaType.Image
notForSale = asset.notForSale || BigNumber.from(asset.priceInfo ? asset.priceInfo.ETHPrice : 0).lt(0)
if (asset.animationUrl) {
if (isAudio(asset.animationUrl)) {
assetMediaType = AssetMediaType.Audio
} else if (isVideo(asset.animationUrl)) {
assetMediaType = AssetMediaType.Video
}
}
return {
notForSale,
assetMediaType,
}
}, [asset])
const notForSale = useNotForSale(asset)
const assetMediaType = useAssetMediaType(asset)
const { provider, rarityLogo } = useMemo(() => {
return {
......
......@@ -173,7 +173,7 @@ export const VerifiedIcon = (props: SVGProps) => (
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M4.52795 13.8056C4.52719 14.4043 4.6712 14.8474 4.95997 15.135C5.24798 15.4233 5.68496 15.5651 6.27091 15.5605H7.57497C7.62945 15.5585 7.68379 15.5676 7.73463 15.5873C7.78547 15.607 7.83176 15.6369 7.87062 15.6752L8.79884 16.5928C9.22054 17.0142 9.63382 17.2237 10.0387 17.2214C10.4436 17.2191 10.8569 17.0096 11.2786 16.5928L12.1954 15.6752C12.2356 15.6365 12.2832 15.6063 12.3354 15.5866C12.3876 15.5669 12.4433 15.558 12.499 15.5605H13.7951C14.3871 15.5613 14.8283 15.4171 15.1186 15.1281C15.4089 14.839 15.5541 14.3959 15.5541 13.7987V12.5014C15.5511 12.389 15.5923 12.2799 15.6687 12.1974L16.5854 11.2798C17.0125 10.86 17.2245 10.4467 17.2214 10.0399C17.2184 9.63305 17.0064 9.21935 16.5854 8.79878L15.6687 7.88115C15.592 7.79886 15.5509 7.68965 15.5541 7.57719V6.2799C15.5533 5.68191 15.4093 5.23878 15.1221 4.95049C14.8348 4.66221 14.3925 4.51806 13.7951 4.51806H12.499C12.4433 4.52036 12.3877 4.51138 12.3355 4.49168C12.2834 4.47197 12.2357 4.44193 12.1954 4.40336L11.2786 3.48574C10.8569 3.06439 10.4436 2.85487 10.0387 2.85717C9.63382 2.85946 9.22054 3.06898 8.79884 3.48574L7.87062 4.40336C7.83164 4.44148 7.78536 4.4713 7.73454 4.49101C7.68373 4.51072 7.62943 4.51993 7.57497 4.51806H6.27091C5.67961 4.51883 5.23995 4.66182 4.95194 4.94705C4.66393 5.23228 4.51992 5.67656 4.51992 6.2799V7.58063C4.52314 7.69309 4.48197 7.80229 4.40533 7.88459L3.48859 8.80222C3.06765 9.22203 2.85718 9.63572 2.85718 10.0433C2.85718 10.4509 3.07033 10.8653 3.49662 11.2867L4.41336 12.2043C4.48979 12.2867 4.53092 12.3958 4.52795 12.5083V13.8056Z"
fill="#4673FA"
fill={props.fill ?? '#4673FA'}
/>
<path
d="M9.99737 12.4943C9.86205 12.7005 9.6623 12.8164 9.43032 12.8164C9.19191 12.8164 9.00504 12.7198 8.83106 12.4943L7.31036 10.6385C7.20082 10.5032 7.14282 10.3614 7.14282 10.2068C7.14282 9.88458 7.38768 9.63327 7.70342 9.63327C7.89673 9.63327 8.05138 9.70415 8.20603 9.90391L9.40455 11.4311L11.9498 7.34577C12.0851 7.12669 12.2591 7.02359 12.4524 7.02359C12.7553 7.02359 13.0388 7.23623 13.0388 7.55197C13.0388 7.70017 12.9615 7.85482 12.8777 7.99014L9.99737 12.4943Z"
......
......@@ -796,7 +796,7 @@ const NFTListRow = ({ asset, globalPriceMethod, globalPrice, setGlobalPrice, sel
marginLeft={localMarkets.length > 1 ? '8' : '0'}
marginRight="8"
transition="500"
src={asset.image_url || '/nft/svgs/image-placeholder.svg'}
src={asset.imageUrl || '/nft/svgs/image-placeholder.svg'}
/>
</Box>
<Column gap="4" minWidth="0">
......
......@@ -30,7 +30,7 @@ import shallow from 'zustand/shallow'
import { EmptyWalletContent } from './EmptyWalletContent'
import * as styles from './ProfilePage.css'
import { WalletAssetDisplay } from './WalletAssetDisplay'
import { ViewMyNftsAsset } from './ViewMyNftsAsset'
const SellModeButton = styled.button<{ active: boolean }>`
display: flex;
......@@ -79,6 +79,7 @@ export const ProfilePage = () => {
const setSellPageState = useProfilePageState((state) => state.setProfilePageState)
const [isFiltersExpanded, setFiltersExpanded] = useFiltersExpanded()
const isMobile = useIsMobile()
const [currentTokenPlayingMedia, setCurrentTokenPlayingMedia] = useState<string | undefined>()
const handleSellModeClick = useCallback(() => {
resetSellAssets()
......@@ -171,7 +172,14 @@ export const ProfilePage = () => {
<div className={assetList}>
{ownerAssets?.length
? ownerAssets.map((asset, index) => (
<WalletAssetDisplay asset={asset} isSellMode={isSellMode} key={index} />
<div key={index}>
<ViewMyNftsAsset
asset={asset}
isSellMode={isSellMode}
mediaShouldBePlaying={asset.tokenId === currentTokenPlayingMedia}
setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia}
/>
</div>
))
: null}
</div>
......
import * as Card from 'nft/components/collection/Card'
import { AssetMediaType } from 'nft/components/collection/Card'
import { useBag, useIsMobile, useSellAsset } from 'nft/hooks'
import { WalletAsset } from 'nft/types'
import { useMemo } from 'react'
import { useNavigate } from 'react-router-dom'
const NFT_DETAILS_HREF = (asset: WalletAsset) =>
`/nfts/asset/${asset.asset_contract.address}/${asset.tokenId}?origin=profile`
interface ViewMyNftsAssetProps {
asset: WalletAsset
isSellMode: boolean
mediaShouldBePlaying: boolean
setCurrentTokenPlayingMedia: (tokenId: string | undefined) => void
}
export const ViewMyNftsAsset = ({
asset,
isSellMode,
mediaShouldBePlaying,
setCurrentTokenPlayingMedia,
}: ViewMyNftsAssetProps) => {
const sellAssets = useSellAsset((state) => state.sellAssets)
const selectSellAsset = useSellAsset((state) => state.selectSellAsset)
const removeSellAsset = useSellAsset((state) => state.removeSellAsset)
const cartExpanded = useBag((state) => state.bagExpanded)
const toggleCart = useBag((state) => state.toggleBag)
const isMobile = useIsMobile()
const navigate = useNavigate()
const isSelected = useMemo(() => {
return sellAssets.some(
(item) => item.tokenId === asset.tokenId && item.asset_contract.address === asset.asset_contract.address
)
}, [asset, sellAssets])
const onCardClick = () => {
isSellMode ? handleSelect(isSelected) : navigate(NFT_DETAILS_HREF(asset))
}
const handleSelect = (removeAsset: boolean) => {
removeAsset ? removeSellAsset(asset) : selectSellAsset(asset)
if (
!cartExpanded &&
!sellAssets.find(
(x) => x.tokenId === asset.tokenId && x.asset_contract.address === asset.asset_contract.address
) &&
!isMobile
)
toggleCart()
}
const assetMediaType = Card.useAssetMediaType(asset)
return (
<Card.Container
asset={asset}
selected={isSelected}
addAssetToBag={() => handleSelect(false)}
removeAssetFromBag={() => handleSelect(true)}
onClick={onCardClick}
>
<Card.ImageContainer>
{assetMediaType === AssetMediaType.Image ? (
<Card.Image />
) : assetMediaType === AssetMediaType.Video ? (
<Card.Video shouldPlay={mediaShouldBePlaying} setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia} />
) : (
<Card.Audio shouldPlay={mediaShouldBePlaying} setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia} />
)}
</Card.ImageContainer>
<Card.DetailsContainer>
<Card.ProfileNftDetails asset={asset} isSellMode={isSellMode} />
</Card.DetailsContainer>
</Card.Container>
)
}
......@@ -71,7 +71,7 @@ export const WalletAssetDisplay = ({ asset, isSellMode }: { asset: WalletAsset;
width="full"
borderTopLeftRadius="20"
borderTopRightRadius="20"
src={asset.image_url ?? '/nft/svgs/image-placeholder.svg'}
src={asset.imageUrl ?? '/nft/svgs/image-placeholder.svg'}
style={{ aspectRatio: '1' }}
/>
<Column paddingTop="12" paddingX="12">
......
import { NftMarketplace, OrderStatus, OrderType } from 'graphql/data/nft/__generated__/DetailsQuery.graphql'
import { GenieCollection } from '../common'
import { GenieCollection, PriceInfo, TokenType } from '../common'
export interface ListingMarket {
name: string
......@@ -41,8 +41,12 @@ export interface Listing {
export interface WalletAsset {
id?: string
image_url: string
image_preview_url: string
imageUrl: string
smallImageUrl: string
notForSale: boolean
animationUrl: string
susFlag: boolean
priceInfo: PriceInfo
name: string
tokenId: string
asset_contract: {
......@@ -52,6 +56,7 @@ export interface WalletAsset {
description: string
image_url: string
payout_address: string
tokenType: TokenType
}
collection: GenieCollection
collectionIsVerified: boolean
......
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