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;