feat: add season annotation bands to Comparison trend chart
All checks were successful
Deploy HiHala Dashboard / deploy (push) Successful in 7s
All checks were successful
Deploy HiHala Dashboard / deploy (push) Successful in 7s
Seasons that overlap the current comparison period appear as colored bands on the Revenue Trend chart, same as Dashboard. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -532,11 +532,53 @@ function Comparison({ data, seasons, showDataLabels, setShowDataLabels, includeV
|
|||||||
}, [data, prevData, currData, ranges, chartMetric, getMetricValue, getPeriodLabel]);
|
}, [data, prevData, currData, ranges, chartMetric, getMetricValue, getPeriodLabel]);
|
||||||
|
|
||||||
const baseOptions = useMemo(() => createBaseOptions(showDataLabels), [showDataLabels]);
|
const baseOptions = useMemo(() => createBaseOptions(showDataLabels), [showDataLabels]);
|
||||||
|
|
||||||
|
// Map seasons to annotation bands on the current period's timeline
|
||||||
|
const seasonAnnotations = useMemo(() => {
|
||||||
|
if (!seasons.length) return {};
|
||||||
|
const currStart = new Date(ranges.curr.start);
|
||||||
|
const currEnd = new Date(ranges.curr.end);
|
||||||
|
const annotations: Record<string, unknown> = {};
|
||||||
|
const msPerDay = 1000 * 60 * 60 * 24;
|
||||||
|
const granDivisor = chartGranularity === 'month' ? 30 : chartGranularity === 'week' ? 7 : 1;
|
||||||
|
|
||||||
|
seasons.forEach((s, i) => {
|
||||||
|
const sStart = new Date(s.StartDate);
|
||||||
|
const sEnd = new Date(s.EndDate);
|
||||||
|
// Check overlap with current period
|
||||||
|
if (sEnd < currStart || sStart > currEnd) return;
|
||||||
|
|
||||||
|
const clampedStart = sStart < currStart ? currStart : sStart;
|
||||||
|
const clampedEnd = sEnd > currEnd ? currEnd : sEnd;
|
||||||
|
const startIdx = Math.floor((clampedStart.getTime() - currStart.getTime()) / msPerDay / granDivisor);
|
||||||
|
const endIdx = Math.floor((clampedEnd.getTime() - currStart.getTime()) / msPerDay / granDivisor);
|
||||||
|
|
||||||
|
annotations[`season${i}`] = {
|
||||||
|
type: 'box',
|
||||||
|
xMin: startIdx - 0.5,
|
||||||
|
xMax: endIdx + 0.5,
|
||||||
|
backgroundColor: s.Color + '20',
|
||||||
|
borderColor: s.Color + '40',
|
||||||
|
borderWidth: 1,
|
||||||
|
label: {
|
||||||
|
display: true,
|
||||||
|
content: `${s.Name} ${s.HijriYear}`,
|
||||||
|
position: 'start',
|
||||||
|
color: s.Color,
|
||||||
|
font: { size: 10, weight: '600' },
|
||||||
|
padding: 4
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return annotations;
|
||||||
|
}, [seasons, ranges.curr, chartGranularity]);
|
||||||
|
|
||||||
const chartOptions: any = {
|
const chartOptions: any = {
|
||||||
...baseOptions,
|
...baseOptions,
|
||||||
plugins: {
|
plugins: {
|
||||||
...baseOptions.plugins,
|
...baseOptions.plugins,
|
||||||
legend: { position: 'top', align: 'end', labels: { boxWidth: 12, padding: 12, font: { size: 13 } } }
|
legend: { position: 'top', align: 'end', labels: { boxWidth: 12, padding: 12, font: { size: 13 } } },
|
||||||
|
annotation: { annotations: seasonAnnotations }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user