import { createColumnHelper, type Table } from "@tanstack/react-table"; import { ExternalLink } from "lucide-react"; import { AppDataTable } from "@/client/components/table/AppDataTable"; import { SortableHeader } from "@/client/components/table/SortableHeader"; import { numericNullsLast } from "@/client/components/table/nullSafeSort"; import { formatCount, formatPlatformLabel, } from "@/client/features/ai-search/platformLabels"; import { formatUrlForDisplay } from "@/client/components/table/url"; import type { BrandLookupResult } from "@/types/schemas/ai-search"; type TopPageRow = BrandLookupResult["topPages"][number]; type TopQueryRow = BrandLookupResult["topQueries"][number]; type PlatformKey = TopPageRow["platform"]; const PLATFORM_BADGE_CLASS: Record = { chat_gpt: "border-emerald-500/40 bg-emerald-500/10 text-emerald-500", google: "border-sky-500/40 bg-sky-500/10 text-sky-500", }; function PlatformBadge({ platform }: { platform: PlatformKey }) { return ( {formatPlatformLabel(platform)} ); } const pagesHelper = createColumnHelper(); const queriesHelper = createColumnHelper(); export const topPagesColumns = [ pagesHelper.accessor("url", { id: "url", header: () => URL, enableSorting: false, cell: ({ row }) => ( <> {formatUrlForDisplay(row.original.url)} {row.original.domain ? (

{row.original.domain}

) : null} ), }), pagesHelper.accessor("platform", { id: "platform", header: () => Platform, enableSorting: false, cell: ({ getValue }) => , }), pagesHelper.accessor("mentions", { id: "mentions", header: ({ column }) => ( ), cell: ({ getValue }) => ( {formatCount(getValue())} ), sortingFn: numericNullsLast, sortDescFirst: true, }), ]; export const topQueriesColumns = [ queriesHelper.accessor("question", { id: "question", header: () => Query, enableSorting: false, cell: ({ row }) => ( <>

{row.original.question}

{row.original.brandsMentioned.length > 0 ? (

Brands: {row.original.brandsMentioned.slice(0, 5).join(", ")}

) : null} ), }), queriesHelper.accessor("platform", { id: "platform", header: () => Platform, enableSorting: false, cell: ({ getValue }) => , }), queriesHelper.accessor("aiSearchVolume", { id: "aiSearchVolume", header: ({ column }) => ( ), cell: ({ getValue }) => ( {formatCount(getValue())} ), sortingFn: numericNullsLast, sortDescFirst: true, }), ]; export function TopPagesTable({ table }: { table: Table }) { if (table.getRowModel().rows.length === 0) { return (

No cited pages returned.

); } return ; } export function TopQueriesTable({ table }: { table: Table }) { if (table.getRowModel().rows.length === 0) { return (

No matching queries found.

); } return ; } function BrandLookupTable({ table, urlLikeColumnId, }: { table: Table; urlLikeColumnId: string; }) { return ( cellClassName( columnId, urlLikeColumnId, table.getColumn(columnId)?.getCanSort() ?? false, ) } getRowClassName={() => ""} /> ); } function cellClassName( columnId: string, urlLikeColumnId: string, isNumeric: boolean, ): string { if (columnId === urlLikeColumnId) { return "min-w-80 max-w-2xl align-top"; } if (isNumeric) { return "whitespace-nowrap text-right align-top"; } return "whitespace-nowrap align-top"; }