import type { ColumnDef } from "@tanstack/react-table";
import { ChevronRight } from "lucide-react";
import { SortableHeader } from "@/client/components/table/SortableHeader";
import {
dateNullsLast,
numericNullsLast,
stringNullsLast,
} from "@/client/components/table/nullSafeSort";
import { HeaderHelpLabel } from "@/client/features/keywords/components";
import { BacklinksSourceLink } from "./BacklinksPageLinks";
import type { BacklinksRow, GroupedBacklinkDomain } from "./backlinksPageTypes";
import {
formatCompactDate,
formatDecimal,
formatNumber,
} from "./backlinksPageUtils";
function BacklinkFlags({ row }: { row: BacklinksRow }) {
return (
{row.isLost ? (
Lost
) : null}
{row.isBroken ? (
Broken
) : null}
{row.isDofollow === false ? (
Nofollow
) : null}
{row.linksCount != null && row.linksCount > 1 ? (
{row.linksCount} links
) : null}
);
}
function DomainFlagBadges({ group }: { group: GroupedBacklinkDomain }) {
const badges: Array<{ label: string; className: string }> = [];
if (group.lostCount > 0) {
badges.push({
label: `${group.lostCount} Lost`,
className:
"badge badge-sm badge-error badge-outline min-w-fit whitespace-nowrap",
});
}
if (group.brokenCount > 0) {
badges.push({
label: `${group.brokenCount} Broken`,
className:
"badge badge-sm badge-warning badge-outline min-w-fit whitespace-nowrap",
});
}
if (group.nofollowCount > 0) {
badges.push({
label: `${group.nofollowCount} Nofollow`,
className: "badge badge-sm badge-outline min-w-fit whitespace-nowrap",
});
}
if (badges.length === 0) return null;
return (
{badges.map((badge) => (
{badge.label}
))}
);
}
export const backlinksColumns: ColumnDef[] = [
{
id: "source",
accessorKey: "domain",
header: ({ column }) => (
),
size: 250,
minSize: 180,
cell: ({ row }) => {
if (row.depth > 0) {
const child = row.original._backlink;
return (
{child?.urlFrom ? (
) : (
-
)}
);
}
const group = row.original;
return (
{group.domain}
{group.backlinkCount}{" "}
{group.backlinkCount === 1 ? "backlink" : "backlinks"} ·{" "}
{group.targetCount} {group.targetCount === 1 ? "page" : "pages"}
);
},
sortingFn: stringNullsLast,
},
{
id: "target",
header: () => (
),
size: 220,
minSize: 150,
enableSorting: false,
cell: ({ row }) => {
if (row.depth > 0) {
const child = row.original._backlink;
return (
{child?.urlTo ? (
) : (
"-"
)}
);
}
return null;
},
},
{
id: "anchor",
header: () => (
),
size: 150,
minSize: 100,
enableSorting: false,
cell: ({ row }) => {
if (row.depth > 0) {
const child = row.original._backlink;
return (
{child?.anchor || "No anchor text"}
{child?.itemType ? (
{child.itemType}
) : null}
);
}
return null;
},
},
{
id: "flags",
header: () => (
),
size: 130,
minSize: 80,
enableSorting: false,
cell: ({ row }) => {
if (row.depth > 0) {
const child = row.original._backlink;
const hasFlags =
child?.isLost ||
child?.isBroken ||
child?.isDofollow === false ||
(child?.linksCount != null && child.linksCount > 1);
return hasFlags && child ? : null;
}
return ;
},
},
{
id: "linkAuthority",
header: () => (
),
size: 70,
minSize: 50,
enableSorting: false,
cell: ({ row }) => {
if (row.depth > 0) {
const child = row.original._backlink;
return (
{formatNumber(child?.rank)}
);
}
return null;
},
},
{
id: "domainAuthority",
accessorKey: "domainAuthority",
header: ({ column }) => (
),
size: 70,
minSize: 50,
cell: ({ row }) => {
if (row.depth > 0) return null;
return (
{formatNumber(row.original.domainAuthority)}
);
},
sortingFn: numericNullsLast,
sortDescFirst: true,
},
{
id: "spamScore",
accessorKey: "spamScore",
header: ({ column }) => (
),
size: 70,
minSize: 50,
cell: ({ row }) => {
const value =
row.depth > 0
? row.original._backlink?.spamScore
: row.original.spamScore;
return (
{value != null && value > 0 ? Math.round(value) : null}
);
},
sortingFn: numericNullsLast,
sortDescFirst: true,
},
{
id: "firstSeen",
accessorKey: "firstSeen",
header: ({ column }) => (
),
size: 110,
minSize: 80,
cell: ({ row }) => {
if (row.depth > 0) {
const child = row.original._backlink;
return (
{formatCompactDate(child?.firstSeen)}
{child?.lastSeen ? (
Last {formatCompactDate(child.lastSeen)}
) : null}
);
}
return (
{formatCompactDate(row.original.firstSeen)}
);
},
sortingFn: dateNullsLast,
sortDescFirst: true,
},
];