fix(nft): empty bag state render (#4947)

* fix empty bag state render

* add tests
This commit is contained in:
Jordan Frankfurt 2022-10-21 12:38:30 -05:00 committed by GitHub
parent a97a6b7fa8
commit 0987a311cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 90 additions and 60 deletions

@ -6,11 +6,9 @@ import { BagFooter } from 'nft/components/bag/BagFooter'
import ListingModal from 'nft/components/bag/profile/ListingModal'
import { Box } from 'nft/components/Box'
import { Portal } from 'nft/components/common/Portal'
import { Center, Column } from 'nft/components/Flex'
import { LargeBagIcon, LargeTagIcon } from 'nft/components/icons'
import { Column } from 'nft/components/Flex'
import { Overlay } from 'nft/components/modals/Overlay'
import { buttonTextMedium, commonButtonStyles, subhead } from 'nft/css/common.css'
import { themeVars } from 'nft/css/sprinkles.css'
import { buttonTextMedium, commonButtonStyles } from 'nft/css/common.css'
import {
useBag,
useIsMobile,
@ -34,39 +32,9 @@ import { useLocation } from 'react-router-dom'
import * as styles from './Bag.css'
import { BagContent } from './BagContent'
import { BagHeader } from './BagHeader'
import EmptyState from './EmptyContent'
import { ProfileBagContent } from './profile/ProfileBagContent'
const EmptyState = () => {
const { pathname } = useLocation()
const isProfilePage = pathname.startsWith('/profile')
return (
<Center height="full">
<Column gap={isProfilePage ? '16' : '12'}>
<Center>
{isProfilePage ? (
<LargeTagIcon color={themeVars.colors.textTertiary} />
) : (
<LargeBagIcon color={themeVars.colors.textTertiary} />
)}
</Center>
{isProfilePage ? (
<span className={subhead}>No NFTs Selected</span>
) : (
<Column gap="16">
<Center className={subhead} style={{ lineHeight: '24px' }}>
Your bag is empty
</Center>
<Center fontSize="12" fontWeight="normal" color="textSecondary" style={{ lineHeight: '16px' }}>
Selected NFTs will appear here
</Center>
</Column>
)}
</Column>
</Center>
)
}
interface SeparatorProps {
top?: boolean
show?: boolean
@ -282,6 +250,13 @@ const Bag = () => {
setScrollProgress(scrollTop ? ((scrollTop + containerHeight) / scrollHeight) * 100 : 0)
}
const isBuyingAssets = itemsInBag.length > 0
const isSellingAssets = sellAssets.length > 0
const shouldRenderEmptyState = Boolean(
(!isProfilePage && !isBuyingAssets && bagStatus === BagStatus.ADDING_TO_BAG) || (isProfilePage && !isSellingAssets)
)
return (
<>
{bagExpanded && shouldShowBag ? (
@ -295,8 +270,7 @@ const Bag = () => {
resetFlow={isProfilePage ? resetSellAssets : reset}
isProfilePage={isProfilePage}
/>
{(!isProfilePage && itemsInBag.length === 0 && bagStatus === BagStatus.ADDING_TO_BAG) ||
(isProfilePage && sellAssets.length === 0 && <EmptyState />)}
{shouldRenderEmptyState && <EmptyState />}
<ScrollingIndicator top show={userCanScroll && scrollProgress > 0} />
<Column ref={scrollRef} className={styles.assetsContainer} onScroll={scrollHandler} gap="12">
{isProfilePage ? <ProfileBagContent /> : <BagContent />}
@ -314,7 +288,7 @@ const Bag = () => {
assetsAreInReview={itemsInBag.some((item) => item.status === BagItemStatus.REVIEWING_PRICE_CHANGE)}
/>
)}
{sellAssets.length !== 0 && isProfilePage && (
{isSellingAssets && isProfilePage && (
<Box
marginTop="32"
marginX="28"

@ -1,9 +1,9 @@
import { style } from '@vanilla-extract/css'
import { subhead } from 'nft/css/common.css'
import { headlineSmall } from 'nft/css/common.css'
import { sprinkles, vars } from 'nft/css/sprinkles.css'
export const header = style([
subhead,
headlineSmall,
sprinkles({
color: 'textPrimary',
justifyContent: 'space-between',

@ -0,0 +1,36 @@
import { Center, Column } from 'nft/components/Flex'
import { LargeBagIcon, LargeTagIcon } from 'nft/components/icons'
import { subhead } from 'nft/css/common.css'
import { themeVars } from 'nft/css/sprinkles.css'
import { useLocation } from 'react-router-dom'
const EmptyState = () => {
const { pathname } = useLocation()
const isProfilePage = pathname.startsWith('/profile')
return (
<Column gap={isProfilePage ? '16' : '12'} marginTop="36">
<Center>
{isProfilePage ? (
<LargeTagIcon color={themeVars.colors.textTertiary} />
) : (
<LargeBagIcon color={themeVars.colors.textTertiary} />
)}
</Center>
{isProfilePage ? (
<span className={subhead}>No NFTs Selected</span>
) : (
<Column gap="16">
<Center className={subhead} style={{ lineHeight: '24px' }}>
Your bag is empty
</Center>
<Center fontSize="12" fontWeight="normal" color="textSecondary" style={{ lineHeight: '16px' }}>
Selected NFTs will appear here
</Center>
</Column>
)}
</Column>
)
}
export default EmptyState

@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Bag.tsx matches base snapshot 1`] = `<DocumentFragment />`;

@ -0,0 +1,21 @@
import { render } from 'test-utils'
import Bag from './Bag'
jest.mock('@web3-react/core', () => {
const web3React = jest.requireActual('@web3-react/core')
return {
useWeb3React: () => ({
account: '0x52270d8234b864dcAC9947f510CE9275A8a116Db',
isActive: true,
}),
...web3React,
}
})
describe('Bag.tsx', () => {
it('matches base snapshot', () => {
const { asFragment } = render(<Bag />)
expect(asFragment()).toMatchSnapshot()
})
})

@ -1,5 +1,4 @@
import * as useV3Positions from 'hooks/useV3Positions'
import { BrowserRouter as Router } from 'react-router-dom'
import { render, screen } from 'test-utils'
import CTACards from './CTACards'
@ -20,11 +19,7 @@ describe('CTAcard links', () => {
return { loading: false, positions: undefined }
})
render(
<Router>
<CTACards />
</Router>
)
render(<CTACards />)
expect(screen.getByTestId('cta-infolink')).toHaveAttribute('href', 'https://info.uniswap.org/#/pools')
})
})

@ -1,6 +1,5 @@
import * as chains from 'constants/chains'
import * as useV3Positions from 'hooks/useV3Positions'
import { BrowserRouter as Router } from 'react-router-dom'
import { render, screen } from 'test-utils'
import Pool from '.'
@ -22,11 +21,7 @@ describe('networks', () => {
return { loading: false, positions: undefined }
})
render(
<Router>
<Pool />
</Router>
)
render(<Pool />)
expect(screen.getByText('Your connected network is unsupported.')).toBeInTheDocument()
})
@ -36,11 +31,7 @@ describe('networks', () => {
return { loading: false, positions: undefined }
})
render(
<Router>
<Pool />
</Router>
)
render(<Pool />)
expect(screen.getByText('Your active V3 liquidity positions will appear here.')).toBeInTheDocument()
})
})

@ -3,9 +3,12 @@ import { I18nProvider } from '@lingui/react'
import { render } from '@testing-library/react'
import Web3Provider from 'components/Web3Provider'
import { DEFAULT_LOCALE } from 'constants/locales'
import { BlockNumberProvider } from 'lib/hooks/useBlockNumber'
import { en } from 'make-plural/plurals'
import { ReactElement, ReactNode } from 'react'
import { QueryClient, QueryClientProvider } from 'react-query'
import { Provider } from 'react-redux'
import { HashRouter } from 'react-router-dom'
import store from 'state'
import ThemeProvider from 'theme'
@ -20,14 +23,21 @@ i18n.loadLocaleData({
i18n.activate(DEFAULT_LOCALE)
const MockedI18nProvider = ({ children }: any) => <I18nProvider i18n={i18n}>{children}</I18nProvider>
const queryClient = new QueryClient()
const WithProviders = ({ children }: { children?: ReactNode }) => {
return (
<MockedI18nProvider>
<Provider store={store}>
<Web3Provider>
<ThemeProvider>{children}</ThemeProvider>
</Web3Provider>
<QueryClientProvider client={queryClient}>
<HashRouter>
<Web3Provider>
<BlockNumberProvider>
<ThemeProvider>{children}</ThemeProvider>
</BlockNumberProvider>
</Web3Provider>
</HashRouter>
</QueryClientProvider>
</Provider>
</MockedI18nProvider>
)