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,
};
}