Commit ed7099bf authored by aballerr's avatar aballerr Committed by GitHub

chore: Merging details page (#4585)

* Initial merge of details page
Co-authored-by: default avatarAlex Ball <alexball@UNISWAP-MAC-038.local>
parent 2604cdfd
import { badge, subheadSmall } from '../../css/common.css'
import { Box, BoxProps } from '../Box'
import { Row } from '../Flex'
import { VerifiedIcon } from '../icons'
export const CollectionProfile = ({
label,
isVerified,
name,
avatarUrl,
...props
}: {
isVerified?: boolean
label: string
name: string
avatarUrl: string
} & BoxProps) => {
return (
<Row {...props}>
{avatarUrl ? (
<Box as="img" src={avatarUrl} height="36" width="36" marginRight="12" borderRadius="round" />
) : (
<Box role="img" background="fallbackGradient" height="36" width="36" marginRight="12" borderRadius="round" />
)}
<div>
<Box as="span" color="darkGray" style={{ textTransform: 'uppercase' }} className={badge}>
{label}
</Box>
<Row marginTop="4" className={subheadSmall} color="blackBlue">
{name} {isVerified && <VerifiedIcon />}
</Row>
</div>
</Row>
)
}
import { bodySmall } from '../../css/common.css'
import { shortenAddress } from '../../utils/address'
import { Box, BoxProps } from '../Box'
import { Column, Row } from '../Flex'
const DetailItemLabel = (props: BoxProps) => <Box as="span" fontSize="14" color="darkGray" {...props} />
const DetailItemValue = (props: BoxProps) => <Box as="span" fontSize="14" marginLeft="4" color="blackBlue" {...props} />
const Detail = (props: BoxProps) => (
<Row justifyContent="space-between" width="full" style={{ minWidth: '224px' }} {...props} />
)
export const Details = ({
contractAddress,
tokenId,
metadataUrl,
tokenType,
totalSupply,
blockchain,
}: {
contractAddress: string
tokenId: string
metadataUrl: string
tokenType: string
totalSupply: number
blockchain: string
}) => (
<Row gap={{ md: '32', sm: '16' }} width="full" justifyContent="space-between" alignItems="flex-start" flexWrap="wrap">
<Column width={{ sm: 'full', md: 'auto' }} gap="10">
<Detail>
<DetailItemLabel>Contract Address: </DetailItemLabel>
<a
href={`https://etherscan.io/token/${contractAddress}`}
target="_blank"
rel="noreferrer"
style={{ textDecoration: 'none' }}
>
<DetailItemValue>{shortenAddress(contractAddress)}</DetailItemValue>
</a>
</Detail>
<Detail>
<DetailItemLabel>Token ID:</DetailItemLabel>
<DetailItemValue className={bodySmall}>{tokenId}</DetailItemValue>
</Detail>
{metadataUrl ? (
<Detail>
<DetailItemLabel>Metadata:</DetailItemLabel>
<a href={metadataUrl} target="_blank" rel="noreferrer" style={{ textDecoration: 'none' }}>
<DetailItemValue>{metadataUrl.slice(0, 12)}...</DetailItemValue>
</a>
</Detail>
) : null}
</Column>
<Column width={{ sm: 'full', md: 'auto' }} gap="10">
<Detail>
<DetailItemLabel>Contract type:</DetailItemLabel>
<DetailItemValue>{tokenType}</DetailItemValue>
</Detail>
<Detail>
<DetailItemLabel>Total supply:</DetailItemLabel>
<DetailItemValue>{totalSupply}</DetailItemValue>
</Detail>
<Detail>
<DetailItemLabel>Blockchain:</DetailItemLabel>
<DetailItemValue>{blockchain}</DetailItemValue>
</Detail>
</Column>
</Row>
)
import { style } from '@vanilla-extract/css'
import { sprinkles } from '../../css/sprinkles.css'
export const grid = style([
sprinkles({ gap: '16', display: 'grid' }),
{
gridTemplateColumns: 'repeat(4, 1fr)',
'@media': {
'(max-width: 1536px)': {
gridTemplateColumns: 'repeat(3, 1fr)',
},
'(max-width: 640px)': {
gridTemplateColumns: 'repeat(2, 1fr)',
},
},
},
])
import qs from 'query-string'
import { badge } from '../../css/common.css'
import { Box } from '../Box'
import { Column } from '../Flex'
import * as styles from './Traits.css'
interface TraitProps {
label: string
value: string
}
const Trait: React.FC<TraitProps> = ({ label, value }: TraitProps) => (
<Column backgroundColor="lightGray" padding="16" gap="4" borderRadius="12">
<Box
as="span"
className={badge}
color="darkGray"
whiteSpace="nowrap"
overflow="hidden"
textOverflow="ellipsis"
style={{ textTransform: 'uppercase' }}
maxWidth={{ sm: '120', md: '160' }}
>
{label}
</Box>
<Box
as="span"
color="blackBlue"
fontSize="16"
fontWeight="normal"
whiteSpace="nowrap"
overflow="hidden"
textOverflow="ellipsis"
maxWidth={{ sm: '120', md: '160' }}
>
{value}
</Box>
</Column>
)
export const Traits = ({
traits,
collectionAddress,
}: {
traits: {
value: string
trait_type: string
}[]
collectionAddress: string
}) => (
<div className={styles.grid}>
{traits.length === 0
? 'No traits'
: traits.map((item) => {
const params = qs.stringify(
{ traits: [`("${item.trait_type}","${item.value}")`] },
{
arrayFormat: 'comma',
}
)
return (
<a
key={`${item.trait_type}-${item.value}`}
href={`#/nft/collection/${collectionAddress}?${params}`}
style={{ textDecoration: 'none' }}
>
<Trait label={item.trait_type} value={item.value} />
</a>
)
})}
</div>
)
import { useQuery } from 'react-query'
import { useParams } from 'react-router-dom'
import { Details } from '../../components/details/Details'
import { fetchSingleAsset } from '../../queries'
import { CollectionInfoForAsset, GenieAsset } from '../../types'
const Asset = () => {
return <div>NFT Details Page</div>
const { tokenId = '', contractAddress = '' } = useParams()
const { data } = useQuery(['assetDetail', contractAddress, tokenId], () =>
fetchSingleAsset({ contractAddress, tokenId })
)
let asset = {} as GenieAsset
let collection = {} as CollectionInfoForAsset
if (data) {
asset = data[0] || {}
collection = data[1] || {}
}
return (
<div>
{' '}
<Details
contractAddress={contractAddress}
tokenId={tokenId}
tokenType={asset.tokenType}
blockchain="Ethereum"
metadataUrl={asset.externalLink}
totalSupply={collection.totalSupply}
/>
</div>
)
}
export default Asset
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