feat: Add Select Page Modal (#4643)
* add select nfts shopping bag modal * Add shopping bag to top lovel modal wrapper * addressing comments * rename to listingTag Co-authored-by: Charles Bachmeier <charlie@genie.xyz>
This commit is contained in:
parent
49c5cbbf3b
commit
8c947a0e0d
@ -2,9 +2,12 @@ import { useWeb3React } from '@web3-react/core'
|
||||
import AddressClaimModal from 'components/claim/AddressClaimModal'
|
||||
import ConnectedAccountBlocked from 'components/ConnectedAccountBlocked'
|
||||
import useAccountRiskCheck from 'hooks/useAccountRiskCheck'
|
||||
import { lazy } from 'react'
|
||||
import { useModalIsOpen, useToggleModal } from 'state/application/hooks'
|
||||
import { ApplicationModal } from 'state/application/reducer'
|
||||
|
||||
const Cart = lazy(() => import('nft/components/sell/modal/ListingTag'))
|
||||
|
||||
export default function TopLevelModals() {
|
||||
const addressClaimOpen = useModalIsOpen(ApplicationModal.ADDRESS_CLAIM)
|
||||
const addressClaimToggle = useToggleModal(ApplicationModal.ADDRESS_CLAIM)
|
||||
@ -18,6 +21,7 @@ export default function TopLevelModals() {
|
||||
<>
|
||||
<AddressClaimModal isOpen={addressClaimOpen} onDismiss={addressClaimToggle} />
|
||||
<ConnectedAccountBlocked account={account} isOpen={open} />
|
||||
<Cart />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
52
src/nft/components/sell/modal/ListingTag.css.ts
Normal file
52
src/nft/components/sell/modal/ListingTag.css.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { style } from '@vanilla-extract/css'
|
||||
import { breakpoints, sprinkles } from 'nft/css/sprinkles.css'
|
||||
|
||||
export const tagContainer = style([
|
||||
sprinkles({
|
||||
borderRadius: '20',
|
||||
borderWidth: '1px',
|
||||
borderStyle: 'solid',
|
||||
borderColor: 'medGray',
|
||||
}),
|
||||
{
|
||||
'@media': {
|
||||
[`screen and (max-width: ${breakpoints.md}px)`]: {
|
||||
borderRadius: '0',
|
||||
},
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
export const tagAssets = style([
|
||||
sprinkles({
|
||||
maxHeight: 'inherit',
|
||||
}),
|
||||
{
|
||||
'@media': {
|
||||
[`screen and (min-width: ${breakpoints.md}px)`]: {
|
||||
maxHeight: '55vh',
|
||||
},
|
||||
},
|
||||
'::-webkit-scrollbar': { display: 'none' },
|
||||
scrollbarWidth: 'none',
|
||||
},
|
||||
])
|
||||
|
||||
export const closeIcon = style({
|
||||
transform: 'rotate(90deg)',
|
||||
float: 'right',
|
||||
paddingTop: '1px',
|
||||
})
|
||||
|
||||
export const orderButton = style([
|
||||
sprinkles({
|
||||
width: 'full',
|
||||
paddingY: '12',
|
||||
paddingX: '0',
|
||||
}),
|
||||
{
|
||||
':hover': {
|
||||
boxShadow: 'none',
|
||||
},
|
||||
},
|
||||
])
|
120
src/nft/components/sell/modal/ListingTag.tsx
Normal file
120
src/nft/components/sell/modal/ListingTag.tsx
Normal file
@ -0,0 +1,120 @@
|
||||
import Loader from 'components/Loader'
|
||||
import { Box } from 'nft/components/Box'
|
||||
import { Column } from 'nft/components/Flex'
|
||||
import { CloseDropDownIcon } from 'nft/components/icons'
|
||||
import { bodySmall, buttonMedium, headlineSmall } from 'nft/css/common.css'
|
||||
import { useBag, useIsMobile, useSellAsset, useSellPageState } from 'nft/hooks'
|
||||
import { SellPageStateType } from 'nft/types'
|
||||
import { lazy, Suspense } from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
|
||||
import * as styles from './ListingTag.css'
|
||||
|
||||
const CartSellAssetRow = lazy(() => import('./TagAssetRow'))
|
||||
|
||||
const Cart = () => {
|
||||
const { pathname } = useLocation()
|
||||
const isNFTSellPage = pathname.startsWith('/nfts/sell')
|
||||
const sellAssets = useSellAsset((state) => state.sellAssets)
|
||||
const setSellPageState = useSellPageState((state) => state.setSellPageState)
|
||||
const sellPageState = useSellPageState((state) => state.state)
|
||||
const toggleCart = useBag((state) => state.toggleBag)
|
||||
const isMobile = useIsMobile()
|
||||
const bagExpanded = useBag((s) => s.bagExpanded)
|
||||
|
||||
return (
|
||||
<Box
|
||||
zIndex={{ sm: '3', md: '2' }}
|
||||
width={{ sm: 'full', md: 'auto' }}
|
||||
height={{ sm: 'full', md: 'auto' }}
|
||||
position="fixed"
|
||||
left={{ sm: '0', md: 'unset' }}
|
||||
right={{ sm: 'unset', md: '0' }}
|
||||
top={{ sm: '0', md: 'unset' }}
|
||||
display={bagExpanded && isNFTSellPage ? 'flex' : 'none'}
|
||||
>
|
||||
<Suspense fallback={<Loader />}>
|
||||
<Column
|
||||
marginTop={{ sm: '0', md: '4' }}
|
||||
marginRight={{ sm: '0', md: '20' }}
|
||||
className={styles.tagContainer}
|
||||
width={{ sm: 'full', md: '288' }}
|
||||
height={{ sm: 'full', md: 'auto' }}
|
||||
backgroundColor="white"
|
||||
marginLeft="0"
|
||||
justifyContent="flex-start"
|
||||
>
|
||||
{sellPageState === SellPageStateType.LISTING ? null : (
|
||||
<>
|
||||
<BagHeader bagQuantity={sellAssets.length} />
|
||||
<Column
|
||||
overflowX="hidden"
|
||||
overflowY="auto"
|
||||
position="relative"
|
||||
paddingTop="6"
|
||||
paddingBottom="6"
|
||||
height="full"
|
||||
className={styles.tagAssets}
|
||||
>
|
||||
{sellAssets.length
|
||||
? sellAssets.map((asset, index) => <CartSellAssetRow asset={asset} key={index} />)
|
||||
: null}
|
||||
</Column>
|
||||
<Box padding="12">
|
||||
<Box
|
||||
as="button"
|
||||
className={`${buttonMedium} ${styles.orderButton}`}
|
||||
disabled={sellAssets.length === 0}
|
||||
onClick={() => {
|
||||
isMobile && toggleCart()
|
||||
setSellPageState(SellPageStateType.LISTING)
|
||||
}}
|
||||
>
|
||||
Continue
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</Column>
|
||||
</Suspense>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const BagHeader = ({ bagQuantity }: { bagQuantity: number }) => {
|
||||
const toggleCart = useBag((state) => state.toggleBag)
|
||||
const resetSellAssets = useSellAsset((state) => state.reset)
|
||||
const isMobile = useIsMobile()
|
||||
return (
|
||||
<Box position="relative" zIndex="2" paddingTop="20" paddingLeft="12" paddingRight="12">
|
||||
{isMobile ? (
|
||||
<Box
|
||||
as="button"
|
||||
border="none"
|
||||
color="darkGray"
|
||||
background="black"
|
||||
className={styles.closeIcon}
|
||||
onClick={toggleCart}
|
||||
>
|
||||
<CloseDropDownIcon />
|
||||
</Box>
|
||||
) : null}
|
||||
<Box className={headlineSmall} paddingTop="0" paddingBottom="8" paddingX="0" margin="0">
|
||||
{'Selected items'}
|
||||
</Box>
|
||||
{bagQuantity > 0 ? (
|
||||
<Box className={bodySmall} paddingTop="0" paddingBottom="8" paddingX="0" marginY="0" marginX="auto">
|
||||
{bagQuantity} {bagQuantity === 1 ? 'NFT' : 'NFTs'}
|
||||
<Box as="span" position="relative" paddingRight="2" paddingLeft="4" style={{ fontSize: '8px', top: '-2px' }}>
|
||||
•
|
||||
</Box>
|
||||
<Box as="span" color="blue400" onClick={resetSellAssets} cursor="pointer" paddingLeft="2">
|
||||
Remove all
|
||||
</Box>
|
||||
</Box>
|
||||
) : null}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default Cart
|
82
src/nft/components/sell/modal/TagAssetRow.css.ts
Normal file
82
src/nft/components/sell/modal/TagAssetRow.css.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import { style } from '@vanilla-extract/css'
|
||||
import { sprinkles } from 'nft/css/sprinkles.css'
|
||||
|
||||
export const tagAssetImage = style([
|
||||
sprinkles({
|
||||
borderRadius: '8',
|
||||
height: '52',
|
||||
width: '52',
|
||||
marginRight: '12',
|
||||
marginLeft: '8',
|
||||
cursor: 'pointer',
|
||||
}),
|
||||
{
|
||||
boxSizing: 'border-box',
|
||||
},
|
||||
])
|
||||
|
||||
export const tagAssetName = style([
|
||||
sprinkles({
|
||||
fontWeight: 'medium',
|
||||
overflow: 'hidden',
|
||||
marginRight: 'auto',
|
||||
marginTop: '4',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
}),
|
||||
])
|
||||
|
||||
export const tagAssetCollectionName = style([
|
||||
sprinkles({
|
||||
fontWeight: 'normal',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
}),
|
||||
{
|
||||
maxWidth: '65%',
|
||||
},
|
||||
])
|
||||
|
||||
export const tagAssetRowBottom = style([
|
||||
sprinkles({
|
||||
width: 'full',
|
||||
display: 'flex',
|
||||
flexWrap: 'nowrap',
|
||||
marginRight: '4',
|
||||
}),
|
||||
{
|
||||
marginTop: '-10px',
|
||||
},
|
||||
])
|
||||
|
||||
export const removeAsset = style([
|
||||
sprinkles({
|
||||
position: 'absolute',
|
||||
cursor: 'pointer',
|
||||
}),
|
||||
{
|
||||
bottom: '-12px',
|
||||
left: '22px',
|
||||
},
|
||||
])
|
||||
|
||||
export const removeIcon = style([
|
||||
sprinkles({
|
||||
width: '32',
|
||||
}),
|
||||
])
|
||||
|
||||
export const tagAssetInfo = style([
|
||||
sprinkles({
|
||||
fontSize: '14',
|
||||
color: 'blackBlue',
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
width: 'full',
|
||||
overflowX: 'hidden',
|
||||
}),
|
||||
{
|
||||
lineHeight: '17px',
|
||||
},
|
||||
])
|
43
src/nft/components/sell/modal/TagAssetRow.tsx
Normal file
43
src/nft/components/sell/modal/TagAssetRow.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import { Box } from 'nft/components/Box'
|
||||
import { bodySmall, subheadSmall } from 'nft/css/common.css'
|
||||
import { useSellAsset } from 'nft/hooks'
|
||||
import { WalletAsset } from 'nft/types'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
import * as styles from './TagAssetRow.css'
|
||||
|
||||
const CartSellAssetRow = ({ asset }: { asset: WalletAsset }) => {
|
||||
const removeAsset = useSellAsset((state) => state.removeSellAsset)
|
||||
const [hovered, setHovered] = useState(false)
|
||||
const handleHover = () => setHovered(!hovered)
|
||||
const assetRowRef = useRef<HTMLDivElement>()
|
||||
|
||||
useEffect(() => {
|
||||
if (hovered && assetRowRef.current && assetRowRef.current.matches(':hover') === false) setHovered(false)
|
||||
}, [hovered])
|
||||
|
||||
return (
|
||||
<Box display="flex" padding="4" marginBottom="4" borderRadius="8" position="relative">
|
||||
<Box
|
||||
onMouseEnter={handleHover}
|
||||
onMouseLeave={handleHover}
|
||||
onClick={() => {
|
||||
removeAsset(asset)
|
||||
}}
|
||||
>
|
||||
<Box visibility={hovered ? 'visible' : 'hidden'} className={styles.removeAsset}>
|
||||
<img className={styles.removeIcon} src={'/nft/svgs/minusCircle.svg'} alt="Remove item" />
|
||||
</Box>
|
||||
<img className={styles.tagAssetImage} src={asset.image_url} alt={asset.name} />
|
||||
</Box>
|
||||
<Box className={styles.tagAssetInfo}>
|
||||
<Box className={`${subheadSmall} ${styles.tagAssetName}`}>{asset.name || `#${asset.tokenId}`}</Box>
|
||||
<Box className={styles.tagAssetRowBottom}>
|
||||
<Box className={`${bodySmall} ${styles.tagAssetCollectionName}`}>{asset.collection?.name}</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default CartSellAssetRow
|
Loading…
Reference in New Issue
Block a user