import { useCallback, useMemo } from "react"; import { BacklinksSearchCard } from "./BacklinksSearchCard"; import { BacklinksBody } from "./BacklinksPageContent"; import type { BacklinksPageProps } from "./backlinksPageTypes"; import type { BacklinksSearchState } from "./backlinksPageTypes"; import { navigateToBacklinksSearch, useBacklinksPageData, } from "./useBacklinksPageData"; import { useBacklinksFilters } from "./useBacklinksFilters"; import { useBacklinksSearchHistory } from "@/client/hooks/useBacklinksSearchHistory"; import type { BacklinksSearchTabInput, SearchTabInput, } from "@/client/features/search-tabs/types"; import { useSearchTabNavigation } from "@/client/features/search-tabs/useSearchTabNavigation"; export function BacklinksPage({ projectId, searchState, navigate, }: BacklinksPageProps) { const filters = useBacklinksFilters(); const { accessGate, activeTabErrorMessage, backlinksDisabledByError, overviewErrorMessage, overviewQuery, referringDomainsQuery, searchCardInitialValues, topPagesQuery, } = useBacklinksPageData({ projectId, searchState, }); const { history, isLoaded: historyLoaded, addSearch, removeHistoryItem, } = useBacklinksSearchHistory(projectId); const urlTabInput = useMemo(() => { if (searchState.target.trim() === "") return null; return { type: "backlinks", target: searchState.target, scope: searchState.scope, }; }, [searchState.scope, searchState.target]); const navigateToTab = useCallback( (input: SearchTabInput | null) => { if (input?.type !== "backlinks") { navigate({ search: () => ({}), replace: true, }); return; } navigateToBacklinksSearch(navigate, { target: input.target, scope: input.scope, }); }, [navigate], ); const handleResultTabChange = useCallback( (tab: BacklinksSearchState["tab"]) => { navigate({ search: (prev) => ({ ...prev, tab: tab === "backlinks" ? undefined : tab, }), replace: true, }); }, [navigate], ); const searchTabs = useSearchTabNavigation({ storageKey: `backlinks:${projectId}`, urlInput: urlTabInput, getLabel: useCallback( (input) => (input.type === "backlinks" ? input.target : ""), [], ), navigateToInput: navigateToTab, }); const toBacklinksTabInput = useCallback( ( values: Pick, ): BacklinksSearchTabInput => ({ type: "backlinks", target: values.target, scope: values.scope, }), [], ); return (

Backlinks

Understand who links to a site, what changed recently, and which pages attract links.

{!accessGate.isLoading && accessGate.enabled && !backlinksDisabledByError ? ( searchTabs.canOpenTab(toBacklinksTabInput(values)) } tabLimit={searchTabs.limit} onSubmit={(values) => { searchTabs.openTab(toBacklinksTabInput(values)); navigateToBacklinksSearch(navigate, values); addSearch({ target: values.target, scope: values.scope }); }} /> ) : null} void overviewQuery.refetch()} onTabChange={handleResultTabChange} searchTabs={ searchState.target ? { activeTabId: searchTabs.activeTabId, tabs: searchTabs.tabs, onSelect: searchTabs.selectTab, onClose: searchTabs.closeTab, onViewed: searchTabs.markTabViewed, } : null } />
); }