feat(ui): contribution graph with daily activity heatmap

Add /v1/activity/daily endpoint returning per-day event counts via
generate_series + LEFT JOIN. Frontend renders an SVG contribution
graph with circles colored by quantile-based thresholds. Clicking a
day navigates to /activity/YYYY-MM-DD showing that day's events.

New /activity/:timespan route parses single dates (YYYY-MM-DD) and
ranges (YYYY-MM-DD..YYYY-MM-DD) from the URL to initialize the
activity timeline filter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-05 17:05:28 +03:00
parent 7de23303bd
commit 27ce16e630
10 changed files with 274 additions and 4 deletions

View File

@@ -65,6 +65,11 @@ export interface ProjectSummary {
last_activity: string | null;
}
export interface DailyCount {
date: string;
count: number;
}
export interface EventQuery {
from?: Date;
to?: Date;
@@ -102,6 +107,12 @@ export async function fetchSources(): Promise<SourceSummary[]> {
return resp.json();
}
export async function fetchDailyCounts(from: string, to: string): Promise<DailyCount[]> {
const resp = await fetch(`${API_BASE}/activity/daily?from=${from}&to=${to}`);
if (!resp.ok) throw new Error(`daily-counts: HTTP ${resp.status}`);
return resp.json();
}
export async function fetchProjects(): Promise<ProjectSummary[]> {
const resp = await fetch(`${API_BASE}/projects`);
if (!resp.ok) throw new Error(`projects: HTTP ${resp.status}`);