diff --git a/components/account/AccountDetailsSection.tsx b/components/account/AccountDetailsSection.tsx index f485b291fde7d135b86e04cb09a8ead18cde55f8..c10b24aa85e9658b2802228195e27b0b240f0822 100644 --- a/components/account/AccountDetailsSection.tsx +++ b/components/account/AccountDetailsSection.tsx @@ -18,7 +18,6 @@ import Explorer from "@/types/Explorer"; import AccountBalanceHistoryCard from "./AccountBalanceHistoryCard"; interface AccountDetailsSectionProps { accountName: string; - refetchAccountOperations: QueryObserverResult["refetch"]; liveDataEnabled: boolean; changeLiveRefresh: () => void; accountDetails?: Explorer.FormattedAccountDetails; @@ -27,11 +26,10 @@ interface AccountDetailsSectionProps { const AccountDetailsSection: React.FC = ({ accountName, - refetchAccountOperations, liveDataEnabled, changeLiveRefresh, accountDetails, - dynamicGlobalData + dynamicGlobalData, }) => { const { witnessDetails, isWitnessDetailsLoading, isWitnessDetailsError } = useWitnessDetails(accountName, !!accountDetails?.is_witness); @@ -89,13 +87,19 @@ const AccountDetailsSection: React.FC = ({ accountName={accountName} liveDataEnabled={liveDataEnabled} /> - { accountDetails.is_witness && !isWitnessDetailsError && !!witnessDetails && ( - - )} - + {accountDetails.is_witness && + !isWitnessDetailsError && + !!witnessDetails && ( + + )} + void; - accountOperations: Hive.OperationsCount; + operationsCount: number; } const AccountPagination: React.FC = ({ page, setPage, - accountOperations, + operationsCount, }) => { const onLatestButtonClick = () => { setPage(undefined); @@ -29,7 +28,7 @@ const AccountPagination: React.FC = ({ { if (!accountNameFromRoute) return; return () => handleClearCommentSearch(); + //eslint-disable-next-line react-hooks/exhaustive-deps }, [accountNameFromRoute]); return ( diff --git a/components/account/tabs/operations/AccountOperationsSection.tsx b/components/account/tabs/operations/AccountOperationsSection.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b9f6a7c5f2ccbf9ef4d99cb5172baf4ddc0e3ee4 --- /dev/null +++ b/components/account/tabs/operations/AccountOperationsSection.tsx @@ -0,0 +1,73 @@ +import { Loader2 } from "lucide-react"; + +import Hive from "@/types/Hive"; +import { convertOperationResultsToTableOperations } from "@/lib/utils"; +import NoResult from "@/components/NoResult"; +import OperationsTable from "@/components/OperationsTable"; +import { defaultSearchParams } from "@/pages/[accountName]"; +import useURLParams from "@/hooks/common/useURLParams"; +import useOperationsFormatter from "@/hooks/common/useOperationsFormatter"; +import AccountPagination from "../../AccountPagination"; + +interface AccountOperationsSectionProps { + accountOperations: Hive.AccountOperationsResponse | undefined; + isAccountOperationsLoading: boolean; +} + +const AccountOperationsSection: React.FC = ({ + accountOperations, + isAccountOperationsLoading, +}) => { + const { paramsState, setParams } = useURLParams(defaultSearchParams); + const { page: pageParam } = paramsState; + + const formattedAccountOperations = useOperationsFormatter( + accountOperations + ) as Hive.AccountOperationsResponse; + + if (!isAccountOperationsLoading && !accountOperations?.total_operations) { + return ( +
+ +
+ ); + } else if (isAccountOperationsLoading) { + return ( +
+ +
+ ); + } + return ( + <> +
+ {accountOperations && + accountOperations.total_pages && + accountOperations.total_operations && ( + + setParams({ ...paramsState, page }) + } + operationsCount={accountOperations.total_operations || 0} + /> + )} +
+ + + + ); +}; + +export default AccountOperationsSection; diff --git a/components/account/tabs/operations/OperationsTabContent.tsx b/components/account/tabs/operations/OperationsTabContent.tsx index 3066b625cc6f8299b57fcf1e29cc87ba55dafa4a..2bac1b43e40518d9fe2530b22ca4d43b4b32a41c 100644 --- a/components/account/tabs/operations/OperationsTabContent.tsx +++ b/components/account/tabs/operations/OperationsTabContent.tsx @@ -1,32 +1,28 @@ -// TODO: This component should be investigated and rebuild in more simple way. -// Possible improvements: handleSearch function , reduce count of use effects. -// I believe we could use much less code and export what is nacessary to other components or utils functions and leave component less crowded than it is now - -import { useEffect, useState } from "react"; -import { Loader2 } from "lucide-react"; +import { useState } from "react"; import { useRouter } from "next/router"; import SearchRanges from "@/components/searchRanges/SearchRanges"; import { Button } from "@/components/ui/button"; import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; import { TabsContent } from "@/components/ui/tabs"; -import OperationsTable from "@/components/OperationsTable"; import useURLParams from "@/hooks/common/useURLParams"; import { defaultSearchParams } from "@/pages/[accountName]"; -import useOperationsFormatter from "@/hooks/common/useOperationsFormatter"; import { convertBooleanArrayToIds, convertIdsToBooleanArray, - convertOperationResultsToTableOperations, } from "@/lib/utils"; -import Hive from "@/types/Hive"; -import AccountPagination from "../../AccountPagination"; import useAccountOperations from "@/hooks/api/accountPage/useAccountOperations"; import useAccountOperationTypes from "@/hooks/api/accountPage/useAccountOperationTypes"; import OperationTypesDialog from "@/components/OperationTypesDialog"; import { getOperationButtonTitle } from "@/utils/UI"; import { useSearchesContext } from "@/contexts/SearchesContext"; -import NoResult from "@/components/NoResult"; +import { + DEFAULT_RANGE_SELECT_KEY, + DEFAULT_LAST_BLOCK_VALUE, + DEFAULT_LAST_TIME_UNIT_VALUE, + DEFAULT_TIME_UNIT_SELECT_KEY, +} from "@/hooks/common/useSearchRanges"; +import AccountOperationsSection from "./AccountOperationsSection"; interface OpeationTabContentProps { liveDataEnabled: boolean; @@ -38,16 +34,9 @@ const OperationTabContent: React.FC = ({ const router = useRouter(); const { searchRanges } = useSearchesContext(); - const { paramsState, setParams } = useURLParams( - { - ...defaultSearchParams, - }, - ["accountName"] - ); - - const [filters, setFilters] = useState([]); - const [initialSearch, setInitialSearch] = useState(false); - const [lastPage, setLastPage] = useState(undefined); + const { paramsState, setParams } = useURLParams(defaultSearchParams, [ + "accountName", + ]); const { filters: filtersParam, @@ -55,188 +44,94 @@ const OperationTabContent: React.FC = ({ toBlock: toBlockParam, fromDate: fromDateParam, toDate: toDateParam, - lastBlocks: lastBlocksParam, - timeUnit: timeUnitParam, - lastTime: lastTimeParam, - rangeSelectKey, - page, } = paramsState; const accountNameFromRoute = (router.query.accountName as string)?.replace( "@", "" ); + const accountOperationsProps = { accountName: accountNameFromRoute, operationTypes: filtersParam.length ? convertBooleanArrayToIds(filtersParam) - : undefined, + : null, pageNumber: paramsState.page, fromBlock: fromBlockParam, toBlock: toBlockParam, startDate: fromDateParam, endDate: toDateParam, }; + + // Operation types + const [filters, setFilters] = useState([]); + const { accountOperations, isAccountOperationsLoading } = useAccountOperations(accountOperationsProps, liveDataEnabled); - const formattedAccountOperations = useOperationsFormatter( - accountOperations - ) as Hive.AccountOperationsResponse; + const { accountOperationTypes } = + useAccountOperationTypes(accountNameFromRoute); + + const handleClearFilter = () => { + const { + setRangeSelectKey, + setTimeUnitSelectKey, + setLastTimeUnitValue, + setLastBlocksValue, + } = searchRanges; - const handleFilterClear = () => { - const newPage = rangeSelectKey !== "lastTime" ? undefined : page; - setParams({ + const props = { ...defaultSearchParams, accountName: accountNameFromRoute, - page: newPage, - }); - searchRanges.setRangeSelectKey("lastTime"); + }; + + setRangeSelectKey(DEFAULT_RANGE_SELECT_KEY); + setTimeUnitSelectKey(DEFAULT_TIME_UNIT_SELECT_KEY); + setLastTimeUnitValue(DEFAULT_LAST_TIME_UNIT_VALUE); + setLastBlocksValue(DEFAULT_LAST_BLOCK_VALUE); + setParams(props); setFilters([]); }; - const { accountOperationTypes } = - useAccountOperationTypes(accountNameFromRoute); - const handleOperationSelect = (filters: number[] | null) => { const newFilters = convertIdsToBooleanArray(filters); setFilters(newFilters); setParams({ ...paramsState, filters: newFilters, page: undefined }); }; - const buildOperationView = () => { - if (!isAccountOperationsLoading && !accountOperations?.total_operations) { - return ( -
- -
- ); - } else if (isAccountOperationsLoading) { - return ( -
- -
- ); - } else { - return ( -
-
- {accountOperations && (page || lastPage) && ( - - setParams({ ...paramsState, page }) - } - accountOperations={accountOperations} - /> - )} -
- - -
- ); - } + const handleSearch = async () => { + const { + payloadFromBlock, + payloadToBlock, + payloadStartDate, + payloadEndDate, + } = await searchRanges.getRangesValues(); + + const props = { + ...paramsState, + fromBlock: payloadFromBlock, + toBlock: payloadToBlock, + fromDate: payloadStartDate, + toDate: payloadEndDate, + lastBlocks: + searchRanges.rangeSelectKey === "lastBlocks" + ? searchRanges.lastBlocksValue + : undefined, + lastTime: + searchRanges.rangeSelectKey === "lastTime" + ? searchRanges.lastTimeUnitValue + : undefined, + timeUnit: + searchRanges.rangeSelectKey === "lastTime" + ? searchRanges.timeUnitSelectKey + : undefined, + rangeSelectKey: searchRanges.rangeSelectKey, + page: undefined, + }; + + setParams(props); }; - const handleSearch = async (resetPage?: boolean) => { - if ( - !initialSearch && - (!!fromDateParam || - !!toDateParam || - !!fromBlockParam || - !!toBlockParam || - !!lastBlocksParam || - !!lastTimeParam || - !!filtersParam?.length) - ) { - fromDateParam && searchRanges.setStartDate(fromDateParam); - toDateParam && searchRanges.setEndDate(toDateParam); - fromBlockParam && searchRanges.setFromBlock(fromBlockParam); - toBlockParam && searchRanges.setToBlock(toBlockParam); - lastBlocksParam && searchRanges.setLastBlocksValue(lastBlocksParam); - timeUnitParam && searchRanges.setTimeUnitSelectKey(timeUnitParam); - rangeSelectKey && searchRanges.setRangeSelectKey(rangeSelectKey); - searchRanges.setLastTimeUnitValue(lastTimeParam); - setFilters(filtersParam); - setInitialSearch(true); - } else { - if (!initialSearch && !isAccountOperationsLoading && accountOperations) { - setInitialSearch(true); - } - - const { - payloadFromBlock, - payloadToBlock, - payloadStartDate, - payloadEndDate, - } = await searchRanges.getRangesValues(); - - setParams({ - ...paramsState, - filters: filters, - fromBlock: payloadFromBlock, - toBlock: payloadToBlock, - fromDate: payloadStartDate, - toDate: payloadEndDate, - lastBlocks: - searchRanges.rangeSelectKey === "lastBlocks" - ? searchRanges.lastBlocksValue - : undefined, - lastTime: - searchRanges.rangeSelectKey === "lastTime" - ? searchRanges.lastTimeUnitValue - : undefined, - timeUnit: - searchRanges.rangeSelectKey === "lastTime" - ? searchRanges.timeUnitSelectKey - : undefined, - rangeSelectKey: searchRanges.rangeSelectKey, - page: resetPage ? undefined : page, - }); - } - }; - - useEffect(() => { - if (!page && accountOperations) { - setLastPage(accountOperations.total_pages); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [accountOperations, page]); - - useEffect(() => { - if (paramsState && !initialSearch) { - handleSearch(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [paramsState]); - - useEffect(() => { - if ( - router.query.page && - accountOperations && - (Number(router.query.page) <= 0 || - Number(router.query.page) > accountOperations.total_pages) - ) { - router.replace({ - query: { - ...router.query, - page: accountOperations.total_pages, - }, - }); - } - }, [router, accountOperations]); - return ( @@ -250,10 +145,12 @@ const OperationTabContent: React.FC = ({ @@ -261,20 +158,26 @@ const OperationTabContent: React.FC = ({
-
- {buildOperationView()} +
); }; diff --git a/components/home/searches/CommentsSearch.tsx b/components/home/searches/CommentsSearch.tsx index 4efd49811295ad6cf7a1a4a306fa0675d57841a1..dd5d06cf9b52e6647a2675b18fcf299423c7aabd 100644 --- a/components/home/searches/CommentsSearch.tsx +++ b/components/home/searches/CommentsSearch.tsx @@ -111,7 +111,9 @@ const CommentsSearch = () => { useEffect(() => { if (!commentsSearchAccountName || commentsSearchPermlink) return; + return () => handleClearCommentSearch(); + //eslint-disable-next-line react-hooks/exhaustive-deps }, [commentsSearchAccountName, commentsSearchPermlink]); return ( diff --git a/components/post/PostPageContent.tsx b/components/post/PostPageContent.tsx index 0af790b200592f88eda4262c3a420d78985e6da8..cb65c230ea2d16d07fbbf4e40b140c33ba8f569c 100644 --- a/components/post/PostPageContent.tsx +++ b/components/post/PostPageContent.tsx @@ -14,10 +14,19 @@ const PostPageContent = () => { const { post } = router.query; const accountName = post?.[1] ?? ""; const permlink = post?.[2] ?? ""; - const path = router.asPath; const { data } = usePostContent(accountName, permlink); + const buildLinkByUrl = (url: string) => { + return `${url}/${accountName}/${permlink}`; + }; + + const LINKS = [ + { name: "hive.blog", href: buildLinkByUrl(HIVE_BLOG_URL) }, + { name: "peakd.com", href: buildLinkByUrl(PEAKD_URL) }, + { name: "ecency.com", href: buildLinkByUrl(ECENCY_URL) }, + ]; + if (!data) return; const { title, author, active_votes } = data; @@ -30,29 +39,20 @@ const PostPageContent = () => {
View this thread on: - - hive.blog - {" "} - | - - peakd.com - {" "} - | - - ecency.com - + {LINKS.map(({ name, href }) => { + return ( +
+ + {name} + {" "} + | +
+ ); + })}
= useQuery({ queryKey: ["account_operations", accountOperationsProps, liveDataEnabled], queryFn: () => fetchAccountOperations(accountOperationsProps), refetchOnWindowFocus: false, - refetchInterval: liveDataEnabled ? config.accountRefreshInterval : false, + refetchInterval: liveDataEnabled + ? config.accountRefreshInterval + : undefined, enabled: !!accountOperationsProps?.accountName && !!accountOperationsProps?.accountName.length, @@ -36,7 +37,6 @@ const useAccountOperations = ( accountOperations, isAccountOperationsLoading, isAccountOperationsError, - refetchAccountOperations, }; }; diff --git a/hooks/common/useSearchRanges.ts b/hooks/common/useSearchRanges.ts index 7b92f2971061d59a40cc016e17d881588956b82b..294c80c19ecb94968e40427b491c8ff3b24cd593 100644 --- a/hooks/common/useSearchRanges.ts +++ b/hooks/common/useSearchRanges.ts @@ -1,13 +1,16 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import moment from "moment"; import { config } from "@/Config"; import Explorer from "@/types/Explorer"; import { useHeadBlockNumber } from "../../contexts/HeadBlockContext"; +import useURLParams from "./useURLParams"; +import { defaultSearchParams } from "@/pages/[accountName]"; export const DEFAULT_LAST_BLOCK_VALUE = 1000; export const DEFAULT_LAST_TIME_UNIT_VALUE = 30; export const DEFAULT_TIME_UNIT_SELECT_KEY = "days"; +export const DEFAULT_RANGE_SELECT_KEY = "lastTime"; interface RangesValues { payloadFromBlock?: number; @@ -39,7 +42,11 @@ export interface SearchRangesResult { setRangesValues: (params: Explorer.CommentSearchParams | undefined) => void; } -const useSearchRanges = (defaultSelectKey: string = "lastTime") => { +const useSearchRanges = ( + defaultSelectKey: string = DEFAULT_RANGE_SELECT_KEY +) => { + const { paramsState } = useURLParams(defaultSearchParams); + const rangeSelectOptions: Explorer.SelectOption[] = [ { name: "Last blocks", @@ -99,16 +106,17 @@ const useSearchRanges = (defaultSelectKey: string = "lastTime") => { const [timeUnitSelectKey, setTimeUnitSelectKey] = useState( DEFAULT_TIME_UNIT_SELECT_KEY ); - const { checkTemporaryHeadBlockNumber } = useHeadBlockNumber(); - const setRangesValues = (params: Explorer.CommentSearchParams) => { + const setRangesValues = (params: any) => { if (!params) return; params.fromBlock && setFromBlock(params.fromBlock); params.toBlock && setToBlock(params.toBlock); params.startDate && setStartDate(params.startDate); params.endDate && setEndDate(params.endDate); + params.fromDate && setStartDate(params.fromDate); + params.toDate && setEndDate(params.toDate); params.lastBlocks && setLastBlocksValue(params.lastBlocks); params.lastTime && setLastTimeUnitValue(params.lastTime); params.rangeSelectKey && setRangeSelectKey(params.rangeSelectKey); @@ -142,9 +150,12 @@ const useSearchRanges = (defaultSelectKey: string = "lastTime") => { .milliseconds(0) .toDate(); } - + //Validate that payloadStartDate is a valid - if (payloadStartDate && (isNaN(payloadStartDate?.getTime()) || payloadStartDate?.getTime() <= 0)) { + if ( + payloadStartDate && + (isNaN(payloadStartDate?.getTime()) || payloadStartDate?.getTime() <= 0) + ) { payloadStartDate = undefined; //fallback } //Validate that payloadToBlock does not exceed latest headblock number @@ -154,8 +165,7 @@ const useSearchRanges = (defaultSelectKey: string = "lastTime") => { payloadToBlock = currentHeadBlockNumber; //fallback } } - if(payloadFromBlock) - { + if (payloadFromBlock) { const currentHeadBlockNumber = await checkTemporaryHeadBlockNumber(); if (payloadFromBlock > currentHeadBlockNumber) { payloadFromBlock = currentHeadBlockNumber; //fallback @@ -170,6 +180,13 @@ const useSearchRanges = (defaultSelectKey: string = "lastTime") => { }; }; + // Set range values from url params + useEffect(() => { + if (paramsState) { + setRangesValues(paramsState); + } + }, [paramsState]); + return { rangeSelectOptions, timeSelectOptions, diff --git a/pages/[...post].tsx b/pages/[...post].tsx index 71097348b03242bbcefb94c1f39f6c1b541a4594..049b644fcc5fa7be2f188532e80fc60c8906ac94 100644 --- a/pages/[...post].tsx +++ b/pages/[...post].tsx @@ -39,11 +39,9 @@ const Post = () => { const community = data?.category; if (!community) return; - const newQuery = [community, accountName, permlink] as string[]; + const url = `${community}/${encodeURI(accountName)}/${permlink}`; - router.replace({ - query: { post: newQuery }, - }); + router.replace(url); return ; } else if (post.length === 3) { diff --git a/pages/[accountName].tsx b/pages/[accountName].tsx index ef147180605b7d25197facdc43937fe22e08f032..44b466028a9c6f2af1a27fe201e1244d8393dca8 100644 --- a/pages/[accountName].tsx +++ b/pages/[accountName].tsx @@ -4,10 +4,8 @@ import { useRouter } from "next/router"; import Head from "next/head"; import ErrorPage from "./ErrorPage"; -import { cn, convertBooleanArrayToIds } from "@/lib/utils"; -import useAccountOperations from "@/hooks/api/accountPage/useAccountOperations"; +import { cn } from "@/lib/utils"; import useMediaQuery from "@/hooks/common/useMediaQuery"; -import useURLParams from "@/hooks/common/useURLParams"; import useConvertedAccountDetails from "@/hooks/common/useConvertedAccountDetails"; import useDynamicGlobal from "@/hooks/api/homePage/useDynamicGlobal"; import ScrollTopButton from "@/components/ScrollTopButton"; @@ -16,6 +14,7 @@ import MobileAccountNameCard from "@/components/account/MobileAccountNameCard"; import { Button } from "@/components/ui/button"; import AccountOperationViewTabs from "@/components/account/tabs/AccountOperationViewTabs"; import { AccountTabsProvider } from "@/contexts/TabsContext"; +import moment from "moment"; interface AccountSearchParams { accountName?: string | undefined; @@ -35,7 +34,7 @@ export const defaultSearchParams: AccountSearchParams = { accountName: undefined, fromBlock: undefined, toBlock: undefined, - fromDate: undefined, + fromDate: moment(new Date()).subtract(30, "days").toDate(), toDate: undefined, lastBlocks: undefined, lastTime: 30, @@ -60,21 +59,6 @@ export default function Account() { setLiveDataEnabled((prev) => !prev); }; - const { paramsState } = useURLParams( - { - ...defaultSearchParams, - }, - ["accountName"] - ); - - const { - filters: filtersParam, - fromBlock: fromBlockParam, - toBlock: toBlockParam, - fromDate: fromDateParam, - toDate: toDateParam, - } = paramsState; - const [showMobileAccountDetails, setShowMobileAccountDetails] = useState(false); @@ -86,22 +70,6 @@ export default function Account() { dynamicGlobalData ); - const accountOperationsProps = { - accountName: accountNameFromRoute, - operationTypes: filtersParam.length - ? convertBooleanArrayToIds(filtersParam) - : undefined, - pageNumber: paramsState.page, - fromBlock: fromBlockParam, - toBlock: toBlockParam, - startDate: fromDateParam, - endDate: toDateParam, - }; - const { refetchAccountOperations } = useAccountOperations( - accountOperationsProps, - liveDataEnabled - ); - const renderAccountDetailsView = () => { if (isMobile) { return ( @@ -131,7 +99,6 @@ export default function Account() {