diff --git a/components/journeys/TopPathsTable.tsx b/components/journeys/TopPathsTable.tsx index f85e57c..72bdcd1 100644 --- a/components/journeys/TopPathsTable.tsx +++ b/components/journeys/TopPathsTable.tsx @@ -2,7 +2,7 @@ import type { TopPath } from '@/lib/api/journeys' import { TableSkeleton } from '@/components/skeletons' -import { Path, ArrowRight, Clock, Users } from '@phosphor-icons/react' +import { Path, ArrowRight, Clock } from '@phosphor-icons/react' interface TopPathsTableProps { paths: TopPath[] @@ -24,8 +24,16 @@ function smartLabel(path: string): string { return `…/${segments[segments.length - 1]}` } +function truncateSequence(seq: string[], max: number): (string | null)[] { + if (seq.length <= max) return seq + const head = seq.slice(0, 3) + const tail = seq.slice(-2) + return [...head, null, ...tail] +} + export default function TopPathsTable({ paths, loading }: TopPathsTableProps) { const hasData = paths.length > 0 + const maxCount = hasData ? paths[0].session_count : 0 return (
@@ -41,49 +49,66 @@ export default function TopPathsTable({ paths, loading }: TopPathsTableProps) { {loading ? ( ) : hasData ? ( -
- {paths.map((path, i) => ( -
-
- - #{i + 1} - -
- - - {path.session_count.toLocaleString()} - - {path.avg_duration > 0 && ( - - - {formatDuration(path.avg_duration)} - - )} -
-
-
- {path.page_sequence.map((page, j) => ( -
- {j > 0 && ( - +
+ {paths.map((path, i) => { + const barWidth = maxCount > 0 ? (path.session_count / maxCount) * 100 : 0 + const displaySeq = truncateSequence(path.page_sequence, 7) + + return ( +
+ {/* Background bar */} +
+ + {/* Content */} +
+ {/* Path sequence */} +
+ {displaySeq.map((page, j) => ( +
+ {j > 0 && ( + + )} + {page === null ? ( + + … + + ) : ( + + {smartLabel(page)} + + )} +
+ ))} +
+ + {/* Stats */} +
+ {path.avg_duration > 0 && ( + + + {formatDuration(path.avg_duration)} + )} - - {smartLabel(page)} + + {path.session_count.toLocaleString()}
- ))} +
-
- ))} + ) + })}
) : (