Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [DetailsV2] initial details landing page view #6453

Merged
merged 8 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/nft/components/details/detailsV2/LandingPage.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { TEST_NFT_ASSET, TEST_NFT_COLLECTION_INFO_FOR_ASSET } from 'test-utils/constants'
import { render } from 'test-utils/render'

import { LandingPage } from './LandingPage'

describe('LandingPage', () => {
it('renders it correctly', () => {
const { asFragment } = render(
<LandingPage asset={TEST_NFT_ASSET} collection={TEST_NFT_COLLECTION_INFO_FOR_ASSET} />
)
expect(asFragment()).toMatchSnapshot()
})
})
102 changes: 102 additions & 0 deletions src/nft/components/details/detailsV2/LandingPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import Column, { ColumnCenter } from 'components/Column'
import Row from 'components/Row'
import { VerifiedIcon } from 'nft/components/icons'
import { CollectionInfoForAsset, GenieAsset } from 'nft/types'
import styled from 'styled-components/macro'
import { BREAKPOINTS, ThemedText } from 'theme'

const MAX_WIDTH = 560

const LandingPageContainer = styled.div`
display: flex;
flex-direction: column;
min-height: ${({ theme }) => `calc(100vh - ${theme.navHeight}px - ${theme.mobileBottomBarHeight}px)`};
align-items: center;
padding: 22px 20px 0px;
gap: 26px;

@media screen and (min-width: ${BREAKPOINTS.sm}px) {
gap: 64px;
padding-top: 28px;
}

@media screen and (min-width: ${BREAKPOINTS.md}px) {
min-height: ${({ theme }) => `calc(100vh - ${theme.navHeight}px )`};
}

@media screen and (min-width: ${BREAKPOINTS.xl}px) {
flex-direction: row;
padding-top: 0px;
padding-bottom: ${({ theme }) => `${theme.navHeight}px`};
gap: 80px;
}
`

const InfoContainer = styled(ColumnCenter)`
gap: 40px;

@media screen and (min-width: ${BREAKPOINTS.sm}px) {
width: ${MAX_WIDTH}px;
}
`

const InfoDetailsContainer = styled(Column)`
gap: 4px;
align-items: center;
`

const MediaContainer = styled.div`
width: 100%;
height: 100%;

@media screen and (min-width: ${BREAKPOINTS.sm}px) {
width: ${MAX_WIDTH}px;
height: ${MAX_WIDTH}px;
}
`

const StyledMedia = styled.img`
object-fit: contain;
height: 100%;
width: 100%;
`

const StyledSubheaderText = styled(ThemedText.SubHeaderSmall)`
line-height: 20px;

@media screen and (min-width: ${BREAKPOINTS.sm}px) {
line-height: 24px !important;
font-size: 16px !important;
}
`

const StyledHeadlineText = styled(ThemedText.HeadlineSmall)`
@media screen and (min-width: ${BREAKPOINTS.sm}px) {
line-height: 44px !important;
font-size: 36px !important;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!important is required in these locations to override the attributes set by props

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the props aren't inline styles so using more specific css rules should allow you to have more specificity 🤔 if you do something like this, would this work instead?

const StyledHeadlineText = styled(ThemedText.HeadlineSmall)
const InfoDetailsContainer = styled(Column)`
   > ${StyledHeadlineText} {
      line-height: 44px;
      font-size: 36px;
   }
`

}
`

interface LandingPageProps {
asset: GenieAsset
collection: CollectionInfoForAsset
}

export const LandingPage = ({ asset, collection }: LandingPageProps) => {
return (
<LandingPageContainer>
<MediaContainer>
<StyledMedia src={asset.imageUrl} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assuming all other forms of media nfts will be addressed in a follow up PR? eg /nfts/asset/0x19b703f65aa7e1e775bd06c2aa0d0d08c80f1c45/1652

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also BE is currently adding a type to handle media types so I was also kinda waiting on that

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

</MediaContainer>
<InfoContainer>
<InfoDetailsContainer>
<Row justify="center" gap="4px" align="center">
<StyledSubheaderText>{collection.collectionName}</StyledSubheaderText>
{collection.isVerified && <VerifiedIcon width="16px" height="16px" />}
</Row>
<StyledHeadlineText>{asset.name ?? `${asset.collectionName} #${asset.tokenId}`}</StyledHeadlineText>
</InfoDetailsContainer>
</InfoContainer>
</LandingPageContainer>
)
}
10 changes: 2 additions & 8 deletions src/nft/components/details/detailsV2/NftDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
import { CollectionInfoForAsset, GenieAsset } from 'nft/types'
import styled from 'styled-components/macro'

import { DataPage } from './DataPage'
import { LandingPage } from './LandingPage'

interface NftDetailsProps {
asset: GenieAsset
collection: CollectionInfoForAsset
}

const LandingPage = styled.div`
height: 100vh;
`

