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 Button, { IconButton, LinkButton } from '@components/shared/Button' import Modal from '@components/shared/Modal' import Tooltip from '@components/shared/Tooltip' import { Disclosure, Transition } from '@headlessui/react' import { ArrowLeftIcon, ArrowPathIcon, ChevronDownIcon, } 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 { useViewport } from 'hooks/useViewport' import { useTranslation } from 'next-i18next' import Image from 'next/legacy/image' import { EXPLORERS } from 'pages/settings' import { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react' import { PREFERRED_EXPLORER_KEY } from 'utils/constants' import { formatDecimal, formatFixedDecimals } from 'utils/numbers' import { breakpoints } from 'utils/theme' import ActivityFeedTable from './ActivityFeedTable' interface Filters { deposit: boolean liquidate_token_with_token: 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, withdraw: true, } const DEFAULT_ADVANCED_FILTERS = { symbol: [], 'start-date': '', 'end-date': '', 'usd-lower': '', 'usd-upper': '', } const DEFAULT_PARAMS = ['deposit', 'liquidate_token_with_token', 'withdraw'] const ActivityFeed = () => { const activityFeed = mangoStore((s) => s.activityFeed.feed) const initialLoad = mangoStore((s) => s.activityFeed.initialLoad) 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 && !initialLoad) { const pubKey = mangoAccount.publicKey.toString() actions.fetchActivityFeed(pubKey) } }, [actions, initialLoad, 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 === 3 ? advancedParamsString : `&activity-type=${params.toString()}${advancedParamsString}` }, [advancedParamsString, params]) return !showActivityDetail ? ( <> ) : ( ) } export default ActivityFeed const ActivityFilters = ({ filters, setFilters, updateFilters, params, advancedFilters, setAdvancedFilters, }: { filters: Filters setFilters: (x: Filters) => void updateFilters: (e: ChangeEvent, filter: string) => void params: string 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 [showAdvancedFiltersModal, setShowAdvancedFiltersModal] = useState(false) const { width } = useViewport() const isMobile = width ? width < breakpoints.lg : false 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) } }, [actions]) const handleUpdateModalResults = () => { handleUpdateResults() setShowAdvancedFiltersModal(false) } const handleUpdateMobileResults = () => { handleUpdateResults() setShowMobileFilters(false) } return mangoAccount ? ( !isMobile ? ( <>

{t('activity:filter-results')}

setShowAdvancedFiltersModal(true)} > {t('activity:advanced-filters')} {hasFilters ? ( handleResetFilters()} size="small" > ) : null}
{showAdvancedFiltersModal ? ( setShowAdvancedFiltersModal(false)} >

{t('activity:advanced-filters')}

) : null} ) : (
{hasFilters ? (
handleResetFilters()} size="small" >
) : null}
setShowMobileFilters(!showMobileFilters)} role="button" className={`default-transition w-full border-b border-th-bkg-3 bg-th-bkg-2 px-6 py-4 hover:bg-th-bkg-3`} > {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, '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 ( <>