Skip to content

Commit

Permalink
split watchlist select
Browse files Browse the repository at this point in the history
c
  • Loading branch information
nguyenhoaidanh committed Sep 29, 2023
1 parent 6cc6bd6 commit 8cd1dbd
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 103 deletions.
50 changes: 50 additions & 0 deletions src/pages/TrueSightV2/components/TokenFilter/WatchlistSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { t } from '@lingui/macro'
import { useMemo, useState } from 'react'
import { CSSProperties } from 'styled-components'

import { SelectOption } from 'components/Select'
import { ActiveSelectItem, StyledSelect } from 'pages/TrueSightV2/components/TokenFilter'
import { ManageListModal } from 'pages/TrueSightV2/components/WatchlistButton'
import { useGetWatchlistInformationQuery } from 'pages/TrueSightV2/hooks/useKyberAIData'

const WatchlistSelect = ({
menuStyle,
onChange,
value,
}: {
menuStyle: CSSProperties
onChange: (key: string) => void
value: string
}) => {
const [isOpen, setIsOpen] = useState(false)
const { data: dataWatchList } = useGetWatchlistInformationQuery()

const watchlistesOptions = useMemo(() => {
let total = 0
const opts: SelectOption[] =
dataWatchList?.watchlists?.map(e => {
total += e.assetNumber
return { value: e.id + '', label: `${e.name} (${e.assetNumber})` }
}) || []

opts.unshift({ label: t`All Tokens (${total})`, value: '' })
opts.push({ label: t`Manage Lists`, onSelect: () => setIsOpen(true) }) // todo danh: update like desgin

return opts
}, [dataWatchList])

return (
<>
<StyledSelect
value={value}
activeRender={item => <ActiveSelectItem name={t`Watchlist`} label={item?.label} />}
options={watchlistesOptions}
onChange={onChange}
optionStyle={{ fontSize: '14px' }}
menuStyle={menuStyle}
/>
<ManageListModal isOpen={isOpen} setIsOpen={setIsOpen} />
</>
)
}
export default WatchlistSelect
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { ChainId } from '@kyberswap/ks-sdk-core'
import { t } from '@lingui/macro'
import { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import Skeleton from 'react-loading-skeleton'
import { useMedia } from 'react-use'
import { Text } from 'rebass'
import styled, { css } from 'styled-components'
import styled, { CSSProperties, css } from 'styled-components'

import { ButtonGray } from 'components/Button'
import Column from 'components/Column'
Expand All @@ -14,10 +13,9 @@ import useShowLoadingAtLeastTime from 'hooks/useShowLoadingAtLeastTime'
import useTheme from 'hooks/useTheme'
import MultipleChainSelect from 'pages/MyEarnings/MultipleChainSelect'
import SubscribeButtonKyberAI from 'pages/TrueSightV2/components/SubscireButtonKyberAI'
import WatchlistButton from 'pages/TrueSightV2/components/WatchlistButton'
import WatchlistSelect from 'pages/TrueSightV2/components/TokenFilter/WatchlistSelect'
import { NETWORK_TO_CHAINID, SUPPORTED_NETWORK_KYBERAI, Z_INDEX_KYBER_AI } from 'pages/TrueSightV2/constants'
import { useGetFilterCategoriesQuery } from 'pages/TrueSightV2/hooks/useKyberAIData'
import { ICustomWatchlists } from 'pages/TrueSightV2/types'
import { useSessionInfo } from 'state/authen/hooks'
import { MEDIA_WIDTHS } from 'theme'

Expand All @@ -39,7 +37,7 @@ const StyledSkeleton = styled(Skeleton)`
width: 150px;
`

const StyledSelect = styled(Select)`
export const StyledSelect = styled(Select)`
${shareStyle}
`

Expand Down Expand Up @@ -106,6 +104,18 @@ const SelectGroup = styled.div`
const getChainsFromSlugs = (values: string[] | undefined) =>
(values || []).map(item => NETWORK_TO_CHAINID[item || '']).filter(Boolean)

export const ActiveSelectItem = ({ name, label }: { name: string; label: ReactNode }) => {
const theme = useTheme()
return (
<Column gap="6px">
<SelectName>{name}</SelectName>
<Text color={theme.text} fontSize={'14px'} fontWeight={'500'} className="test">
{label}
</Text>
</Column>
)
}

export default function TokenFilter({
handleFilterChange,
setShowShare,
Expand Down Expand Up @@ -158,12 +168,6 @@ export default function TokenFilter({
[chainFilter, onChangeFilter, allChainIds, onTrackingSelectChain],
)

const [watchListInfo, setWatchlistInfo] = useState<ICustomWatchlists>()
const handleChangeWatchlist = (watchlist: ICustomWatchlists) => {
setWatchlistInfo(watchlist)
onChangeFilter('watchlist', watchlist.id + '')
}

const isInit = useRef(false)
useEffect(() => {
if (isInit.current || defaultChains.length + allChainIds.length === 0) return
Expand All @@ -174,15 +178,12 @@ export default function TokenFilter({
// todo loading de len filter
const upToSmall = useMedia(`(max-width: ${MEDIA_WIDTHS.upToSmall}px)`)

const activeRender = (name: string, label: ReactNode) => (
<Column gap="6px">
<SelectName>{name}</SelectName>
<Text color={theme.text} fontSize={'14px'} fontWeight={'500'} className="test">
{label}
</Text>
</Column>
)

const menuStyle: CSSProperties = {
zIndex: Z_INDEX_KYBER_AI.FILTER_TOKEN_OPTIONS,
top: upToSmall ? undefined : SELECT_SIZE,
maxHeight: 400,
overflowY: 'scroll',
}
return (
<StyledWrapper>
<SelectGroup>
Expand All @@ -202,32 +203,23 @@ export default function TokenFilter({
handleChangeChains={handleChainChange}
chainIds={allChainIds}
selectedChainIds={selectedChains}
activeRender={node => activeRender('Chains', node)}
activeRender={node => <ActiveSelectItem name={'Chains'} label={node} />}
/>
{listSelects.map(({ queryKey, displayName, values }) => (
<StyledSelect
value={filter[queryKey]}
key={queryKey}
activeRender={item => activeRender(displayName, item?.label)}
activeRender={item => <ActiveSelectItem name={displayName} label={item?.label} />}
options={values}
onChange={value => onChangeFilter(queryKey, value)}
optionStyle={{ fontSize: '14px' }}
menuStyle={{
zIndex: Z_INDEX_KYBER_AI.FILTER_TOKEN_OPTIONS,
top: upToSmall ? undefined : SELECT_SIZE,
maxHeight: 400,
overflowY: 'scroll',
}}
menuStyle={menuStyle}
/>
))}
<WatchlistButton
trigger={
<StyledSelect
options={[]}
activeRender={() => activeRender('Watchlist', watchListInfo?.name || t`All Tokens`)}
/>
}
onSelectWatchlist={handleChangeWatchlist}
<WatchlistSelect
value={filter['watchlist']}
onChange={value => onChangeFilter('watchlist', value)}
menuStyle={menuStyle}
/>
</>
)}
Expand Down
126 changes: 59 additions & 67 deletions src/pages/TrueSightV2/components/WatchlistButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Trans, t } from '@lingui/macro'
import { AnimatePresence, Reorder, useDragControls } from 'framer-motion'
import { CSSProperties, ReactNode, memo, useEffect, useRef, useState } from 'react'
import { CSSProperties, memo, useEffect, useRef, useState } from 'react'
import { Check, Plus, X } from 'react-feather'
import { useDispatch } from 'react-redux'
import { Text } from 'rebass'
Expand Down Expand Up @@ -347,40 +347,86 @@ const debounce = (func: () => void, timeout = 1000) => {

const MAX_LIMIT_WATCHED_TOKEN = 50

export const ManageListModal = ({ isOpen, setIsOpen }: { isOpen: boolean; setIsOpen: (v: boolean) => void }) => {
const { data, refetch: refetchWatchlists } = useGetWatchlistInformationQuery()
const watchlists = data?.watchlists || []
const numberOfWatchlists = watchlists?.length || 0
const dispatch = useDispatch()
const [updateWatchlistsPriorities] = useUpdateCustomizedWatchlistsPrioritiesMutation()
const reorderWrapperRef = useRef<HTMLDivElement>(null)
const handleReorder = (newOrders: ICustomWatchlists[]) => {
const orderedIds = newOrders.map(item => item.id).join(',')
dispatch(
kyberAIApi.util.updateQueryData('getWatchlistInformation', undefined, draft => {
const order = orderedIds.split(',')
draft.watchlists = draft.watchlists.sort((a, b) => {
return order.indexOf(a.id.toString()) - order.indexOf(b.id.toString())
})
return draft
}),
)
debounce(() => updateWatchlistsPriorities({ orderedIds }), 1000)
}

const onDismiss = () => setIsOpen(false)

return (
<Modal isOpen={isOpen} width="380px" onDismiss={onDismiss}>
<ModalWrapper onClick={e => e.stopPropagation()}>
<RowBetween>
<Text>Manage Watchlists</Text>
<ButtonAction onClick={onDismiss}>
<X />
</ButtonAction>
</RowBetween>
<CreateListInput watchlistsCount={numberOfWatchlists} refetchList={() => refetchWatchlists()} />
<ReorderWrapper ref={reorderWrapperRef}>
<Reorder.Group axis="y" values={watchlists} onReorder={handleReorder}>
<AnimatePresence>
{watchlists?.map(item => (
<WatchlistsItem
wrapperRef={reorderWrapperRef}
watchlistsCount={numberOfWatchlists}
key={item.id}
item={item}
refetchList={() => refetchWatchlists()}
/>
))}
</AnimatePresence>
</Reorder.Group>
</ReorderWrapper>
</ModalWrapper>
</Modal>
)
}

function WatchlistButton({
assetId,
symbol,
size,
wrapperStyle,
onSelectWatchlist,
trigger,
}: {
assetId?: string
symbol?: string
size?: number
wrapperStyle?: CSSProperties
onSelectWatchlist?: (watchListId: ICustomWatchlists) => void
trigger?: ReactNode
}) {
const theme = useTheme()
const dispatch = useDispatch()

const mixpanelHandler = useMixpanelKyberAI()

const [openMenu, setOpenMenu] = useState(false)
const [openManageModal, setOpenManageModal] = useState(false)

const { data, refetch: refetchWatchlists } = useGetWatchlistInformationQuery()
const { data } = useGetWatchlistInformationQuery()
const watchlists = data?.watchlists || []
const numberOfWatchlists = watchlists?.length || 0
const isReachMaxLimit = (data?.totalUniqueAssetNumber || 0) >= MAX_LIMIT_WATCHED_TOKEN

const [updateWatchlistsPriorities] = useUpdateCustomizedWatchlistsPrioritiesMutation()

const [addToWatchlist] = useAddToWatchlistMutation()
const [removeFromWatchlist] = useRemoveFromWatchlistMutation()

const ref = useRef<HTMLDivElement>(null)
const reorderWrapperRef = useRef<HTMLDivElement>(null)

useOnClickOutside(ref, () => {
setOpenMenu(false)
})
Expand All @@ -405,25 +451,7 @@ function WatchlistButton({
}
}

const handleReorder = (newOrders: ICustomWatchlists[]) => {
const orderedIds = newOrders.map(item => item.id).join(',')
dispatch(
kyberAIApi.util.updateQueryData('getWatchlistInformation', undefined, draft => {
const order = orderedIds.split(',')
draft.watchlists = draft.watchlists.sort((a, b) => {
return order.indexOf(a.id.toString()) - order.indexOf(b.id.toString())
})
return draft
}),
)
debounce(() => updateWatchlistsPriorities({ orderedIds }), 1000)
}

const onSelect = (watchlist: ICustomWatchlists, watched: boolean) => {
if (onSelectWatchlist) {
onSelectWatchlist(watchlist)
return
}
watched ? handleRemoveFromWatchlist(watchlist.id) : handleAddtoWatchlist(watchlist.id)
}

Expand Down Expand Up @@ -483,45 +511,9 @@ function WatchlistButton({
placement="bottom-start"
noArrow={true}
>
{trigger ? (
<div
onClick={e => {
e.stopPropagation()
setOpenMenu(v => !v)
}}
>
{trigger}
</div>
) : (
btnStar
)}
{btnStar}
</Popover>
<Modal isOpen={openManageModal} width="380px">
<ModalWrapper onClick={e => e.stopPropagation()}>
<RowBetween>
<Text>Manage Watchlists</Text>
<ButtonAction onClick={() => setOpenManageModal(false)}>
<X />
</ButtonAction>
</RowBetween>
<CreateListInput watchlistsCount={numberOfWatchlists} refetchList={() => refetchWatchlists()} />
<ReorderWrapper ref={reorderWrapperRef}>
<Reorder.Group axis="y" values={watchlists} onReorder={handleReorder}>
<AnimatePresence>
{watchlists?.map(item => (
<WatchlistsItem
wrapperRef={reorderWrapperRef}
watchlistsCount={numberOfWatchlists}
key={item.id}
item={item}
refetchList={() => refetchWatchlists()}
/>
))}
</AnimatePresence>
</Reorder.Group>
</ReorderWrapper>
</ModalWrapper>
</Modal>
<ManageListModal isOpen={openManageModal} setIsOpen={setOpenManageModal} />
</div>
)
}
Expand Down

0 comments on commit 8cd1dbd

Please sign in to comment.