Spaces:
Running
Running
Download apps/web/src/components/ui/ActivityHeatmap.tsx from Benaah/MicProtocol: direct link, hf CLI and curl.
- Browser
- Download file 4.35 kB
-
https://huggingface.co/spaces/Benaah/MicProtocol/resolve/main/apps/web/src/components/ui/ActivityHeatmap.tsx
- Command line
-
hf download hf://spaces/Benaah/MicProtocol/apps/web/src/components/ui/ActivityHeatmap.tsx
-
curl -L -o ActivityHeatmap.tsx https://huggingface.co/spaces/Benaah/MicProtocol/resolve/main/apps/web/src/components/ui/ActivityHeatmap.tsx
4.35 kB
| "use client"; | |
| import React from "react"; | |
| import { Activity, Flame, Calendar } from "lucide-react"; | |
| interface ActivityHeatmapProps { | |
| title?: string; | |
| subtitle?: string; | |
| data?: Array<{ date?: string; month?: string; count: number; level?: number }>; | |
| className?: string; | |
| } | |
| // Generate 12 months of activity data | |
| const generateMonthlyData = () => { | |
| const months = [ | |
| "Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
| "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", | |
| ]; | |
| return months.map((month, i) => ({ | |
| month, | |
| count: Math.floor(Math.random() * 100) + 20, | |
| level: Math.floor(Math.random() * 4), // 0-3 intensity | |
| })); | |
| }; | |
| const LEVEL_COLORS = [ | |
| "var(--border-color-subtle)", // level 0 - no activity | |
| "rgba(255, 159, 10, 0.15)", // level 1 - light | |
| "rgba(255, 159, 10, 0.4)", // level 2 - medium | |
| "var(--color-primary)", // level 3 - heavy | |
| ]; | |
| export function ActivityHeatmap({ | |
| title = "Activity Overview", | |
| subtitle = "Activity over the last 12 months", | |
| data, | |
| className, | |
| }: ActivityHeatmapProps) { | |
| const heatmapData = data || generateMonthlyData(); | |
| const maxCount = Math.max(...heatmapData.map((d) => d.count), 1); | |
| return ( | |
| <div | |
| className={[ | |
| "rounded-xl border border-border-color bg-bg-elevated p-6", | |
| className, | |
| ].filter(Boolean).join(" ")} | |
| style={{ borderColor: "var(--border-color)" }} | |
| > | |
| <div className="flex items-center justify-between mb-6"> | |
| <div> | |
| <p className="text-text-tertiary text-xs uppercase tracking-wider font-medium"> | |
| {title} | |
| </p> | |
| <p className="text-text-secondary text-sm">{subtitle}</p> | |
| </div> | |
| <div className="w-10 h-10 rounded-md bg-bg-tertiary flex items-center justify-center border border-border-color-subtle"> | |
| <Activity size={16} className="text-text-tertiary" /> | |
| </div> | |
| </div> | |
| {/* Heatmap grid */} | |
| <div className="grid grid-cols-12 gap-2 mb-6"> | |
| {heatmapData.map((item, i) => ( | |
| <div | |
| key={i} | |
| className="flex flex-col items-center gap-2" | |
| > | |
| <div | |
| className="h-8 rounded-sm transition-colors" | |
| style={{ | |
| backgroundColor: LEVEL_COLORS[item.level ?? 0], | |
| }} | |
| title={`${(item as { month?: string; date?: string }).month ?? (item as { month?: string; date?: string }).date ?? ""}: ${item.count} activities`} | |
| /> | |
| <span className="text-text-tertiary text-xs"> | |
| {(item as { month?: string; date?: string }).month ?? (item as { month?: string; date?: string }).date ?? ""} | |
| </span> | |
| </div> | |
| ))} | |
| </div> | |
| {/* Legend */} | |
| <div className="flex items-center gap-2 text-text-tertiary text-xs"> | |
| <div className="w-2 h-2 rounded-sm" style={{ backgroundColor: LEVEL_COLORS[0] }} /> | |
| <span>Low</span> | |
| <span className="mx-2">•</span> | |
| <div className="w-2 h-2 rounded-sm" style={{ backgroundColor: LEVEL_COLORS[2] }} /> | |
| <span>High</span> | |
| </div> | |
| {/* Stats summary */} | |
| <div className="mt-6 pt-6 border-t border-border-color-subtle grid grid-cols-3 gap-4"> | |
| <div className="text-center"> | |
| <div className="text-2xl font-display font-bold text-text-primary"> | |
| {heatmapData.reduce((sum, d) => sum + d.count, 0)} | |
| </div> | |
| <div className="text-text-tertiary text-xs uppercase tracking-wider"> | |
| Total Activities | |
| </div> | |
| </div> | |
| <div className="text-center"> | |
| <div className="text-2xl font-display font-bold text-text-primary"> | |
| {Math.round( | |
| heatmapData.reduce((sum, d) => sum + d.count, 0) / | |
| heatmapData.length | |
| )} | |
| </div> | |
| <div className="text-text-tertiary text-xs uppercase tracking-wider"> | |
| Avg per Month | |
| </div> | |
| </div> | |
| <div className="text-center"> | |
| <div className="text-2xl font-display font-bold text-text-primary"> | |
| {heatmapData[heatmapData.length - 1]?.count} | |
| </div> | |
| <div className="text-text-tertiary text-xs uppercase tracking-wider"> | |
| This Month | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |