import { useMemo } from "react"; import { BacklinksOverviewPanels, BacklinksResultsCard, } from "./BacklinksPageSections"; import { BacklinksAccessLoadingState, BacklinksErrorState, BacklinksLoadingState, BacklinksSetupGate, } from "./BacklinksPageStates"; import { BacklinksHistorySection } from "./BacklinksHistorySection"; import type { BacklinksSearchHistoryItem } from "@/client/hooks/useBacklinksSearchHistory"; import type { BacklinksOverviewData, BacklinksReferringDomainsData, BacklinksSearchState, BacklinksTopPagesData, } from "./backlinksPageTypes"; import type { UseAccessGateResult } from "@/client/features/access-gate/useAccessGate"; import { buildSummaryStats } from "./backlinksPageUtils"; import { filterBacklinkRows, filterReferringDomainRows, filterTopPageRows, } from "./backlinksFiltering"; import type { BacklinksFiltersState } from "./useBacklinksFilters"; import { SearchTabStrip, type SearchTab, } from "@/client/features/search-tabs/SearchTabStrip"; type BacklinksBodyProps = { projectId: string; accessGate: UseAccessGateResult; backlinksDisabledByError: boolean; history: BacklinksSearchHistoryItem[]; historyLoaded: boolean; overviewData: BacklinksOverviewData | undefined; overviewError: string | null; overviewLoading: boolean; referringDomains: BacklinksReferringDomainsData | undefined; searchState: BacklinksSearchState; filters: BacklinksFiltersState; tabErrorMessage: string | null; tabLoading: boolean; topPages: BacklinksTopPagesData | undefined; onRemoveHistoryItem: (timestamp: number) => void; onRetryOverview: () => void; onTabChange: (tab: BacklinksSearchState["tab"]) => void; searchTabs: { activeTabId: string | null; tabs: SearchTab[]; onSelect: (tab: SearchTab) => void; onClose: (tabId: string) => void; onViewed: (tabId: string, when?: number) => void; } | null; }; export function BacklinksBody({ projectId, accessGate, backlinksDisabledByError, history, historyLoaded, overviewData, overviewError, overviewLoading, referringDomains, searchState, filters, tabErrorMessage, tabLoading, topPages, onRemoveHistoryItem, onRetryOverview, onTabChange, searchTabs, }: BacklinksBodyProps) { const mergedData = useMemo( () => mergeTabData(overviewData, referringDomains, topPages), [overviewData, referringDomains, topPages], ); const filteredData = useMemo(() => { if (!mergedData) { return { backlinks: [], referringDomains: [], topPages: [] }; } return { backlinks: filterBacklinkRows( mergedData.backlinks, filters.backlinks.values, ), referringDomains: filterReferringDomainRows( mergedData.referringDomains, filters.domains.values, ), topPages: filterTopPageRows(mergedData.topPages, filters.pages.values), }; }, [ mergedData, filters.backlinks.values, filters.domains.values, filters.pages.values, ]); const summaryStats = useMemo( () => buildSummaryStats(mergedData), [mergedData], ); const tabStrip = searchTabs ? ( ) : null; if (accessGate.isLoading) { return ; } if (accessGate.statusErrorMessage) { return ( ); } if (!accessGate.enabled || backlinksDisabledByError) { return ( ); } if (!searchState.target) { return ( ); } if (overviewLoading) { return ( <> {tabStrip} ); } if (!mergedData) { return ( <> {tabStrip} ); } return ( <> {tabStrip} ); } function mergeTabData( data: BacklinksOverviewData | undefined, referringDomains: BacklinksReferringDomainsData | undefined, topPages: BacklinksTopPagesData | undefined, ) { if (!data) { return undefined; } return { ...data, referringDomains: referringDomains ?? data.referringDomains, topPages: topPages ?? data.topPages, }; }