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: add buy with crypto button to ENS detail page #2198

Merged
merged 9 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
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 && (
Copy link
Contributor

Choose a reason for hiding this comment

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

If we're removing this, we should remove the estateInfo css as well, would you mind removing it?

<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.

Loading
Loading