import Card from "./Card"; import StatsStyling from "../styles/stats_styling"; import type { InteractionAnalysisResponse } from "../types/ApiTypes"; import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, PieChart, Pie, Cell, Legend, } from "recharts"; const styles = StatsStyling; type InteractionalStatsProps = { data: InteractionAnalysisResponse; }; const InteractionalStats = ({ data }: InteractionalStatsProps) => { const graph = data.interaction_graph ?? {}; const userCount = Object.keys(graph).length; const edges = Object.values(graph).flatMap((targets) => Object.values(targets)); const edgeCount = edges.length; const interactionVolume = edges.reduce((sum, value) => sum + value, 0); const concentration = data.conversation_concentration; const topTenCommentShare = typeof concentration?.top_10pct_comment_share === "number" ? concentration?.top_10pct_comment_share : null; const topTenAuthorCount = typeof concentration?.top_10pct_author_count === "number" ? concentration.top_10pct_author_count : null; const totalCommentingAuthors = typeof concentration?.total_commenting_authors === "number" ? concentration.total_commenting_authors : null; const singleCommentAuthorRatio = typeof concentration?.single_comment_author_ratio === "number" ? concentration.single_comment_author_ratio : null; const singleCommentAuthors = typeof concentration?.single_comment_authors === "number" ? concentration.single_comment_authors : null; const topPairs = (data.top_interaction_pairs ?? []) .filter((item): item is [[string, string], number] => { if (!Array.isArray(item) || item.length !== 2) { return false; } const pair = item[0]; const count = item[1]; return Array.isArray(pair) && pair.length === 2 && typeof pair[0] === "string" && typeof pair[1] === "string" && typeof count === "number"; }) .slice(0, 20); const topPairChartData = topPairs.slice(0, 8).map(([[source, target], value], index) => ({ pair: `${source} -> ${target}`, replies: value, rank: index + 1, })); const topTenSharePercent = topTenCommentShare === null ? null : topTenCommentShare * 100; const nonTopTenSharePercent = topTenSharePercent === null ? null : Math.max(0, 100 - topTenSharePercent); let concentrationPieData: { name: string; value: number }[] = []; if (topTenSharePercent !== null && nonTopTenSharePercent !== null) { concentrationPieData = [ { name: "Top 10% authors", value: topTenSharePercent }, { name: "Other authors", value: nonTopTenSharePercent }, ]; } const PIE_COLORS = ["#2b6777", "#c8d8e4"]; return (
Who talks to who, and how concentrated the replies are.
Main reply links and concentration split.
Most common user-to-user reply paths.
{!topPairs.length ? (