Skip to content

Commit

Permalink
feat: add buy with crypto button to ENS detail page (#2198)
Browse files Browse the repository at this point in the history
* feat: add buy with crypto button to ENS detail page

* feat: remove buy page and add tests for the actions component

* fix: eslint issue

* fix: eslint issue

* feat: add isPartOfEstate logic to DetailsBox

* feat: add estateInfo styles

* feat: remove estate logic from details

* test: fix test

* chore: eslint fixes
  • Loading branch information
juanmahidalgo committed Apr 2, 2024
1 parent f89cdcc commit d145fe8
Show file tree
Hide file tree
Showing 16 changed files with 138 additions and 201 deletions.
14 changes: 11 additions & 3 deletions webapp/src/components/AssetPage/Actions/Actions.container.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import { connect } from 'react-redux'
import { Order } from '@dcl/schemas'
import { openModal } from 'decentraland-dapps/dist/modules/modal/actions'
import { NFT } from '../../../modules/nft/types'
import { getCurrentOrder } from '../../../modules/order/selectors'
import { RootState } from '../../../modules/reducer'
import { getNFTBids } from '../../../modules/ui/nft/bid/selectors'
import { getWallet } from '../../../modules/wallet/selectors'
import Actions from './Actions'
import { MapDispatch, MapDispatchProps, MapStateProps } from './Actions.types'
import { MapDispatch, MapDispatchProps, MapStateProps, OwnProps } from './Actions.types'

const mapState = (state: RootState): MapStateProps => ({
wallet: getWallet(state),
order: getCurrentOrder(state),
bids: getNFTBids(state)
})

const mapDispatch = (dispatch: MapDispatch): MapDispatchProps => ({
onLeavingSite: (nft: NFT) => dispatch(openModal('LeavingSiteModal', { nft }))
const mapDispatch = (dispatch: MapDispatch, ownProps: OwnProps): MapDispatchProps => ({
onLeavingSite: (nft: NFT) => dispatch(openModal('LeavingSiteModal', { nft })),
onBuyWithCrypto: (order: Order) =>
dispatch(
openModal('BuyNftWithCryptoModal', {
nft: ownProps.nft,
order
})
)
})

export default connect(mapState, mapDispatch)(Actions)
115 changes: 115 additions & 0 deletions webapp/src/components/AssetPage/Actions/Actions.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { Bid, Order } from '@dcl/schemas'
import { t } from 'decentraland-dapps/dist/modules/translation/utils'
import { Wallet } from 'decentraland-dapps/dist/modules/wallet'
import { NFT } from '../../../modules/nft/types'
import { VendorName } from '../../../modules/vendor'
import { renderWithProviders } from '../../../utils/test'
import Actions from './Actions'
import { Props } from './Actions.types'

describe('Actions Component', () => {
let props: Props
let nft: NFT
let wallet: Wallet
let order: Order | null
let bids: Bid[]
let onBuyWithCrypto: (order: Order) => void
let onLeavingSite
let address: string

beforeEach(() => {
address = '0xAnAddress'
wallet = { address: 'user-wallet-address' } as Wallet
nft = {
contractAddress: 'nft-contract-address',
tokenId: 'nft-token-id',
vendor: VendorName.DECENTRALAND,
data: {}
} as NFT
// order = null
bids = []
onBuyWithCrypto = jest.fn()
onLeavingSite = jest.fn()
props = {
wallet,
nft,
order,
bids,
onBuyWithCrypto,
onLeavingSite
}
})

describe('and it has an order', () => {
beforeEach(() => {
order = {} as Order
})
describe('and it is owner and can sell', () => {
beforeEach(() => {
nft.owner = address
wallet.address = nft.owner
})
it('should render the update and the cancel sale button', () => {
const { queryByText } = renderWithProviders(<Actions {...props} order={order} />)
const updateButton = queryByText(t('asset_page.actions.update'))
const cancelButton = queryByText(t('asset_page.actions.cancel_sale'))
expect(updateButton).toBeInTheDocument()
expect(cancelButton).toBeInTheDocument()
})
})
describe('and its not the owner', () => {
beforeEach(() => {
nft.owner = '0xAnotherAddress'
wallet.address = address
})
it('should render the bid button and not render the update and the cancel sale button', () => {
const { queryByText } = renderWithProviders(<Actions {...props} order={order} />)
const bidButton = queryByText(t('asset_page.actions.bid'))
const updateButton = queryByText(t('asset_page.actions.update'))
const cancelButton = queryByText(t('asset_page.actions.cancel_sale'))
expect(bidButton).toBeInTheDocument()
expect(updateButton).not.toBeInTheDocument()
expect(cancelButton).not.toBeInTheDocument()
})
})
})
describe('and there is no order', () => {
beforeEach(() => {
order = null
})
describe('and its the owner', () => {
beforeEach(() => {
nft.owner = address
wallet.address = nft.owner
})
describe('and its an ENS name', () => {
beforeEach(() => {
nft.data.ens = { subdomain: '' }
})
it('should render the manage button', () => {
const { queryByText } = renderWithProviders(<Actions {...props} order={order} />)
const manageButton = queryByText(t('asset_page.actions.manage'))
expect(manageButton).toBeInTheDocument()
})
})
it('should render the sell and transfer button', () => {
const { queryByText } = renderWithProviders(<Actions {...props} order={order} />)
const sellButton = queryByText(t('asset_page.actions.sell'))
const transferButton = queryByText(t('asset_page.actions.transfer'))
expect(sellButton).toBeInTheDocument()
expect(transferButton).toBeInTheDocument()
})
})
describe('and it is not the owner', () => {
beforeEach(() => {
nft.owner = '0xAnotherAddress'
wallet.address = address
})
it('should render the bid button', () => {
const { queryByText } = renderWithProviders(<Actions {...props} order={order} />)
const bidButton = queryByText(t('asset_page.actions.bid'))
expect(bidButton).toBeInTheDocument()
})
})
})
})
12 changes: 5 additions & 7 deletions webapp/src/components/AssetPage/Actions/Actions.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React from 'react'
import { memo } from 'react'
import { Link } from 'react-router-dom'
import { t } from 'decentraland-dapps/dist/modules/translation/utils'
import { Button } from 'decentraland-ui'
import { builderUrl } from '../../../lib/environment'
import { AssetType } from '../../../modules/asset/types'
import { isOwnedBy } from '../../../modules/asset/utils'
import { locations } from '../../../modules/routing/locations'
import { VendorFactory } from '../../../modules/vendor'
import { BuyWithCryptoButton } from '../SaleActionBox/BuyNFTButtons/BuyWithCryptoButton'
import { Props } from './Actions.types'
import styles from './Actions.module.css'

const Actions = (props: Props) => {
const { wallet, nft, order, bids, onLeavingSite } = props
const { wallet, nft, order, bids, onLeavingSite, onBuyWithCrypto } = props
const { contractAddress, tokenId, data } = nft

const { bidService, orderService } = VendorFactory.build(nft.vendor)
Expand All @@ -37,9 +37,7 @@ const Actions = (props: Props) => {
</>
) : !isOwner ? (
<>
<Button as={Link} to={locations.buy(AssetType.NFT, contractAddress, tokenId)} primary fluid>
{t('asset_page.actions.buy')}
</Button>
<BuyWithCryptoButton asset={nft} onClick={() => onBuyWithCrypto} />
{canBid ? (
<Button as={Link} to={locations.bid(contractAddress, tokenId)} fluid>
{t('asset_page.actions.bid')}
Expand Down Expand Up @@ -78,4 +76,4 @@ const Actions = (props: Props) => {
)
}

export default React.memo(Actions)
export default memo(Actions)
3 changes: 2 additions & 1 deletion webapp/src/components/AssetPage/Actions/Actions.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ export type Props = {
order: Order | null
bids: Bid[]
onLeavingSite: (nft: NFT) => ReturnType<typeof openModal>
onBuyWithCrypto: (order: Order) => void
}

export type MapStateProps = Pick<Props, 'wallet' | 'order' | 'bids'>
export type MapDispatchProps = Pick<Props, 'onLeavingSite'>
export type MapDispatchProps = Pick<Props, 'onLeavingSite' | 'onBuyWithCrypto'>
export type MapDispatch = Dispatch<OpenModalAction>
export type OwnProps = Pick<Props, 'nft'>
16 changes: 2 additions & 14 deletions webapp/src/components/AssetPage/EstateDetail/EstateDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@ import React from 'react'
import classNames from 'classnames'
import { t } from 'decentraland-dapps/dist/modules/translation/utils'
import { Badge } from 'decentraland-ui'
import { isLand } from '../../../modules/nft/utils'
import { AssetImage } from '../../AssetImage'
import { Network } from '../../Network'
import Price from '../../Price'
import { Actions } from '../Actions'
import BaseDetail from '../BaseDetail'
import { BidList } from '../BidList'
import { Description } from '../Description'
import Expiration from '../Expiration'
import { JumpIn } from '../JumpIn'
import { Owner } from '../Owner'
import { ProximityHighlights } from '../ProximityHighlights'
Expand All @@ -36,7 +31,7 @@ const EstateDetail = ({ nft, order, rental }: Props) => {
className="EstateDetail"
asset={nft}
rental={rental ?? undefined}
showDetails={isLand(nft)}
showDetails
assetImage={
<>
<AssetImage
Expand Down Expand Up @@ -69,14 +64,7 @@ const EstateDetail = ({ nft, order, rental }: Props) => {
<ProximityHighlights nft={nft} />
</>
}
box={
<>
<Price asset={nft} />
<Network asset={nft} />
{estate.size > 0 && <Actions nft={nft} />}
<Expiration />
</>
}
box={<></>}
below={
<>
<BidList nft={nft} />
Expand Down

This file was deleted.

33 changes: 1 addition & 32 deletions webapp/src/components/AssetPage/ParcelDetail/ParcelDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,21 @@
import React from 'react'
import { Link } from 'react-router-dom'
import { NFTCategory } from '@dcl/schemas'
import { T } from 'decentraland-dapps/dist/modules/translation/utils'
import { isLand } from '../../../modules/nft/utils'
import { locations } from '../../../modules/routing/locations'
import { AssetImage } from '../../AssetImage'
import { Coordinate } from '../../Coordinate'
import { Network } from '../../Network'
import Price from '../../Price'
import { Actions } from '../Actions'
import BaseDetail from '../BaseDetail'
import { BidList } from '../BidList'
import { Description } from '../Description'
import Expiration from '../Expiration'
import { JumpIn } from '../JumpIn'
import { Owner } from '../Owner'
import { ProximityHighlights } from '../ProximityHighlights'
import { RentalHistory } from '../RentalHistory'
import { SaleRentActionBox } from '../SaleRentActionBox'
import { TransactionHistory } from '../TransactionHistory'
import { Props } from './ParcelDetail.types'
import styles from './ParcelDetail.module.css'

const ParcelDetail = ({ nft, order, rental }: Props) => {
const parcel = nft.data.parcel!
const { x, y } = parcel
const isPartOfEstate = nft.category === NFTCategory.PARCEL && parcel.estate

return (
<BaseDetail
Expand All @@ -48,28 +38,7 @@ const ParcelDetail = ({ nft, order, rental }: Props) => {
</>
}
actions={<SaleRentActionBox order={order} nft={nft} rental={rental} />}
box={
<>
{isPartOfEstate && (
<div className={styles.estateInfo}>
<T
id="asset_page.part_of_estate"
values={{
estate_name: (
<Link title={parcel.estate!.name} to={locations.nft(nft.owner, parcel.estate!.tokenId)}>
{parcel.estate!.name}
</Link>
)
}}
/>
</div>
)}
<Price asset={nft} />
<Network asset={nft} />
<Actions nft={nft} />
<Expiration />
</>
}
box={<></>}
below={
<>
<BidList nft={nft} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { T, t } from 'decentraland-dapps/dist/modules/translation/utils'
import { Button, Popup } from 'decentraland-ui'
import { builderUrl } from '../../../lib/environment'
import { formatWeiMANA } from '../../../lib/mana'
import { AssetType } from '../../../modules/asset/types'
import { isOwnedBy } from '../../../modules/asset/utils'
import { isPartOfEstate } from '../../../modules/nft/utils'
import {
Expand Down Expand Up @@ -230,22 +229,7 @@ const SaleRentActionBox = ({
</Button>
) : null}
<div className={styles.saleButtons}>
{order ? (
isCrossChainLandEnabled ? (
<BuyWithCryptoButton asset={nft} onClick={onBuyWithCrypto} />
) : (
<Button
as={Link}
to={locations.buy(AssetType.NFT, nft.contractAddress, nft.tokenId)}
disabled={!hasEnoughManaToBuy}
className={styles.buy}
primary
fluid
>
{t('asset_page.actions.buy')}
</Button>
)
) : null}
{order ? <BuyWithCryptoButton asset={nft} onClick={onBuyWithCrypto} /> : null}
{canBid ? (
<Popup
content={t('asset_page.sales_rent_action_box.parcel_belongs_to_estate_bid')}
Expand Down
44 changes: 0 additions & 44 deletions webapp/src/components/BuyPage/BuyPage.css

This file was deleted.

0 comments on commit d145fe8

Please sign in to comment.