File size: 3,126 Bytes
cd201c7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
import React from "react";
import { Tooltip } from "@mui/material";
import { getWeekDateRange } from "../utils/weeklyCalendar";
type WeeklyActivity = {
date: string;
count: number;
level: number;
};
type WeeklyHeatmapProps = {
data: WeeklyActivity[];
color: string;
};
const WeeklyHeatmap: React.FC<WeeklyHeatmapProps> = ({ data, color }) => {
// Group data by month and year
const groupedData = data.reduce((acc, activity) => {
const date = new Date(activity.date);
const yearMonth = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
if (!acc[yearMonth]) {
acc[yearMonth] = [];
}
acc[yearMonth].push(activity);
return acc;
}, {} as Record<string, WeeklyActivity[]>);
// Get color intensity based on level
const getColorIntensity = (level: number) => {
if (level === 0) return '#161b22'; // Dark background for no activity
const intensities = ['#0e4429', '#006d32', '#26a641', '#39d353'];
return intensities[Math.min(level - 1, 3)] || color;
};
// Get month names
const getMonthName = (yearMonth: string) => {
const [year, month] = yearMonth.split('-');
const date = new Date(parseInt(year), parseInt(month) - 1);
return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
};
const sortedMonths = Object.keys(groupedData).sort();
return (
<div className="w-full">
<div className="flex flex-wrap gap-4 justify-center">
{sortedMonths.map((yearMonth) => {
const monthData = groupedData[yearMonth];
return (
<div key={yearMonth} className="flex flex-col items-center">
<div className="text-xs mb-2 text-gray-600 dark:text-gray-400">
{getMonthName(yearMonth)}
</div>
<div className="flex gap-1">
{monthData.map((activity, index) => (
<Tooltip
key={`${yearMonth}-${index}`}
title={`${activity.count} new repos in week of ${getWeekDateRange(activity.date)}`}
arrow
>
<div
className="w-3 h-3 rounded-sm cursor-pointer transition-opacity hover:opacity-80"
style={{
backgroundColor: getColorIntensity(activity.level),
}}
/>
</Tooltip>
))}
</div>
</div>
);
})}
</div>
{/* Legend */}
<div className="flex items-center justify-center mt-4 text-xs text-gray-600 dark:text-gray-400">
<span className="mr-2">Less</span>
<div className="flex gap-1">
{[0, 1, 2, 3, 4].map((level) => (
<div
key={level}
className="w-2.5 h-2.5 rounded-sm"
style={{
backgroundColor: getColorIntensity(level),
}}
/>
))}
</div>
<span className="ml-2">More</span>
</div>
</div>
);
};
export default WeeklyHeatmap; |