feat: Web 1854 listed card (#5160)
* 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 * init * fix * color * remove floor price when not on sell mode * remove floor when nft is listed * feat: Web 1858 disabled card 1155 when sell mode is on (#5169) * disabled states + tooltips * remove collection asset changes * popover offset changes * respond to padmini comment * respond to charlie
This commit is contained in:
parent
a95697daf8
commit
f1443671ef
@ -1,7 +1,7 @@
|
||||
import { Options, Placement } from '@popperjs/core'
|
||||
import Portal from '@reach/portal'
|
||||
import useInterval from 'lib/hooks/useInterval'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import React, { CSSProperties, useCallback, useMemo, useState } from 'react'
|
||||
import { usePopper } from 'react-popper'
|
||||
import styled from 'styled-components/macro'
|
||||
import { Z_INDEX } from 'theme/zIndex'
|
||||
@ -76,9 +76,20 @@ export interface PopoverProps {
|
||||
show: boolean
|
||||
children: React.ReactNode
|
||||
placement?: Placement
|
||||
offsetX?: number
|
||||
offsetY?: number
|
||||
style?: CSSProperties
|
||||
}
|
||||
|
||||
export default function Popover({ content, show, children, placement = 'auto' }: PopoverProps) {
|
||||
export default function Popover({
|
||||
content,
|
||||
show,
|
||||
children,
|
||||
placement = 'auto',
|
||||
offsetX = 8,
|
||||
offsetY = 8,
|
||||
style,
|
||||
}: PopoverProps) {
|
||||
const [referenceElement, setReferenceElement] = useState<HTMLDivElement | null>(null)
|
||||
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null)
|
||||
const [arrowElement, setArrowElement] = useState<HTMLDivElement | null>(null)
|
||||
@ -88,12 +99,12 @@ export default function Popover({ content, show, children, placement = 'auto' }:
|
||||
placement,
|
||||
strategy: 'fixed',
|
||||
modifiers: [
|
||||
{ name: 'offset', options: { offset: [8, 8] } },
|
||||
{ name: 'offset', options: { offset: [offsetX, offsetY] } },
|
||||
{ name: 'arrow', options: { element: arrowElement } },
|
||||
{ name: 'preventOverflow', options: { padding: 8 } },
|
||||
],
|
||||
}),
|
||||
[arrowElement, placement]
|
||||
[arrowElement, offsetX, offsetY, placement]
|
||||
)
|
||||
|
||||
const { styles, update, attributes } = usePopper(referenceElement, popperElement, options)
|
||||
@ -105,7 +116,9 @@ export default function Popover({ content, show, children, placement = 'auto' }:
|
||||
|
||||
return (
|
||||
<>
|
||||
<ReferenceElement ref={setReferenceElement as any}>{children}</ReferenceElement>
|
||||
<ReferenceElement style={style} ref={setReferenceElement as any}>
|
||||
{children}
|
||||
</ReferenceElement>
|
||||
<Portal>
|
||||
<PopoverContainer show={show} ref={setPopperElement as any} style={styles.popper} {...attributes.popper}>
|
||||
{content}
|
||||
|
@ -42,9 +42,10 @@ export function MouseoverTooltip({ text, disableHover, children, ...rest }: Omit
|
||||
const [show, setShow] = useState(false)
|
||||
const open = useCallback(() => setShow(true), [setShow])
|
||||
const close = useCallback(() => setShow(false), [setShow])
|
||||
const noOp = () => null
|
||||
return (
|
||||
<Tooltip {...rest} show={show} text={disableHover ? null : text}>
|
||||
<div onMouseEnter={open} onMouseLeave={close}>
|
||||
<div onMouseEnter={disableHover ? noOp : open} onMouseLeave={disableHover ? noOp : close}>
|
||||
{children}
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
@ -163,10 +163,19 @@ interface CardProps {
|
||||
addAssetToBag: () => void
|
||||
removeAssetFromBag: () => void
|
||||
children: ReactNode
|
||||
isDisabled?: boolean
|
||||
onClick?: () => void
|
||||
}
|
||||
|
||||
const Container = ({ asset, selected, addAssetToBag, removeAssetFromBag, children, onClick }: CardProps) => {
|
||||
const Container = ({
|
||||
asset,
|
||||
selected,
|
||||
addAssetToBag,
|
||||
removeAssetFromBag,
|
||||
children,
|
||||
isDisabled,
|
||||
onClick,
|
||||
}: CardProps) => {
|
||||
const [hovered, toggleHovered] = useReducer((s) => !s, false)
|
||||
const [href, setHref] = useState(baseHref(asset))
|
||||
|
||||
@ -210,8 +219,9 @@ const Container = ({ asset, selected, addAssetToBag, removeAssetFromBag, childre
|
||||
onMouseEnter={() => toggleHovered()}
|
||||
onMouseLeave={() => toggleHovered()}
|
||||
transition="250"
|
||||
cursor={asset.notForSale ? 'default' : 'pointer'}
|
||||
onClick={onClick ?? handleAssetInBag}
|
||||
opacity={isDisabled ? '0.5' : '1'}
|
||||
cursor={isDisabled ? 'default' : 'pointer'}
|
||||
onClick={isDisabled ? () => null : onClick ?? handleAssetInBag}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
@ -535,8 +545,14 @@ const ProfileNftDetails = ({ asset, isSellMode }: ProfileNftDetailsProps) => {
|
||||
</TruncatedTextRow>
|
||||
{asset.susFlag && <Suspicious />}
|
||||
</Row>
|
||||
<TruncatedTextRow className={subhead} style={{ color: themeVars.colors.textSecondary }}>
|
||||
{!!asset.floorPrice && isSellMode && <span>{`${floorFormatter(asset.floorPrice)} ETH Floor`}</span>}
|
||||
<TruncatedTextRow
|
||||
className={subhead}
|
||||
style={{ color: !asset.notForSale ? themeVars.colors.textPrimary : themeVars.colors.textSecondary }}
|
||||
>
|
||||
{!asset.notForSale && <span>{`${floorFormatter(asset.floor_sell_order_price)} ETH`}</span>}
|
||||
{asset.notForSale && isSellMode && !!asset.floorPrice && (
|
||||
<span>{`${floorFormatter(asset.floorPrice)} ETH Floor`}</span>
|
||||
)}
|
||||
</TruncatedTextRow>
|
||||
</Box>
|
||||
)
|
||||
|
@ -1,10 +1,14 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { MouseoverTooltip } from 'components/Tooltip'
|
||||
import { Box } from 'nft/components/Box'
|
||||
import * as Card from 'nft/components/collection/Card'
|
||||
import { AssetMediaType } from 'nft/components/collection/Card'
|
||||
import { bodySmall } from 'nft/css/common.css'
|
||||
import { themeVars } from 'nft/css/sprinkles.css'
|
||||
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`
|
||||
|
||||
@ -15,6 +19,21 @@ interface ViewMyNftsAssetProps {
|
||||
setCurrentTokenPlayingMedia: (tokenId: string | undefined) => void
|
||||
}
|
||||
|
||||
const getNftDisplayComponent = (
|
||||
assetMediaType: AssetMediaType,
|
||||
mediaShouldBePlaying: boolean,
|
||||
setCurrentTokenPlayingMedia: (tokenId: string | undefined) => void
|
||||
) => {
|
||||
switch (assetMediaType) {
|
||||
case AssetMediaType.Image:
|
||||
return <Card.Image />
|
||||
case AssetMediaType.Video:
|
||||
return <Card.Video shouldPlay={mediaShouldBePlaying} setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia} />
|
||||
case AssetMediaType.Audio:
|
||||
return <Card.Audio shouldPlay={mediaShouldBePlaying} setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia} />
|
||||
}
|
||||
}
|
||||
|
||||
export const ViewMyNftsAsset = ({
|
||||
asset,
|
||||
isSellMode,
|
||||
@ -53,6 +72,10 @@ export const ViewMyNftsAsset = ({
|
||||
|
||||
const assetMediaType = Card.useAssetMediaType(asset)
|
||||
|
||||
const isDisabled = asset.asset_contract.tokenType === 'ERC1155' || (isSellMode && asset.susFlag)
|
||||
const disabledTooltipText =
|
||||
asset.asset_contract.tokenType === 'ERC1155' ? 'ERC-1155 support coming soon' : 'Blocked from trading'
|
||||
|
||||
return (
|
||||
<Card.Container
|
||||
asset={asset}
|
||||
@ -60,16 +83,24 @@ export const ViewMyNftsAsset = ({
|
||||
addAssetToBag={() => handleSelect(false)}
|
||||
removeAssetFromBag={() => handleSelect(true)}
|
||||
onClick={onCardClick}
|
||||
isDisabled={isDisabled}
|
||||
>
|
||||
<Card.ImageContainer>
|
||||
{assetMediaType === AssetMediaType.Image ? (
|
||||
<Card.Image />
|
||||
) : assetMediaType === AssetMediaType.Video ? (
|
||||
<Card.Video shouldPlay={mediaShouldBePlaying} setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia} />
|
||||
) : (
|
||||
<Card.Audio shouldPlay={mediaShouldBePlaying} setCurrentTokenPlayingMedia={setCurrentTokenPlayingMedia} />
|
||||
)}
|
||||
</Card.ImageContainer>
|
||||
<MouseoverTooltip
|
||||
text={
|
||||
<Box as="span" className={bodySmall} style={{ color: themeVars.colors.textPrimary }}>
|
||||
<Trans>{disabledTooltipText}</Trans>{' '}
|
||||
</Box>
|
||||
}
|
||||
placement="bottom"
|
||||
offsetX={0}
|
||||
offsetY={-100}
|
||||
style={{ display: 'block' }}
|
||||
disableHover={!isDisabled}
|
||||
>
|
||||
<Card.ImageContainer>
|
||||
{getNftDisplayComponent(assetMediaType, mediaShouldBePlaying, setCurrentTokenPlayingMedia)}
|
||||
</Card.ImageContainer>
|
||||
</MouseoverTooltip>
|
||||
<Card.DetailsContainer>
|
||||
<Card.ProfileNftDetails asset={asset} isSellMode={isSellMode} />
|
||||
</Card.DetailsContainer>
|
||||
|
Loading…
Reference in New Issue
Block a user