import { memo, useMemo } from "react";
import {
LineChart,
Line,
XAxis,
YAxis,
Tooltip,
CartesianGrid,
ResponsiveContainer,
} from "recharts";
import ActivityHeatmap from "../stats/ActivityHeatmap";
import { ReactWordcloud } from "@cp949/react-wordcloud";
import StatsStyling from "../styles/stats_styling";
import Card from "../components/Card";
import {
type SummaryResponse,
type FrequencyWord,
type UserEndpointResponse,
type TimeAnalysisResponse,
type LinguisticAnalysisResponse,
} from "../types/ApiTypes";
import {
buildAllRecordsSpec,
buildDateBucketSpec,
buildOneTimeUsersSpec,
buildUserSpec,
type CorpusExplorerSpec,
} from "../utils/corpusExplorer";
const styles = StatsStyling;
const MAX_WORDCLOUD_WORDS = 250;
const exploreButtonStyle = { padding: "4px 8px", fontSize: 12 };
const WORDCLOUD_OPTIONS = {
rotations: 2,
rotationAngles: [0, 90] as [number, number],
fontSizes: [14, 60] as [number, number],
enableTooltip: true,
};
type SummaryStatsProps = {
userData: UserEndpointResponse | null;
timeData: TimeAnalysisResponse | null;
linguisticData: LinguisticAnalysisResponse | null;
summary: SummaryResponse | null;
onExplore: (spec: CorpusExplorerSpec) => void;
};
type WordCloudPanelProps = {
words: { text: string; value: number }[];
};
const WordCloudPanel = memo(({ words }: WordCloudPanelProps) => (
));
function formatDateRange(startUnix: number, endUnix: number) {
const start = new Date(startUnix * 1000);
const end = new Date(endUnix * 1000);
const fmt = (d: Date) =>
d.toLocaleDateString(undefined, {
year: "numeric",
month: "short",
day: "2-digit",
});
return `${fmt(start)} -> ${fmt(end)}`;
}
function convertFrequencyData(data: FrequencyWord[]) {
return data.map((d: FrequencyWord) => ({
text: d.word,
value: d.count,
}));
}
const renderExploreButton = (onClick: () => void) => (
);
const SummaryStats = ({
userData,
timeData,
linguisticData,
summary,
onExplore,
}: SummaryStatsProps) => {
const wordCloudWords = useMemo(
() =>
convertFrequencyData(
(linguisticData?.word_frequencies ?? []).slice(0, MAX_WORDCLOUD_WORDS),
),
[linguisticData?.word_frequencies],
);
const topUsersPreview = useMemo(
() => (userData?.top_users ?? []).slice(0, 100),
[userData?.top_users],
);
return (
onExplore(buildAllRecordsSpec()))}
style={{ gridColumn: "span 4" }}
/>
onExplore(buildAllRecordsSpec()))}
style={{ gridColumn: "span 4" }}
/>
onExplore(buildAllRecordsSpec()))}
style={{ gridColumn: "span 4" }}
/>
onExplore(buildAllRecordsSpec()))}
style={{ gridColumn: "span 4" }}
/>
onExplore(buildOneTimeUsersSpec()))}
style={{ gridColumn: "span 4" }}
/>
3 ? "..." : "")
: "-"
}
rightSlot={renderExploreButton(() => onExplore(buildAllRecordsSpec()))}
style={{ gridColumn: "span 4" }}
/>
Activity Over Time
How much posting happened each day.
{
const payload = (state as { activePayload?: Array<{ payload?: { date?: string } }> })
?.activePayload?.[0]?.payload as
| { date?: string }
| undefined;
if (payload?.date) {
onExplore(buildDateBucketSpec(String(payload.date)));
}
}}
>
Common Words
Frequently used words across the dataset.
Most Active Users
Who posted the most events.
{topUsersPreview.map((item) => (
onExplore(buildUserSpec(item.author))}
>
{item.author}
{item.source} • {item.count} events
))}
Weekly Activity Pattern
When activity tends to happen by weekday and hour.
);
};
export default SummaryStats;