Commit 1411a921 authored by Jordan Frankfurt's avatar Jordan Frankfurt Committed by GitHub

feat(sell-bag): closing link sell bag open/close state with sell mode activation (#5128)

* stash resolve

* toggling bag open/close also toggles sell mode
parent d016bdd8
...@@ -2,14 +2,33 @@ import { NavIcon } from 'components/NavBar/NavIcon' ...@@ -2,14 +2,33 @@ import { NavIcon } from 'components/NavBar/NavIcon'
import * as styles from 'components/NavBar/ShoppingBag.css' import * as styles from 'components/NavBar/ShoppingBag.css'
import { Box } from 'nft/components/Box' import { Box } from 'nft/components/Box'
import { BagIcon, HundredsOverflowIcon } from 'nft/components/icons' import { BagIcon, HundredsOverflowIcon } from 'nft/components/icons'
import { useBag } from 'nft/hooks' import { useBag, useSellAsset } from 'nft/hooks'
import { useEffect, useState } from 'react' import { useCallback, useEffect, useState } from 'react'
import shallow from 'zustand/shallow'
export const ShoppingBag = () => { export const ShoppingBag = () => {
const itemsInBag = useBag((state) => state.itemsInBag) const itemsInBag = useBag((state) => state.itemsInBag)
const [bagQuantity, setBagQuantity] = useState(0) const [bagQuantity, setBagQuantity] = useState(0)
const toggleBag = useBag((s) => s.toggleBag) const { bagExpanded, setBagExpanded } = useBag(
({ bagExpanded, setBagExpanded }) => ({ bagExpanded, setBagExpanded }),
shallow
)
const { isSellMode, resetSellAssets, setIsSellMode } = useSellAsset(
({ isSellMode, reset, setIsSellMode }) => ({
isSellMode,
resetSellAssets: reset,
setIsSellMode,
}),
shallow
)
const handleIconClick = useCallback(() => {
if (isSellMode && bagExpanded) {
resetSellAssets()
setIsSellMode(false)
}
setBagExpanded({ bagExpanded: !bagExpanded })
}, [bagExpanded, isSellMode, resetSellAssets, setBagExpanded, setIsSellMode])
useEffect(() => { useEffect(() => {
setBagQuantity(itemsInBag.length) setBagQuantity(itemsInBag.length)
...@@ -18,7 +37,7 @@ export const ShoppingBag = () => { ...@@ -18,7 +37,7 @@ export const ShoppingBag = () => {
const bagHasItems = bagQuantity > 0 const bagHasItems = bagQuantity > 0
return ( return (
<NavIcon onClick={toggleBag}> <NavIcon onClick={handleIconClick}>
<BagIcon viewBox="0 0 20 20" width={24} height={24} /> <BagIcon viewBox="0 0 20 20" width={24} height={24} />
{bagHasItems && ( {bagHasItems && (
<Box className={styles.bagQuantity}>{bagQuantity > 99 ? <HundredsOverflowIcon /> : bagQuantity}</Box> <Box className={styles.bagQuantity}>{bagQuantity > 99 ? <HundredsOverflowIcon /> : bagQuantity}</Box>
......
...@@ -30,6 +30,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' ...@@ -30,6 +30,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useQuery, useQueryClient } from 'react-query' import { useQuery, useQueryClient } from 'react-query'
import { useLocation } from 'react-router-dom' import { useLocation } from 'react-router-dom'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import shallow from 'zustand/shallow'
import * as styles from './Bag.css' import * as styles from './Bag.css'
import { BagContent } from './BagContent' import { BagContent } from './BagContent'
...@@ -67,24 +68,37 @@ const ScrollingIndicator = ({ top, show }: SeparatorProps) => ( ...@@ -67,24 +68,37 @@ const ScrollingIndicator = ({ top, show }: SeparatorProps) => (
const Bag = () => { const Bag = () => {
const { account, provider } = useWeb3React() const { account, provider } = useWeb3React()
const bagStatus = useBag((s) => s.bagStatus) const { resetSellAssets, sellAssets, setIsSellMode } = useSellAsset(
const setBagStatus = useBag((s) => s.setBagStatus) ({ isSellMode, reset, sellAssets, setIsSellMode }) => ({
const didOpenUnavailableAssets = useBag((s) => s.didOpenUnavailableAssets) isSellMode,
const setDidOpenUnavailableAssets = useBag((s) => s.setDidOpenUnavailableAssets) resetSellAssets: reset,
const bagIsLocked = useBag((s) => s.isLocked) sellAssets,
const setLocked = useBag((s) => s.setLocked) setIsSellMode,
const reset = useBag((s) => s.reset) }),
const resetSellAssets = useSellAsset((state) => state.reset) shallow
const sellAssets = useSellAsset((state) => state.sellAssets) )
const setProfilePageState = useProfilePageState((state) => state.setProfilePageState)
const profilePageState = useProfilePageState((state) => state.state) const { profilePageState, setProfilePageState } = useProfilePageState(
const uncheckedItemsInBag = useBag((s) => s.itemsInBag) ({ setProfilePageState, state }) => ({ profilePageState: state, setProfilePageState }),
const setItemsInBag = useBag((s) => s.setItemsInBag) shallow
const bagExpanded = useBag((s) => s.bagExpanded) )
const toggleBag = useBag((s) => s.toggleBag)
const setTotalEthPrice = useBag((s) => s.setTotalEthPrice) const {
const setTotalUsdPrice = useBag((s) => s.setTotalUsdPrice) bagStatus,
const setBagExpanded = useBag((state) => state.setBagExpanded) setBagStatus,
didOpenUnavailableAssets,
setDidOpenUnavailableAssets,
bagIsLocked,
setLocked,
reset,
setItemsInBag,
bagExpanded,
toggleBag,
setTotalEthPrice,
setTotalUsdPrice,
setBagExpanded,
} = useBag((state) => ({ ...state, bagIsLocked: state.isLocked, uncheckedItemsInBag: state.itemsInBag }), shallow)
const { uncheckedItemsInBag } = useBag(({ itemsInBag }) => ({ uncheckedItemsInBag: itemsInBag }))
const { pathname } = useLocation() const { pathname } = useLocation()
const isProfilePage = pathname.startsWith('/nfts/profile') const isProfilePage = pathname.startsWith('/nfts/profile')
...@@ -101,9 +115,7 @@ const Bag = () => { ...@@ -101,9 +115,7 @@ const Bag = () => {
const queryClient = useQueryClient() const queryClient = useQueryClient()
const itemsInBag = useMemo(() => { const itemsInBag = useMemo(() => recalculateBagUsingPooledAssets(uncheckedItemsInBag), [uncheckedItemsInBag])
return recalculateBagUsingPooledAssets(uncheckedItemsInBag)
}, [uncheckedItemsInBag])
const [isOpen, setModalIsOpen] = useState(false) const [isOpen, setModalIsOpen] = useState(false)
const [userCanScroll, setUserCanScroll] = useState(false) const [userCanScroll, setUserCanScroll] = useState(false)
...@@ -153,7 +165,10 @@ const Bag = () => { ...@@ -153,7 +165,10 @@ const Bag = () => {
} }
} }
const handleCloseBag = useCallback(() => setBagExpanded({ bagExpanded: false, manualClose: true }), [setBagExpanded]) const handleCloseBag = useCallback(() => {
setIsSellMode(false)
setBagExpanded({ bagExpanded: false, manualClose: true })
}, [setBagExpanded, setIsSellMode])
const fetchAssets = async () => { const fetchAssets = async () => {
const itemsToBuy = itemsInBag.filter((item) => item.status !== BagItemStatus.UNAVAILABLE).map((item) => item.asset) const itemsToBuy = itemsInBag.filter((item) => item.status !== BagItemStatus.UNAVAILABLE).map((item) => item.asset)
...@@ -258,6 +273,14 @@ const Bag = () => { ...@@ -258,6 +273,14 @@ const Bag = () => {
(!isProfilePage && !isBuyingAssets && bagStatus === BagStatus.ADDING_TO_BAG) || (isProfilePage && !isSellingAssets) (!isProfilePage && !isBuyingAssets && bagStatus === BagStatus.ADDING_TO_BAG) || (isProfilePage && !isSellingAssets)
) )
const eventProperties = useMemo(
() => ({
usd_value: totalUsdPrice,
...formatAssetEventProperties(itemsInBag.map((item) => item.asset)),
}),
[itemsInBag, totalUsdPrice]
)
return ( return (
<> <>
{bagExpanded && isNFTPage ? ( {bagExpanded && isNFTPage ? (
...@@ -283,10 +306,7 @@ const Bag = () => { ...@@ -283,10 +306,7 @@ const Bag = () => {
totalUsdPrice={totalUsdPrice} totalUsdPrice={totalUsdPrice}
bagStatus={bagStatus} bagStatus={bagStatus}
fetchAssets={fetchAssets} fetchAssets={fetchAssets}
eventProperties={{ eventProperties={eventProperties}
usd_value: totalUsdPrice,
...formatAssetEventProperties(itemsInBag.map((item) => item.asset)),
}}
/> />
)} )}
{isSellingAssets && isProfilePage && ( {isSellingAssets && isProfilePage && (
......
...@@ -9,6 +9,7 @@ import { CrossIcon, TagIcon } from 'nft/components/icons' ...@@ -9,6 +9,7 @@ import { CrossIcon, TagIcon } from 'nft/components/icons'
import { FilterSidebar } from 'nft/components/profile/view/FilterSidebar' import { FilterSidebar } from 'nft/components/profile/view/FilterSidebar'
import { buttonTextMedium, subhead } from 'nft/css/common.css' import { buttonTextMedium, subhead } from 'nft/css/common.css'
import { import {
useBag,
useFiltersExpanded, useFiltersExpanded,
useIsMobile, useIsMobile,
useProfilePageState, useProfilePageState,
...@@ -19,11 +20,12 @@ import { ...@@ -19,11 +20,12 @@ import {
import { ScreenBreakpointsPaddings } from 'nft/pages/collection/index.css' import { ScreenBreakpointsPaddings } from 'nft/pages/collection/index.css'
import { fetchWalletAssets, OSCollectionsFetcher } from 'nft/queries' import { fetchWalletAssets, OSCollectionsFetcher } from 'nft/queries'
import { ProfilePageStateType, WalletAsset, WalletCollection } from 'nft/types' import { ProfilePageStateType, WalletAsset, WalletCollection } from 'nft/types'
import { Dispatch, SetStateAction, useEffect, useMemo, useReducer, useState } from 'react' import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useState } from 'react'
import InfiniteScroll from 'react-infinite-scroll-component' import InfiniteScroll from 'react-infinite-scroll-component'
import { useInfiniteQuery, useQuery } from 'react-query' import { useInfiniteQuery, useQuery } from 'react-query'
import { useSpring } from 'react-spring' import { useSpring } from 'react-spring'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import shallow from 'zustand/shallow'
import { EmptyWalletContent } from './EmptyWalletContent' import { EmptyWalletContent } from './EmptyWalletContent'
import { ProfileAccountDetails } from './ProfileAccountDetails' import { ProfileAccountDetails } from './ProfileAccountDetails'
...@@ -69,19 +71,27 @@ export const ProfilePage = () => { ...@@ -69,19 +71,27 @@ export const ProfilePage = () => {
const walletCollections = useWalletCollections((state) => state.walletCollections) const walletCollections = useWalletCollections((state) => state.walletCollections)
const setWalletCollections = useWalletCollections((state) => state.setWalletCollections) const setWalletCollections = useWalletCollections((state) => state.setWalletCollections)
const listFilter = useWalletCollections((state) => state.listFilter) const listFilter = useWalletCollections((state) => state.listFilter)
const { isSellMode, resetSellAssets, setIsSellMode } = useSellAsset(
({ isSellMode, reset, setIsSellMode }) => ({
isSellMode,
resetSellAssets: reset,
setIsSellMode,
}),
shallow
)
const sellAssets = useSellAsset((state) => state.sellAssets) const sellAssets = useSellAsset((state) => state.sellAssets)
const reset = useSellAsset((state) => state.reset) const { setBagExpanded } = useBag(({ setBagExpanded }) => ({ setBagExpanded }), shallow)
const resetSellAssets = useSellAsset((state) => state.reset)
const setSellPageState = useProfilePageState((state) => state.setProfilePageState) const setSellPageState = useProfilePageState((state) => state.setProfilePageState)
const [isFiltersExpanded, setFiltersExpanded] = useFiltersExpanded() const [isFiltersExpanded, setFiltersExpanded] = useFiltersExpanded()
const isMobile = useIsMobile() const isMobile = useIsMobile()
const isNftGraphQl = useNftGraphQlFlag() === NftGraphQlVariant.Enabled const isNftGraphQl = useNftGraphQlFlag() === NftGraphQlVariant.Enabled
const [isSellMode, toggleSellMode] = useReducer((s) => !s, false)
const handleSellModeClick = () => { const handleSellModeClick = useCallback(() => {
resetSellAssets() resetSellAssets()
toggleSellMode() setIsSellMode(!isSellMode)
} setBagExpanded({ bagExpanded: !isSellMode })
}, [isSellMode, resetSellAssets, setBagExpanded, setIsSellMode])
const { data: ownerCollections, isLoading: collectionsAreLoading } = useQuery( const { data: ownerCollections, isLoading: collectionsAreLoading } = useQuery(
['ownerCollections', address], ['ownerCollections', address],
...@@ -234,7 +244,7 @@ export const ProfilePage = () => { ...@@ -234,7 +244,7 @@ export const ProfilePage = () => {
color="genieBlue" color="genieBlue"
marginRight="20" marginRight="20"
marginLeft="auto" marginLeft="auto"
onClick={reset} onClick={resetSellAssets}
lineHeight="16" lineHeight="16"
> >
Clear Clear
......
...@@ -4,6 +4,7 @@ import { devtools } from 'zustand/middleware' ...@@ -4,6 +4,7 @@ import { devtools } from 'zustand/middleware'
import { ListingMarket, ListingWarning, WalletAsset } from '../types' import { ListingMarket, ListingWarning, WalletAsset } from '../types'
interface SellAssetState { interface SellAssetState {
isSellMode: boolean
sellAssets: WalletAsset[] sellAssets: WalletAsset[]
selectSellAsset: (asset: WalletAsset) => void selectSellAsset: (asset: WalletAsset) => void
removeSellAsset: (asset: WalletAsset) => void removeSellAsset: (asset: WalletAsset) => void
...@@ -11,6 +12,7 @@ interface SellAssetState { ...@@ -11,6 +12,7 @@ interface SellAssetState {
setGlobalExpiration: (expirationTime: number) => void setGlobalExpiration: (expirationTime: number) => void
setAssetListPrice: (asset: WalletAsset, price?: number, marketplace?: ListingMarket) => void setAssetListPrice: (asset: WalletAsset, price?: number, marketplace?: ListingMarket) => void
setGlobalMarketplaces: (marketplaces: ListingMarket[]) => void setGlobalMarketplaces: (marketplaces: ListingMarket[]) => void
setIsSellMode: (b: boolean) => void
removeAssetMarketplace: (asset: WalletAsset, marketplace: ListingMarket) => void removeAssetMarketplace: (asset: WalletAsset, marketplace: ListingMarket) => void
addMarketplaceWarning: (asset: WalletAsset, warning: ListingWarning) => void addMarketplaceWarning: (asset: WalletAsset, warning: ListingWarning) => void
removeMarketplaceWarning: (asset: WalletAsset, warning: ListingWarning, setGlobalOverride?: boolean) => void removeMarketplaceWarning: (asset: WalletAsset, warning: ListingWarning, setGlobalOverride?: boolean) => void
...@@ -20,6 +22,7 @@ interface SellAssetState { ...@@ -20,6 +22,7 @@ interface SellAssetState {
export const useSellAsset = create<SellAssetState>()( export const useSellAsset = create<SellAssetState>()(
devtools( devtools(
(set) => ({ (set) => ({
isSellMode: false,
sellAssets: [], sellAssets: [],
selectSellAsset: (asset) => selectSellAsset: (asset) =>
set(({ sellAssets }) => { set(({ sellAssets }) => {
...@@ -95,6 +98,7 @@ export const useSellAsset = create<SellAssetState>()( ...@@ -95,6 +98,7 @@ export const useSellAsset = create<SellAssetState>()(
return { sellAssets: assetsCopy } return { sellAssets: assetsCopy }
}) })
}, },
setIsSellMode: (isSellMode) => set(() => ({ isSellMode })),
removeAssetMarketplace: (asset, marketplace) => { removeAssetMarketplace: (asset, marketplace) => {
set(({ sellAssets }) => { set(({ sellAssets }) => {
const assetsCopy = [...sellAssets] const assetsCopy = [...sellAssets]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment