From 3c19dee2364d7b4374911c47fd9248a96cf5e27f Mon Sep 17 00:00:00 2001 From: fahed Date: Tue, 31 Mar 2026 16:23:35 +0300 Subject: [PATCH] feat: add season annotation bands to Comparison trend chart 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) --- src/components/Comparison.tsx | 44 ++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/components/Comparison.tsx b/src/components/Comparison.tsx index 6637868..315bb46 100644 --- a/src/components/Comparison.tsx +++ b/src/components/Comparison.tsx @@ -532,11 +532,53 @@ function Comparison({ data, seasons, showDataLabels, setShowDataLabels, includeV }, [data, prevData, currData, ranges, chartMetric, getMetricValue, getPeriodLabel]); 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 = {}; + 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 = { ...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 } } };