export const NftDetails = ({ asset, collection }: NftDetailsProps) => {
return (
<>
<LandingPage>
Details page for {asset.name} from {collection.collectionName}
</LandingPage>
<LandingPage asset={asset} collection={collection} />
<DataPage asset={asset} />
</>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`LandingPage renders it correctly 1`] = `
<DocumentFragment>
.c7 {
box-sizing: border-box;
margin: 0;
min-width: 0;
}

.c8 {
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
padding: 0;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
gap: 4px;
}

.c9 {
color: #7780A0;
}

.c11 {
color: #0D111C;
}

.c3 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
}

.c4 {
width: 100%;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}

.c0 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
min-height: calc(100vh - 72px - 52px);
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
padding: 22px 20px 0px;
gap: 26px;
}

.c5 {
gap: 40px;
}

.c6 {
gap: 4px;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}

.c1 {
width: 100%;
height: 100%;
}

.c2 {
object-fit: contain;
height: 100%;
width: 100%;
}

.c10 {
line-height: 20px;
}

@media screen and (min-width:640px) {
.c0 {
gap: 64px;
padding-top: 28px;
}
}

@media screen and (min-width:768px) {
.c0 {
min-height: calc(100vh - 72px );
}
}

@media screen and (min-width:1280px) {
.c0 {
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
padding-top: 0px;
padding-bottom: 72px;
gap: 80px;
}
}

@media screen and (min-width:640px) {
.c5 {
width: 560px;
}
}

@media screen and (min-width:640px) {
.c1 {
width: 560px;
height: 560px;
}
}

@media screen and (min-width:640px) {
.c10 {
line-height: 24px !important;
font-size: 16px !important;
}
}

@media screen and (min-width:640px) {
.c12 {
line-height: 44px !important;
font-size: 36px !important;
}
}

<div
class="c0"
>
<div
class="c1"
>
<img
class="c2"
src="https://cdn.center.app/1/0xED5AF388653567Af2F388E6224dC7C4b3241C544/3318/50ed67ad647d0aa0cad0b830d136a677efc2fb72a44587bc35f2a5fb334a7fdf.png"
/>
</div>
<div
class="c3 c4 c5"
>
<div
class="c3 c6"
>
<div
class="c7 c8"
>
<div
class="c9 c10 css-1aekuku"
>
Azuki
</div>
<svg
fill="none"
height="16px"
viewBox="0 0 20 20"
width="16px"
xmlns="http://www.w3.org/2000/svg"
>
<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="#FB118E"
/>
<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"
fill="white"
/>
</svg>
</div>
<div
class="c11 c12 css-iapcxi"
>
Azuki #3318
</div>
</div>
</div>
</div>
</DocumentFragment>
`;
14 changes: 13 additions & 1 deletion src/test-utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { V3Route } from '@uniswap/smart-order-router'
import { FeeAmount, Pool } from '@uniswap/v3-sdk'
import { NftActivityType, NftStandard, OrderStatus } from 'graphql/data/__generated__/types-and-hooks'
import JSBI from 'jsbi'
import { ActivityEvent, GenieAsset, Markets, WalletAsset } from 'nft/types'
import { ActivityEvent, CollectionInfoForAsset, GenieAsset, Markets, WalletAsset } from 'nft/types'
import { InterfaceTrade } from 'state/routing/types'

export const TEST_TOKEN_1 = new Token(1, '0x0000000000000000000000000000000000000001', 18, 'ABC', 'Abc')
Expand Down Expand Up @@ -154,3 +154,15 @@ export const TEST_NFT_ACTIVITY_EVENT: ActivityEvent = {
url: 'https://opensea.io/assets/0xed5af388653567af2f388e6224dc7c4b3241c544/5674',
eventTimestamp: 1682444662,
}

export const TEST_NFT_COLLECTION_INFO_FOR_ASSET: CollectionInfoForAsset = {
collectionDescription:
'Take the red bean to join the garden. View the collection at [azuki.com/gallery](https://azuki.com/gallery).\r\n\r\nAzuki starts with a collection of 10,000 avatars that give you membership access to The Garden: a corner of the internet where artists, builders, and web3 enthusiasts meet to create a decentralized future. Azuki holders receive access to exclusive drops, experiences, and more. Visit [azuki.com](https://azuki.com) for more details.\r\n\r\nWe rise together. We build together. We grow together.',
collectionImageUrl:
'https://i.seadn.io/gae/H8jOCJuQokNqGBpkBN5wk1oZwO7LM8bNnrHCaekV2nKjnCqw6UB5oaH8XyNeBDj6bA_n1mjejzhFQUP3O1NfjFLHr3FOaeHcTOOT?w=500&auto=format',
collectionName: 'Azuki',
discordUrl: 'https://discord.gg/azuki',
externalUrl: 'http://www.azuki.com',
isVerified: true,
totalSupply: 10000,
}