feat(web): add Analytics page with Chart.js charts and activity feed

Add Analytics page with stat cards (open tasks, active time, top category),
Chart.js timeline bar chart bucketed by hour, category donut chart with
legend, and paginated activity feed with htmx "Load more" support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 22:33:12 -05:00
parent fc674847f5
commit 91f2eec922
4 changed files with 464 additions and 1 deletions

View File

@@ -1638,6 +1638,24 @@ body::before {
.space-y-8 > * + * { margin-top: 32px; }
/* ============================================================
ANALYTICS PAGE
============================================================ */
.analytics-page { max-width: 1152px; margin: 0 auto; }
.analytics-header { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 16px; margin-bottom: 32px; }
.analytics-filters { display: flex; gap: 12px; }
.stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 32px; }
.category-legend { display: flex; flex-direction: column; gap: 8px; }
.category-legend-item { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.category-legend-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.category-legend-name { color: var(--color-text-primary); flex: 1; }
.category-legend-count { color: var(--color-text-secondary); font-size: 12px; }
.category-legend-pct { color: var(--color-text-tertiary); font-size: 11px; width: 32px; text-align: right; }
section { margin-bottom: 32px; }
.search-empty { padding: 24px; text-align: center; color: var(--color-text-secondary); font-size: 14px; }
/* ============================================================
RESPONSIVE
============================================================ */
@@ -1657,10 +1675,16 @@ body::before {
grid-template-columns: 1fr;
}
.grid-cols-3 {
.grid-cols-3,
.stat-grid {
grid-template-columns: 1fr;
}
.analytics-header {
flex-direction: column;
align-items: flex-start;
}
.search-modal {
width: calc(100vw - 20px);
top: 10%;