MCPcopy Create free account
hub / github.com/Fibi66/FeiControl / ActivityHeatmap

Function ActivityHeatmap

src/components/ActivityHeatmap.tsx:29–199  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

27}
28
29export function ActivityHeatmap() {
30 const [stats, setStats] = useState<HeatmapStats | null>(null);
31 const [loading, setLoading] = useState(true);
32 const [tooltip, setTooltip] = useState<{ day: string; count: number; x: number; y: number } | null>(null);
33
34 useEffect(() => {
35 fetch("/api/activities/stats")
36 .then((r) => r.json())
37 .then((data) => { setStats(data); setLoading(false); })
38 .catch(() => setLoading(false));
39 }, []);
40
41 if (loading) {
42 return (
43 <div style={{ padding: "1.5rem", backgroundColor: "var(--card)", borderRadius: "0.75rem", border: "1px solid var(--border)" }}>
44 <div style={{ height: "100px", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--text-muted)", fontSize: "0.875rem" }}>
45 Loading heatmap...
46 </div>
47 </div>
48 );
49 }
50
51 if (!stats) return null;
52
53 // Build 52-week grid
54 const today = new Date();
55 const startDay = subDays(today, 364);
56 const days = eachDayOfInterval({ start: startDay, end: today });
57
58 // Pad to start from Sunday
59 const firstDayOfWeek = startOfWeek(startDay, { weekStartsOn: 0 });
60 const paddedDays = eachDayOfInterval({ start: firstDayOfWeek, end: today });
61
62 // Map data
63 const dayMap: Record<string, number> = {};
64 for (const d of stats.heatmap) {
65 dayMap[d.day] = d.count;
66 }
67
68 const maxCount = Math.max(...Object.values(dayMap), 1);
69
70 // Group into weeks (columns)
71 const weeks: Array<Array<{ date: Date; count: number }>> = [];
72 let currentWeek: Array<{ date: Date; count: number }> = [];
73
74 for (const day of paddedDays) {
75 const key = format(day, "yyyy-MM-dd");
76 currentWeek.push({ date: day, count: dayMap[key] || 0 });
77 if (currentWeek.length === 7) {
78 weeks.push(currentWeek);
79 currentWeek = [];
80 }
81 }
82 if (currentWeek.length > 0) weeks.push(currentWeek);
83
84 const totalActivities = Object.values(dayMap).reduce((a, b) => a + b, 0);
85 const topTypes = Object.entries(stats.byType).sort(([, a], [, b]) => b - a).slice(0, 5);
86

Callers

nothing calls this directly

Calls 1

getColorFunction · 0.85

Tested by

no test coverage detected