import Checkbox from '@components/forms/Checkbox' import MangoDateRangePicker from '@components/forms/DateRangePicker' import Input from '@components/forms/Input' import Label from '@components/forms/Label' import MultiSelectDropdown from '@components/forms/MultiSelectDropdown' import { EXPLORERS } from '@components/settings/PreferredExplorerSettings' import Button, { IconButton } from '@components/shared/Button' import Tooltip from '@components/shared/Tooltip' import { Disclosure } from '@headlessui/react' import { AdjustmentsVerticalIcon, ArrowLeftIcon, ArrowPathIcon, ChevronDownIcon, ChevronRightIcon, } from '@heroicons/react/20/solid' import mangoStore, { LiquidationFeedItem } from '@store/mangoStore' import dayjs from 'dayjs' import useLocalStorageState from 'hooks/useLocalStorageState' import useMangoAccount from 'hooks/useMangoAccount' import useMangoGroup from 'hooks/useMangoGroup' import { useTranslation } from 'next-i18next' import Image from 'next/legacy/image' import { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react' import { PREFERRED_EXPLORER_KEY } from 'utils/constants' import { formatDecimal, formatFixedDecimals } from 'utils/numbers' import ActivityFeedTable from './ActivityFeedTable' interface Filters { deposit: boolean liquidate_token_with_token: boolean perp_trade: boolean swap: boolean withdraw: boolean } interface AdvancedFilters { symbol: string[] 'start-date': string 'end-date': string 'usd-lower': string 'usd-upper': string } const DEFAULT_FILTERS = { deposit: true, liquidate_token_with_token: true, perp_trade: true, swap: true, withdraw: true, } const DEFAULT_ADVANCED_FILTERS = { symbol: [], 'start-date': '', 'end-date': '', 'usd-lower': '', 'usd-upper': '', } const DEFAULT_PARAMS = [ 'deposit', 'liquidate_token_with_token', 'swap', 'perp_trade', 'withdraw', ] const ActivityFeed = () => { const activityFeed = mangoStore((s) => s.activityFeed.feed) const actions = mangoStore((s) => s.actions) const { mangoAccount } = useMangoAccount() const [showActivityDetail, setShowActivityDetail] = useState(null) const [filters, setFilters] = useState(DEFAULT_FILTERS) const [advancedFilters, setAdvancedFilters] = useState( DEFAULT_ADVANCED_FILTERS ) const [params, setParams] = useState(DEFAULT_PARAMS) useEffect(() => { if (mangoAccount) { const pubKey = mangoAccount.publicKey.toString() actions.fetchActivityFeed(pubKey) } }, [actions, mangoAccount]) const handleShowActivityDetails = (activity: any) => { setShowActivityDetail(activity) } const updateFilters = (e: ChangeEvent, filter: string) => { setFilters({ ...filters, [filter]: e.target.checked }) let newParams: string[] = DEFAULT_PARAMS if (params.includes(filter)) { newParams = params.filter((p) => p !== filter) } else { newParams = [...params, filter] } setParams(newParams) } const advancedParamsString = useMemo(() => { let advancedParams = '' Object.entries(advancedFilters).map((entry) => { if (entry[1].length) { advancedParams = advancedParams + `&${entry[0]}=${entry[1]}` } }) return advancedParams }, [advancedFilters]) const queryParams = useMemo(() => { return params.length === 5 ? advancedParamsString : `&activity-type=${params.toString()}${advancedParamsString}` }, [advancedParamsString, params]) return !showActivityDetail ? ( <> ) : ( ) } export default ActivityFeed const ActivityFilters = ({ filters, setFilters, updateFilters, params, setParams, advancedFilters, setAdvancedFilters, }: { filters: Filters setFilters: (x: Filters) => void updateFilters: (e: ChangeEvent, filter: string) => void params: string setParams: (x: string[]) => void advancedFilters: AdvancedFilters setAdvancedFilters: (x: AdvancedFilters) => void }) => { const { t } = useTranslation(['common', 'activity']) const actions = mangoStore((s) => s.actions) const loadActivityFeed = mangoStore((s) => s.activityFeed.loading) const { mangoAccount } = useMangoAccount() const [showMobileFilters, setShowMobileFilters] = useState(false) const [hasFilters, setHasFilters] = useState(false) const handleUpdateResults = useCallback(() => { const mangoAccount = mangoStore.getState().mangoAccount.current const set = mangoStore.getState().set if (params) { setHasFilters(true) } else { setHasFilters(false) } set((s) => { s.activityFeed.feed = [] s.activityFeed.loading = true }) if (mangoAccount) { actions.fetchActivityFeed(mangoAccount.publicKey.toString(), 0, params) } }, [actions, params]) const handleResetFilters = useCallback(async () => { const mangoAccount = mangoStore.getState().mangoAccount.current const set = mangoStore.getState().set setHasFilters(false) set((s) => { s.activityFeed.feed = [] s.activityFeed.loading = true }) if (mangoAccount) { await actions.fetchActivityFeed(mangoAccount.publicKey.toString()) setAdvancedFilters(DEFAULT_ADVANCED_FILTERS) setFilters(DEFAULT_FILTERS) setParams(DEFAULT_PARAMS) } }, [actions]) const handleUpdateMobileResults = () => { handleUpdateResults() setShowMobileFilters(false) } return mangoAccount ? (
{hasFilters ? (
handleResetFilters()} size="small" >
) : null}
setShowMobileFilters(!showMobileFilters)} role="button" className={`default-transition w-full bg-th-bkg-2 p-4 hover:bg-th-bkg-3 md:px-6`} >
{t('activity:filter-results')}
) : null } const ActivityTypeFiltersForm = ({ filters, updateFilters, }: { filters: Filters updateFilters: (e: ChangeEvent, filter: string) => void }) => { const { t } = useTranslation('activity') return (
updateFilters(e, 'deposit')} > {t('deposits')}
updateFilters(e, 'withdraw')} > {t('withdrawals')}
updateFilters(e, 'swap')} > {t('swaps')}
updateFilters(e, 'perp_trade')} > {t('perps')}
updateFilters(e, 'liquidate_token_with_token')} > {t('liquidations')}
) } interface AdvancedFiltersFormProps { advancedFilters: any setAdvancedFilters: (x: any) => void } const AdvancedFiltersForm = ({ advancedFilters, setAdvancedFilters, }: AdvancedFiltersFormProps) => { const { t } = useTranslation(['common', 'activity']) const { group } = useMangoGroup() const [dateFrom, setDateFrom] = useState(null) const [dateTo, setDateTo] = useState(null) const [valueFrom, setValueFrom] = useState(advancedFilters['usd-lower'] || '') const [valueTo, setValueTo] = useState(advancedFilters['usd-upper'] || '') const symbols = useMemo(() => { if (!group) return [] return Array.from(group.banksMapByName, ([key]) => key) }, [group]) useEffect(() => { if (advancedFilters['start-date']) { setDateFrom(new Date(advancedFilters['start-date'])) } if (advancedFilters['end-date']) { setDateTo(new Date(advancedFilters['end-date'])) } }, []) const toggleOption = (option: string) => { setAdvancedFilters((prevSelected: any) => { const newSelections = prevSelected.symbol ? [...prevSelected.symbol] : [] if (newSelections.includes(option)) { return { ...prevSelected, symbol: newSelections.filter((item) => item != option), } } else { newSelections.push(option) return { ...prevSelected, symbol: newSelections } } }) } useEffect(() => { if (dateFrom && dateTo) { setAdvancedFilters({ ...advancedFilters, 'start-date': dayjs(dateFrom).set('hour', 0).toISOString(), 'end-date': dayjs(dateTo) .set('hour', 23) .set('minute', 59) .toISOString(), }) } else { setAdvancedFilters({ ...advancedFilters, 'start-date': '', 'end-date': '', }) } }, [dateFrom, dateTo]) useEffect(() => { if (valueFrom && valueTo) { setAdvancedFilters({ ...advancedFilters, 'usd-lower': valueFrom, 'usd-upper': valueTo, }) } else { setAdvancedFilters({ ...advancedFilters, 'usd-lower': '', 'usd-upper': '', }) } }, [valueFrom, valueTo]) return ( <>