@@ -34,14 +34,40 @@ export default function CalendarHeatmap() {
3434 // Get previous year's data for background comparison
3535 const prevYear = ( parseInt ( year ) - 1 ) . toString ( )
3636 const prevYearData = useMemo ( ( ) => {
37- // Map previous year data to current year dates for overlay
37+ // Map previous year data to same day of week in current year
3838 return dailyCounts
3939 . filter ( d => d . date . startsWith ( prevYear ) )
40- . map ( d => ( {
41- ...d ,
42- // Shift the date to current year for alignment
43- date : year + d . date . slice ( 4 )
44- } ) )
40+ . map ( d => {
41+ // Parse the date components
42+ const [ prevYearStr , month , day ] = d . date . split ( '-' )
43+
44+ // Get day of week for this date in previous year
45+ const prevDate = new Date ( d . date )
46+ const prevDayOfWeek = prevDate . getDay ( )
47+
48+ // Get day of week for same date in current year
49+ const currentYearSameDate = new Date ( `${ year } -${ month } -${ day } ` )
50+ const currentYearDayOfWeek = currentYearSameDate . getDay ( )
51+
52+ // Calculate how many days to shift
53+ let dayShift = prevDayOfWeek - currentYearDayOfWeek
54+ if ( dayShift > 3 ) dayShift -= 7
55+ if ( dayShift < - 3 ) dayShift += 7
56+
57+ // Apply the shift
58+ const shiftedDate = new Date ( currentYearSameDate )
59+ shiftedDate . setDate ( shiftedDate . getDate ( ) + dayShift )
60+
61+ // Format back to YYYY-MM-DD
62+ const shiftedDateStr = shiftedDate . toISOString ( ) . slice ( 0 , 10 )
63+
64+ return {
65+ ...d ,
66+ date : shiftedDateStr
67+ }
68+ } )
69+ // Keep all dates that fall within the current year
70+ . filter ( d => d . date . startsWith ( year ) )
4571 } , [ dailyCounts , prevYear , year ] )
4672
4773 // Get max values for better color scaling
@@ -91,23 +117,60 @@ export default function CalendarHeatmap() {
91117 return content
92118 }
93119 } ,
94- visualMap : {
95- min : 0 ,
96- max : maxCount ,
97- calculable : true ,
98- orient : 'horizontal' ,
99- left : 'center' ,
100- bottom : 0 ,
101- inRange : {
102- color : [ '#1a1f2e' , '#3b4252' , '#6366f1' , '#8b5cf6' , '#d946ef' ]
103- } ,
104- text : [ 'High Activity' , 'Low Activity' ] ,
105- textStyle : {
106- color : '#94a3b8' ,
107- fontSize : 11
120+ visualMap : [
121+ // Visual map for previous year data (orange) - bottom slider
122+ {
123+ min : 0 ,
124+ max : maxCount ,
125+ calculable : true ,
126+ orient : 'horizontal' ,
127+ left : '10%' ,
128+ right : '55%' ,
129+ bottom : 0 ,
130+ inRange : {
131+ color : [ 'rgba(251, 146, 60, 0.1)' , 'rgba(251, 146, 60, 0.8)' ]
132+ } ,
133+ text : [ prevYear , '' ] ,
134+ textStyle : {
135+ color : '#fb923c' ,
136+ fontSize : 10
137+ } ,
138+ seriesIndex : 0 ,
139+ dimension : 1 ,
140+ handleStyle : {
141+ color : '#fb923c'
142+ } ,
143+ outOfRange : {
144+ color : 'transparent'
145+ }
108146 } ,
109- seriesIndex : 1 // Apply to heatmap series (second series)
110- } ,
147+ // Visual map for current year data (blue-purple) - bottom slider
148+ {
149+ min : 0 ,
150+ max : maxCount ,
151+ calculable : true ,
152+ orient : 'horizontal' ,
153+ left : '55%' ,
154+ right : '10%' ,
155+ bottom : 0 ,
156+ inRange : {
157+ color : [ '#1a1f2e' , '#3b4252' , '#6366f1' , '#8b5cf6' , '#d946ef' ]
158+ } ,
159+ text : [ year , '' ] ,
160+ textStyle : {
161+ color : '#6366f1' ,
162+ fontSize : 10
163+ } ,
164+ seriesIndex : 1 ,
165+ dimension : 1 ,
166+ handleStyle : {
167+ color : '#6366f1'
168+ } ,
169+ outOfRange : {
170+ color : 'transparent'
171+ }
172+ }
173+ ] ,
111174 calendar : {
112175 range : year ,
113176 top : 30 ,
@@ -145,19 +208,15 @@ export default function CalendarHeatmap() {
145208 }
146209 } ,
147210 series : [
148- // Previous year data (shown in orange where current year has no data )
211+ // Previous year data (all dates )
149212 {
150- type : 'scatter ' ,
213+ type : 'heatmap ' ,
151214 coordinateSystem : 'calendar' ,
152- symbolSize : 15 ,
153- data : prevYearData
154- . filter ( pd => ! data . some ( d => d . date === pd . date ) )
155- . map ( pd => ( {
156- value : [ pd . date , pd . count ] ,
157- itemStyle : {
158- color : `rgba(251, 146, 60, ${ 0.3 + Math . min ( pd . count / maxCount , 1 ) * 0.5 } )`
159- }
160- } ) )
215+ data : prevYearData . map ( pd => [ pd . date , pd . count ] ) ,
216+ itemStyle : {
217+ borderColor : '#2e3447' ,
218+ borderWidth : 1
219+ }
161220 } ,
162221 // Current year data
163222 {
0 commit comments