File size: 3,633 Bytes
3857bd9
fdb7c58
d088c21
fdb7c58
cd201c7
 
494bbae
cd201c7
 
fdb7c58
 
 
 
 
d088c21
 
929d75e
 
cd201c7
fdb7c58
 
cd201c7
 
 
 
 
 
 
 
 
 
3857bd9
 
98fcc8e
3857bd9
 
98fcc8e
3857bd9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98fcc8e
3857bd9
 
cd201c7
82437bb
 
 
 
 
 
 
 
 
 
 
 
fbae805
82437bb
494bbae
fdb7c58
d088c21
929d75e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d088c21
929d75e
fdb7c58
cd201c7
 
 
 
82437bb
cd201c7
3857bd9
82437bb
 
3857bd9
cd201c7
 
 
3857bd9
 
 
 
 
 
 
 
cd201c7
 
fdb7c58
 
 
 
 
3857bd9
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import React, { useEffect, useState } from "react";
import ActivityCalendar from "react-activity-calendar";
import { Tooltip, Avatar } from "@mui/material";
import Link from "next/link";
import { aggregateToWeeklyData } from "../utils/weeklyCalendar";
import WeeklyHeatmap from "./WeeklyHeatmap";
import { getHeatmapTheme, getHeatmapColorIntensity } from "../utils/heatmapColors";

type ViewMode = 'daily' | 'weekly';

type HeatmapProps = {
  data: Array<{ date: string; count: number; level: number }>;
  color: string;
  providerName: string;
  fullName: string;
  avatarUrl: string;
  authorId: string;
  showHeader?: boolean;
  viewMode: ViewMode;
};

const Heatmap: React.FC<HeatmapProps> = ({ 
  data, 
  color, 
  providerName, 
  fullName, 
  avatarUrl, 
  authorId, 
  showHeader = true,
  viewMode 
}) => {
  // Process data based on view mode
  const processedData = viewMode === 'weekly' ? aggregateToWeeklyData(data) : data;
  
  // Track theme state for proper ActivityCalendar theming
  const [isDarkMode, setIsDarkMode] = useState(false);
  
  useEffect(() => {
    // Check initial theme
    const checkTheme = () => {
      setIsDarkMode(document.documentElement.classList.contains('dark'));
    };
    
    checkTheme();
    
    // Watch for theme changes
    const observer = new MutationObserver(checkTheme);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class']
    });
    
    return () => observer.disconnect();
  }, []);
  
  // Use theme-aware colors
  const emptyColor = isDarkMode ? "#374151" : "#d1d5db";
  
  // Create the correct color progression based on current theme
  const getThemeAwareColors = () => {
    const colors = [emptyColor]; // level 0
    
    for (let level = 1; level <= 4; level++) {
      const intensity = getHeatmapColorIntensity(level, color, isDarkMode);
      if (intensity) {
        colors.push(intensity);
      }
    }
    return colors;
  };
  
  const themeColors = getThemeAwareColors();
  
  return (
    <div className="flex flex-col items-center w-full mx-auto">
      {showHeader && (
        <div className="flex flex-col sm:flex-row items-center mb-4 w-full justify-center">
          {avatarUrl && (
            <Avatar src={avatarUrl} alt={fullName} className="mb-2 sm:mb-0 sm:mr-4" sx={{ width: 48, height: 48 }} />
          )}
          <div className="text-center sm:text-left">
            <h2 className="text-lg font-semibold">
              <Link
                href={`https://huggingface.co/${authorId}`}
                target="_blank"
                rel="noopener noreferrer"
                className="hover:text-blue-500 hover:underline"
              >
                {fullName}
              </Link>
            </h2>
          </div>
        </div>
      )}
      <div className="w-full overflow-x-auto flex justify-center">
        {viewMode === 'weekly' ? (
          <WeeklyHeatmap data={processedData} color={color} />
        ) : (
          <ActivityCalendar
            key={`${isDarkMode}-${color}`} // Force re-render on theme change
            data={processedData}
            theme={{
              light: themeColors,
              dark: themeColors
            }}
            blockSize={11}
            blockMargin={2}
            hideTotalCount
            renderBlock={(block, activity) => (
              <Tooltip
                title={`${activity.count} new repos on ${activity.date}`}
                arrow
              >
                {block}
              </Tooltip>
            )}
          />
        )}
      </div>
    </div>
  );
};

export default Heatmap;