import { memo , useCallback , useMemo , useState } from 'react' ; import styled from 'styled-components' ; import { BodyMedium } from 'components/core/Text/Text' ; import Spacer from 'components/core/Spacer/Spacer' ; import { FOOTER_HEIGHT } from 'flows/shared/components/WizardFooter/WizardFooter' ; import TextButton from 'components/core/Button/TextButton' ; import { useSidebarNftsState , useCollectionEditorActions , } from 'contexts/collectionEditor/CollectionEditorContext' ; import { useRefreshOpenseaSync } from 'hooks/api/nfts/useOpenseaSync' ; import { EditModeNft } from '../types' ; import { convertObjectToArray } from '../convertObjectToArray' ; import SidebarNftIcon from './SidebarNftIcon' ; import SearchBar from './SearchBar' ; import { useMutateAllNftsCache } from 'hooks/api/nfts/useAllNfts' ; function Sidebar ( ) { const sidebarNfts = useSidebarNftsState ( ) ; const { setNftsIsSelected , stageNfts , unstageNfts } = useCollectionEditorActions ( ) ; const refreshOpenseaSync = useRefreshOpenseaSync ( ) ; const mutateAllNftsCache = useMutateAllNftsCache ( ) ; const [ debouncedSearchQuery , setDebouncedSearchQuery ] = useState ( '' ) ; const [ searchResults , setSearchResults ] = useState < string [ ] > ( [ ] ) ; const sidebarNftsAsArray = useMemo ( ( ) => convertObjectToArray ( sidebarNfts ) . reverse ( ) , [ sidebarNfts ] ) ; const nftsToDisplayInSidebar = useMemo ( ( ) => { if ( debouncedSearchQuery ) { const searchResultNfts = [ ] ; for ( const resultId of searchResults ) { if ( sidebarNfts [ resultId ] ) { searchResultNfts . push ( sidebarNfts [ resultId ] ) ; } } return searchResultNfts ; } return sidebarNftsAsArray ; } , [ debouncedSearchQuery , searchResults , sidebarNfts , sidebarNftsAsArray ] ) ; const isAllNftsSelected = useMemo ( ( ) => ! nftsToDisplayInSidebar . some ( ( nft ) => ! nft . isSelected ) , [ nftsToDisplayInSidebar ] ) ; const handleSelectAllClick = useCallback ( ( ) => { const nftsToStage = nftsToDisplayInSidebar . filter ( ( nft ) => ! nft . isSelected ) ; if ( nftsToStage . length === 0 ) { return ; } stageNfts ( nftsToStage ) ; setNftsIsSelected ( nftsToStage , true ) ; } , [ nftsToDisplayInSidebar , stageNfts , setNftsIsSelected ] ) ; const handleDeselectAllClick = useCallback ( ( ) => { const nftIdsToUnstage = nftsToDisplayInSidebar . map ( ( nft ) => nft . id ) ; if ( nftIdsToUnstage . length === 0 ) { return ; } unstageNfts ( nftIdsToUnstage ) ; setNftsIsSelected ( nftsToDisplayInSidebar , false ) ; } , [ nftsToDisplayInSidebar , setNftsIsSelected , unstageNfts ] ) ; const [ isRefreshing , setIsRefreshing ] = useState ( false ) ; const handleRefreshWalletClick = useCallback ( async ( ) => { setIsRefreshing ( true ) ; try { await refreshOpenseaSync ( ) ; void mutateAllNftsCache ( ) ; } catch { } setIsRefreshing ( false ) ; } , [ mutateAllNftsCache , refreshOpenseaSync ] ) ; return ( < StyledSidebar > < Header > < BodyMedium > Your NFTs < /BodyMedium> < TextButton text = { isRefreshing ? 'Refreshing...' : 'Refresh Wallet' } onClick = { handleRefreshWalletClick } disabled = { isRefreshing } / > < /Header> < Spacer height = { 16 } / > < SearchBar setSearchResults = { setSearchResults } setDebouncedSearchQuery = { setDebouncedSearchQuery } sidebarNfts = { sidebarNftsAsArray } / > < Spacer height = { 24 } /> < StyledSelectButtonWrapper > { isAllNftsSelected ? ( < TextButton text = { `Deselect All (${ nftsToDisplayInSidebar . length })` } onClick = { handleDeselectAllClick } / > ) : ( < TextButton text = { `Select All (${ nftsToDisplayInSidebar . length })` } onClick = { handleSelectAllClick } / > ) } < /StyledSelectButtonWrapper> < Spacer height = { 8 } / > < Selection > { nftsToDisplayInSidebar . map ( ( editModeNft ) => ( < SidebarNftIcon key = { editModeNft . nft . id } editModeNft = { editModeNft } / > ) ) } < /Selection> < Spacer height = { 12 } / > < /StyledSidebar>); } const StyledSidebar = styled . div `
  width: 100%;
  height: calc(100vh - ${ FOOTER_HEIGHT }px);

  background: #f7f7f7;

  padding: 32px;

  overflow: scroll;

  &::-webkit-scrollbar {
    display: none;
  }
` ; const Header = styled . div `
  display: flex;
  justify-content: space-between;
  align-items: baseline;
` ; const StyledSelectButtonWrapper = styled . div `
  display: flex;
  justify-content: flex-end;
` ; const Selection = styled . div `
  display: flex;
  flex-wrap: wrap;

  // Safari doesn't support this yet
  // column-gap: 12px;
  // row-gap: 12px;

  // Temporary solution until Safari support
  width: calc(100% + 12px);
  margin-left: -6px;
` ; export default memo ( Sidebar ) ;