diff --git a/components/account/tabs/comments/AccountCommentPermlinkSearchResults.tsx b/components/account/tabs/comments/AccountCommentPermlinkSearchResults.tsx new file mode 100644 index 0000000000000000000000000000000000000000..678e11de2ec82ecc436f371bf6482c5bfd847d69 --- /dev/null +++ b/components/account/tabs/comments/AccountCommentPermlinkSearchResults.tsx @@ -0,0 +1,61 @@ +import { useSearchesContext } from "@/contexts/SearchesContext"; +import CustomPagination from "@/components/CustomPagination"; +import { config } from "@/Config"; +import AccountCommentPermlinkResultTable from "@/components/account/tabs/comments/AccountCommentPermlinkResultTable"; +import NoResult from "@/components/NoResult"; +import Hive from "@/types/Hive"; + +interface AccountCommentPermlinkSearchResultsProps { + data: Hive.CommentPermlinksResponse | null | undefined; + accountName: string; +} + +const AccountCommentPermlinkSearchResults: React.FC< + AccountCommentPermlinkSearchResultsProps +> = ({ data, accountName }) => { + const { + permlinkSearchProps, + setPermlinkSearchProps, + permlinkPaginationPage, + setPermlinkPaginationPage, + } = useSearchesContext(); + + const changePermlinkSearchPagination = (newPageNum: number) => { + const newSearchProps: any = { + ...permlinkSearchProps, + pageNumber: newPageNum, + }; + setPermlinkSearchProps(newSearchProps); + setPermlinkPaginationPage(newPageNum); + }; + + if (!data) return; + + return ( + <> + {data.total_permlinks ? ( +
+
+ +
+ +
+ +
+
+ ) : ( + + )} + + ); +}; + +export default AccountCommentPermlinkSearchResults; diff --git a/components/account/tabs/comments/AccountCommentsPermlinkSearch.tsx b/components/account/tabs/comments/AccountCommentsPermlinkSearch.tsx index 4142b255af18052205f77ee1207bc1485a4b9cd4..6be67a8e175adfd293efb7168608fcd4e9ffc98c 100644 --- a/components/account/tabs/comments/AccountCommentsPermlinkSearch.tsx +++ b/components/account/tabs/comments/AccountCommentsPermlinkSearch.tsx @@ -1,68 +1,30 @@ -import { useState, ChangeEvent, useEffect } from "react"; -import { useRouter } from "next/router"; +import { ChangeEvent } from "react"; import { Loader2 } from "lucide-react"; -import moment from "moment"; import Explorer from "@/types/Explorer"; -import { trimAccountName } from "@/utils/StringUtils"; import SearchRanges from "@/components/searchRanges/SearchRanges"; import { Button } from "@/components/ui/button"; import { useSearchesContext } from "@/contexts/SearchesContext"; -import usePermlinkSearch from "@/hooks/api/common/usePermlinkSearch"; -import { getSearchParams } from "@/components/home/searches/utils/getSearchParams"; import PostTypeSelector from "@/components/home/searches/PostTypeSelector"; -import { - DEFAULT_LAST_TIME_UNIT_VALUE, - DEFAULT_TIME_UNIT_SELECT_KEY, -} from "@/hooks/common/useSearchRanges"; +import usePermlinkCommentSearch from "./usePermlinkCommentSearch"; -const AccountCommentsPermlinkSearch = () => { - const { - permlinkSearchProps, - setPermlinkSearchProps, - setPermlinkPaginationPage, - permlinkPaginationPage, - setCommentType, - searchRanges, - } = useSearchesContext(); - const router = useRouter(); - const accountNameFromRoute = router.query.accountName as string; - - const { permlinkSearchDataLoading } = usePermlinkSearch(permlinkSearchProps); +interface AccountCommentsPermlinkSearchProps { + accountName: string; + isDataLoading: boolean; +} - const [accountName, setAccountName] = useState(""); - const [localCommentType, setLocalCommentType] = - useState(permlinkSearchProps?.commentType || "post"); +const AccountCommentsPermlinkSearch: React.FC< + AccountCommentsPermlinkSearchProps +> = ({ accountName, isDataLoading }) => { + const { setPermlinkPaginationPage, setCommentType, searchRanges } = + useSearchesContext(); const { - setRangesValues, - setLastTimeUnitValue, - setRangeSelectKey, - setTimeUnitSelectKey, - setFromBlock, - setToBlock, - setStartDate, - setEndDate, - setLastBlocksValue, - } = searchRanges; - - const handleCommentPermlinkSearch = async () => { - if (!accountName) return; - - const searchParams = await getSearchParams(searchRanges); - - if (!searchParams) return; - - const commentPermlinksSearchProps = { - accountName: trimAccountName(accountName), - commentType: localCommentType, - pageNumber: permlinkPaginationPage, - ...searchParams, - }; - - setPermlinkSearchProps(commentPermlinksSearchProps); - setRangesValues(commentPermlinksSearchProps); - }; + handleClearFilters, + handleCommentPermlinkSearch, + localCommentType, + setLocalCommentType, + } = usePermlinkCommentSearch(accountName); const handleChangeCommentType = (e: ChangeEvent) => { const { @@ -79,58 +41,9 @@ const AccountCommentsPermlinkSearch = () => { handleCommentPermlinkSearch(); }; - const handleClearFilters = async () => { - setFromBlock(undefined); - setToBlock(undefined); - setStartDate(undefined); - setEndDate(undefined); - setLastBlocksValue(undefined); - setLastTimeUnitValue(DEFAULT_LAST_TIME_UNIT_VALUE); - setRangeSelectKey("lastTime"); - setTimeUnitSelectKey(DEFAULT_TIME_UNIT_SELECT_KEY); - setLocalCommentType("post"); - setCommentType("post"); - - const commentPermlinksSearchProps = { - accountName: trimAccountName(accountName), - commentType: "post" as Explorer.CommentType, - pageNumber: 1, - fromBlock: undefined, - toBlock: undefined, - startDate: moment(Date.now()).subtract(30, "days").toDate(), - endDate: undefined, - lastBlocks: undefined, - lastTime: 30, - rangeSelectKey: "lastTime", - timeUnit: "days", - }; - setPermlinkSearchProps(commentPermlinksSearchProps); - setRangesValues(commentPermlinksSearchProps); - }; - - useEffect(() => { - if (!accountName) { - setAccountName(accountNameFromRoute); - } - }, [accountName, accountNameFromRoute]); - - useEffect(() => { - if (!accountName) return; - handleCommentPermlinkSearch(); - - return () => { - handleClearFilters(); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [accountName]); - return ( <> - - +
{ disabled={!accountName} > Search - {permlinkSearchDataLoading && ( - - )} + {isDataLoading && }
diff --git a/components/account/tabs/comments/CommentsTabContent.tsx b/components/account/tabs/comments/CommentsTabContent.tsx index 56d49aa28bc8966a1c405d89df2ed997c3c2b36c..63f4951d1702c0c1ae1d025a9ae9daef160226cf 100644 --- a/components/account/tabs/comments/CommentsTabContent.tsx +++ b/components/account/tabs/comments/CommentsTabContent.tsx @@ -1,9 +1,51 @@ -import CommentPermlinkSearchResults from "@/components/home/searches/searchesResults/CommentPermlinkSearchResults"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { TabsContent } from "@/components/ui/tabs"; import AccountCommentsPermlinkSearch from "./AccountCommentsPermlinkSearch"; +import AccountCommentPermlinkSearchResults from "./AccountCommentPermlinkSearchResults"; +import usePermlinkSearch from "@/hooks/api/common/usePermlinkSearch"; +import { useSearchesContext } from "@/contexts/SearchesContext"; +import moment from "moment"; +import { useState, useEffect } from "react"; +import { trimAccountName } from "@/utils/StringUtils"; +import { useRouter } from "next/router"; + +const DEFAULT_SEARCH_PROPS = { + accountName: undefined, + commentType: "post", + pageNumber: 1, + fromBlock: undefined, + toBlock: undefined, + startDate: moment(Date.now()).subtract(30, "days").toDate(), + endDate: undefined, + lastBlocks: undefined, + lastTime: 30, + rangeSelectKey: "lastTime", + timeUnit: "days", +}; const CommentsTabContent = () => { + const { permlinkSearchProps } = useSearchesContext(); + const router = useRouter(); + const [accountName, setAccountName] = useState(""); + + const props = { + ...DEFAULT_SEARCH_PROPS, + ...permlinkSearchProps, + accountName, + }; + + const { permlinkSearchData, permlinkSearchDataLoading } = + usePermlinkSearch(props); + + useEffect(() => { + if (!router.isReady) return; + + const accounNameFromRoute = trimAccountName( + router.query.accountName as string + ); + setAccountName(accounNameFromRoute); + }, [router.isReady, router.query.accountName]); + return ( @@ -11,10 +53,16 @@ const CommentsTabContent = () => { Comment Search - + - + ); }; diff --git a/components/account/tabs/comments/usePermlinkCommentSearch.tsx b/components/account/tabs/comments/usePermlinkCommentSearch.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1298d51f52ded0fb8b255eec8365050381786bfb --- /dev/null +++ b/components/account/tabs/comments/usePermlinkCommentSearch.tsx @@ -0,0 +1,92 @@ +import { useState } from "react"; +import { useSearchesContext } from "@/contexts/SearchesContext"; +import { + DEFAULT_TIME_UNIT_SELECT_KEY, + DEFAULT_LAST_TIME_UNIT_VALUE, +} from "@/hooks/common/useSearchRanges"; +import { trimAccountName } from "@/utils/StringUtils"; +import moment from "moment"; +import Explorer from "@/types/Explorer"; +import { getSearchParams } from "@/components/home/searches/utils/getSearchParams"; + +const usePermlinkCommentSearch = (accountName: string) => { + const { + searchRanges, + setCommentType, + permlinkSearchProps, + setPermlinkSearchProps, + permlinkPaginationPage, + } = useSearchesContext(); + + const [localCommentType, setLocalCommentType] = useState< + Explorer.CommentType | string + >(permlinkSearchProps?.commentType || "post"); + + const { + setRangesValues, + setLastTimeUnitValue, + setRangeSelectKey, + setTimeUnitSelectKey, + setFromBlock, + setToBlock, + setStartDate, + setEndDate, + setLastBlocksValue, + } = searchRanges; + + const handleClearFilters = async () => { + setFromBlock(undefined); + setToBlock(undefined); + setStartDate(undefined); + setEndDate(undefined); + setLastBlocksValue(undefined); + setLastTimeUnitValue(DEFAULT_LAST_TIME_UNIT_VALUE); + setRangeSelectKey("lastTime"); + setTimeUnitSelectKey(DEFAULT_TIME_UNIT_SELECT_KEY); + setLocalCommentType("post"); + setCommentType("post"); + + const commentPermlinksSearchProps = { + accountName: trimAccountName(accountName), + commentType: "post" as Explorer.CommentType, + pageNumber: 1, + fromBlock: undefined, + toBlock: undefined, + startDate: moment(Date.now()).subtract(30, "days").toDate(), + endDate: undefined, + lastBlocks: undefined, + lastTime: 30, + rangeSelectKey: "lastTime", + timeUnit: "days", + }; + setPermlinkSearchProps(commentPermlinksSearchProps); + setRangesValues(commentPermlinksSearchProps); + }; + + const handleCommentPermlinkSearch = async () => { + if (!accountName) return; + + const searchParams = await getSearchParams(searchRanges); + + if (!searchParams) return; + + const commentPermlinksSearchProps = { + accountName: trimAccountName(accountName), + commentType: localCommentType, + pageNumber: permlinkPaginationPage, + ...searchParams, + }; + + setPermlinkSearchProps(commentPermlinksSearchProps); + setRangesValues(commentPermlinksSearchProps); + }; + + return { + handleClearFilters, + handleCommentPermlinkSearch, + localCommentType, + setLocalCommentType, + }; +}; + +export default usePermlinkCommentSearch; diff --git a/components/home/searches/PostTypeSelector.tsx b/components/home/searches/PostTypeSelector.tsx index 64a3a66cce9fbcd4d4dfe6566dd21fe6cad4e5fb..2d6c1cc33b90bd450f948f355fa9b84f24b0b10a 100644 --- a/components/home/searches/PostTypeSelector.tsx +++ b/components/home/searches/PostTypeSelector.tsx @@ -6,7 +6,7 @@ const COMMENT_TYPES = ["all", "post", "comment"]; interface PostTypeSelectorProps { showLabel?: boolean | undefined; handleChange: ChangeEventHandler; - commentType: Explorer.CommentType; + commentType: Explorer.CommentType | string; } const PostTypeSelector: React.FC = ({ diff --git a/components/home/searches/searchesResults/CommentPermlinkSearchResults.tsx b/components/home/searches/searchesResults/CommentPermlinkSearchResults.tsx index 53d624574676952ef9b28c8f21c1c86ff36b36df..6ccef2c5dbcfc237b5ed845d3057b5b273c7eebb 100644 --- a/components/home/searches/searchesResults/CommentPermlinkSearchResults.tsx +++ b/components/home/searches/searchesResults/CommentPermlinkSearchResults.tsx @@ -3,8 +3,6 @@ import CommentPermlinkResultTable from "../CommentPermlinkResultTable"; import { useSearchesContext } from "@/contexts/SearchesContext"; import CustomPagination from "@/components/CustomPagination"; import { config } from "@/Config"; -import { useRouter } from "next/router"; -import AccountCommentPermlinkResultTable from "@/components/account/tabs/comments/AccountCommentPermlinkResultTable"; import NoResult from "@/components/NoResult"; const CommentPermlinkSearchResults = () => { @@ -18,8 +16,6 @@ const CommentPermlinkSearchResults = () => { setActiveSearchSection, setLastSearchKey, } = useSearchesContext(); - const router = useRouter(); - const isAccountPage = Boolean(router.query.accountName) || false; const { permlinkSearchData } = usePermlinkSearch(permlinkSearchProps); @@ -57,18 +53,11 @@ const CommentPermlinkSearchResults = () => {
- {isAccountPage ? ( - - ) : ( - - )} +
) : ( diff --git a/components/providers.tsx b/components/providers.tsx index 38d32299149de0bf9b33e1e271d150048faa6407..3786e3b052ba491c37c72ac09cb115ef5f3e2bc3 100644 --- a/components/providers.tsx +++ b/components/providers.tsx @@ -28,8 +28,10 @@ const Providers: React.FC<{ children: ReactNode }> = ({ children }) => { defaultOptions: { queries: { enabled: apiAddress !== null && nodeAddress !== null, + staleTime: 10000, }, }, + queryCache: new QueryCache({ onError: (error: any) => { toast.error("Error occured", { diff --git a/components/searchRanges/SearchRanges.tsx b/components/searchRanges/SearchRanges.tsx index 8da6b19ec9ffe66a0059b35893e789fac7e49e0e..7ad3d1ba6d6774a8cb4a111f7ecb236dd76fcb0d 100644 --- a/components/searchRanges/SearchRanges.tsx +++ b/components/searchRanges/SearchRanges.tsx @@ -11,10 +11,7 @@ interface SearchRangesProps { safeTimeRangeDisplay?: boolean; } -const SearchRanges: React.FC = ({ - rangesProps, - safeTimeRangeDisplay, -}) => { +const SearchRanges: React.FC = ({ rangesProps }) => { const { rangeSelectOptions, timeSelectOptions, @@ -36,29 +33,11 @@ const SearchRanges: React.FC = ({ setLastTimeUnitValue, } = rangesProps; - - const [rangeError, setRangeError] = useState(null); - - const handleOnBlur = ( - e: React.FocusEvent, - fieldSetter: Function, - validateField: Function | null - ) => { - const value = e.target.value; - const numericValue = value ? Number(value) : undefined; - - // Fetch the latest block number dynamically - let validated = true; - if (validateField) { - validated = validateField(e, numericValue); - } - - validated ? fieldSetter(numericValue) : fieldSetter(null); - }; + const [rangeError, setRangeError] = useState(null); const validateToBlock = ( e: React.FocusEvent, - value: number | undefined, + value: number | undefined ) => { if (value !== undefined && value <= 0) { setRangeError("Block Number must be a positive number"); @@ -75,7 +54,7 @@ const SearchRanges: React.FC = ({ const validateFromBlock = ( e: React.FocusEvent, - value: number | undefined, + value: number | undefined ) => { if (value !== undefined && value <= 0) { setRangeError("Block Number must be a positive number"); @@ -92,6 +71,8 @@ const SearchRanges: React.FC = ({ const handleNumericInput = ( e: React.ChangeEvent, + fieldSetter: Function, + validateField: Function | null, allowDecimal: boolean = false ) => { let cleanedValue = e.target.value; @@ -112,6 +93,15 @@ const SearchRanges: React.FC = ({ } e.target.value = cleanedValue; + + const numericValue = cleanedValue ? Number(cleanedValue) : undefined; + + let validated = true; + if (validateField) { + validated = validateField(e, numericValue); + } + + validated ? fieldSetter(numericValue) : fieldSetter(null); }; useEffect(() => { @@ -124,7 +114,6 @@ const SearchRanges: React.FC = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [startDate, endDate]); - return (
handleNumericInput(e)} - onBlur={(e) => handleOnBlur(e,setLastBlocksValue,null)} + value={lastBlocksValue || ""} + onChange={(e) => handleNumericInput(e, setLastBlocksValue, null)} placeholder={"Last"} />
@@ -175,9 +163,10 @@ const SearchRanges: React.FC = ({ handleNumericInput(e,true)} - onBlur={(e) => handleOnBlur(e,setLastTimeUnitValue,null)} + value={lastTimeUnitValue || ""} + onChange={(e) => + handleNumericInput(e, setLastTimeUnitValue, null) + } placeholder={"Last"} /> @@ -216,9 +205,10 @@ const SearchRanges: React.FC = ({ type="text" className="bg-theme border-0 border-b-2" data-testid="from-block-input" - defaultValue={fromBlock || ""} - onChange={(e) => handleNumericInput(e)} - onBlur={(e) => handleOnBlur(e,setFromBlock,validateFromBlock)} + value={fromBlock || ""} + onChange={(e) => + handleNumericInput(e, setFromBlock, validateFromBlock) + } placeholder="From" /> @@ -228,9 +218,10 @@ const SearchRanges: React.FC = ({ data-testid="headblock-number" type="text" defaultValue={toBlock || ""} - onChange={(e) => handleNumericInput(e)} + onChange={(e) => + handleNumericInput(e, setToBlock, validateToBlock) + } placeholder={"To"} - onBlur={(e) => handleOnBlur(e,setToBlock,validateToBlock)} /> @@ -267,4 +258,4 @@ const SearchRanges: React.FC = ({ ); }; -export default SearchRanges; \ No newline at end of file +export default SearchRanges; diff --git a/contexts/SearchesContext.tsx b/contexts/SearchesContext.tsx index aa3b401fbd639649ee2731c3833b97ceba56393e..d5827a17859c7c5d60be8abbcf7a01aaba60cf20 100644 --- a/contexts/SearchesContext.tsx +++ b/contexts/SearchesContext.tsx @@ -48,8 +48,8 @@ export interface SearchesContextType { setAccountOperationsSearchProps: Dispatch< SetStateAction >; - commentType: CommentType; - setCommentType: Dispatch>; + commentType: CommentType | string; + setCommentType: Dispatch>; commentsSearchAccountName: string | string[] | undefined; setCommentsSearchAccountName: Dispatch< SetStateAction @@ -121,7 +121,7 @@ export const SearchesContextProvider: React.FC<{ useState(undefined); // comment_type: post is default by backend - const [commentType, setCommentType] = useState("post"); + const [commentType, setCommentType] = useState("post"); const [commentsSearchAccountName, setCommentsSearchAccountName] = useState< string | string[] | undefined >(""); diff --git a/hooks/api/common/usePermlinkSearch.ts b/hooks/api/common/usePermlinkSearch.ts index d1ed0819e44daf1786387b7ec67069c3fe50baea..cc2098da46325781f7b56d215162858de0522605 100644 --- a/hooks/api/common/usePermlinkSearch.ts +++ b/hooks/api/common/usePermlinkSearch.ts @@ -8,12 +8,13 @@ const usePermlinkSearch = ( ) => { const { data: permlinkSearchData, - isFetching: permlinkSearchDataLoading, + isLoading: permlinkSearchDataLoading, isError: permlinkSearchDataError, } = useQuery({ queryKey: ["permlinkSearch", permlinkSearchProps], queryFn: () => fetchCommentPermlinks(permlinkSearchProps), refetchOnWindowFocus: false, + enabled: !!permlinkSearchProps?.accountName, }); const fetchCommentPermlinks = async ( diff --git a/pages/[accountName].tsx b/pages/[accountName].tsx index 3bc63faba66a439f21c3b4ec4f9bb939ad4da6ba..45af07830d0b3e4dc1621026f9a79f5a2ad1e46c 100644 --- a/pages/[accountName].tsx +++ b/pages/[accountName].tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import { Loader2, ArrowBigRightDash, X } from "lucide-react"; import { useRouter } from "next/router"; import Head from "next/head"; @@ -15,6 +15,7 @@ import { Button } from "@/components/ui/button"; import AccountOperationViewTabs from "@/components/account/tabs/AccountOperationViewTabs"; import { AccountTabsProvider } from "@/contexts/TabsContext"; import moment from "moment"; +import usePermlinkCommentSearch from "@/components/account/tabs/comments/usePermlinkCommentSearch"; export interface AccountSearchParams { accountName?: string | undefined; @@ -70,6 +71,8 @@ export default function Account() { dynamicGlobalData ); + const { handleClearFilters } = usePermlinkCommentSearch(accountNameFromRoute); + const renderAccountDetailsView = () => { if (isMobile) { return ( @@ -122,6 +125,11 @@ export default function Account() { } }; + useEffect(() => { + handleClearFilters(); + //eslint-disable-next-line react-hooks/exhaustive-deps + }, [accountNameFromRoute]); + // get the accountName and treat it as a string const routeAccountName = Array.isArray(router.query.accountName) ? router.query.accountName[0] // If it's an array, get the first element diff --git a/services/FetchingService.ts b/services/FetchingService.ts index f3afaf6f23650809b74d277bb68e0974297ec360..930719fd2bfb182b38965b07ade861a318390f31 100644 --- a/services/FetchingService.ts +++ b/services/FetchingService.ts @@ -359,7 +359,10 @@ class FetchingService { ): Promise { const requestParams: Hive.GetCommentPermlinksParams = { accountName: permlinkSearchProps.accountName, - "comment-type": permlinkSearchProps.commentType, + "comment-type": permlinkSearchProps.commentType as + | "all" + | "post" + | "comment", page: permlinkSearchProps.pageNumber || 1, "page-size": config.standardPaginationSize, "from-block": diff --git a/types/Explorer.ts b/types/Explorer.ts index 99cf67219ea422f68a650bda795c6f0c557ddfcf..bd040309bcd359a5206aa7b313ab4bda94ef31de 100644 --- a/types/Explorer.ts +++ b/types/Explorer.ts @@ -107,7 +107,7 @@ declare module Explorer { interface PermlinkSearchProps extends CommonSearchProps { accountName: string; - commentType?: CommentType; + commentType?: CommentType | string; pageNumber?: number; } @@ -244,7 +244,7 @@ declare module Explorer { curation_rewards: string; vesting_balance: string; reward_vesting_hive: string; - account_value : string; + account_value: string; } interface FormattedAccountDetails