feat(charts): show actual dates in trend chart tooltips
Deploy HiHala Dashboard / deploy (push) Successful in 11s
Deploy HiHala Dashboard / deploy (push) Successful in 11s
Replace opaque W1/D1/month abbreviation tooltip titles with human-readable period labels (e.g. "Week 1 · 1 Apr – 7 Apr", "1 April 2025", "April 2025") in both Dashboard and Comparison trend charts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -88,7 +88,7 @@ export default function DashboardDemo({ data, seasons: _seasons, includeVAT, set
|
||||
return rows.reduce((s,r) => s + parseFloat(String((r as any)[f[m]]||0)), 0);
|
||||
}, [revenueField]);
|
||||
|
||||
const trendData = useMemo(() => {
|
||||
const trendResult = useMemo(() => {
|
||||
const group = (rows: MuseumRecord[], ps: string) => {
|
||||
const s = new Date(ps); const acc: Record<number, MuseumRecord[]> = {};
|
||||
rows.forEach(r => {
|
||||
@@ -102,18 +102,37 @@ export default function DashboardDemo({ data, seasons: _seasons, includeVAT, set
|
||||
};
|
||||
const pg = group(prevData, prevStart), cg = group(filteredData, start);
|
||||
const maxK = Math.max(...Object.keys(pg).map(Number), ...Object.keys(cg).map(Number), 1);
|
||||
const s0 = new Date(start);
|
||||
const fmt = (d: Date) => d.toLocaleDateString('en-GB', { day: 'numeric', month: 'short' });
|
||||
const labels = Array.from({length:maxK}, (_,i) =>
|
||||
gran==='week' ? `W${i+1}` : gran==='month' ? L.monthShort[(new Date(start).getMonth()+i)%12] : `D${i+1}`
|
||||
gran==='week' ? `W${i+1}` : gran==='month' ? L.monthShort[(s0.getMonth()+i)%12] : `D${i+1}`
|
||||
);
|
||||
const tooltipLabels = Array.from({length:maxK}, (_,i) => {
|
||||
if (gran==='week') {
|
||||
const ws = new Date(s0.getTime() + i * 7 * 86400000);
|
||||
const we = new Date(s0.getTime() + (i+1) * 7 * 86400000 - 86400000);
|
||||
return `Week ${i+1} · ${fmt(ws)} – ${fmt(we)}`;
|
||||
}
|
||||
if (gran==='month') {
|
||||
const ms = new Date(s0.getFullYear(), s0.getMonth() + i, 1);
|
||||
return ms.toLocaleDateString('en-GB', { month: 'long', year: 'numeric' });
|
||||
}
|
||||
const ds = new Date(s0.getTime() + i * 86400000);
|
||||
return ds.toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' });
|
||||
});
|
||||
const prevYear = parseInt(start.slice(0,4))-1;
|
||||
return {
|
||||
labels,
|
||||
datasets: [
|
||||
{ label:`${prevYear}`, data:labels.map((_,i) => pg[i+1]||0), borderColor:chartColors.muted, backgroundColor:'transparent', borderWidth:1.5, tension:0.4, pointRadius:0, borderDash:[4,3] },
|
||||
{ label:start.slice(0,4), data:labels.map((_,i) => cg[i+1]||0), borderColor:chartColors.primary, backgroundColor:chartColors.primary+'18', borderWidth:2.5, tension:0.4, fill:true, pointRadius:gran==='week'?3:1, pointBackgroundColor:chartColors.primary },
|
||||
]
|
||||
tooltipLabels,
|
||||
data: {
|
||||
labels,
|
||||
datasets: [
|
||||
{ label:`${prevYear}`, data:labels.map((_,i) => pg[i+1]||0), borderColor:chartColors.muted, backgroundColor:'transparent', borderWidth:1.5, tension:0.4, pointRadius:0, borderDash:[4,3] },
|
||||
{ label:start.slice(0,4), data:labels.map((_,i) => cg[i+1]||0), borderColor:chartColors.primary, backgroundColor:chartColors.primary+'18', borderWidth:2.5, tension:0.4, fill:true, pointRadius:gran==='week'?3:1, pointBackgroundColor:chartColors.primary },
|
||||
]
|
||||
}
|
||||
};
|
||||
}, [filteredData, prevData, prevStart, start, metric, gran, getVal, L]);
|
||||
const trendData = trendResult.data;
|
||||
|
||||
const museumData = useMemo(() => {
|
||||
const g = groupByMuseum(filteredData, includeVAT);
|
||||
@@ -172,6 +191,19 @@ export default function DashboardDemo({ data, seasons: _seasons, includeVAT, set
|
||||
const barNoLegend: any = { ...chartOpts, plugins:{ ...chartOpts.plugins, legend:{ display:false } } };
|
||||
return { chartOpts, barHorizOpts, barNoLegend };
|
||||
}, [baseOpts]);
|
||||
const trendOpts: any = useMemo(() => ({
|
||||
...chartOpts,
|
||||
plugins: {
|
||||
...chartOpts.plugins,
|
||||
tooltip: {
|
||||
...chartOpts.plugins.tooltip,
|
||||
callbacks: {
|
||||
title: (items: any[]) => trendResult.tooltipLabels[items[0]?.dataIndex] ?? items[0]?.label,
|
||||
}
|
||||
}
|
||||
}
|
||||
}), [chartOpts, trendResult.tooltipLabels]);
|
||||
|
||||
const pieOptions: any = useMemo(() => ({
|
||||
responsive: true, maintainAspectRatio: false,
|
||||
plugins: {
|
||||
@@ -250,7 +282,7 @@ export default function DashboardDemo({ data, seasons: _seasons, includeVAT, set
|
||||
{granOpts.map(o => <button key={o.value} type="button" aria-pressed={gran===o.value} className={`alt-ctrl${gran===o.value?' alt-ctrl-on':''}`} onClick={() => setGran(o.value)}>{o.label}</button>)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="alt-chart-wrap alt-chart-wrap--tall"><Line data={trendData} options={chartOpts} /></div>
|
||||
<div className="alt-chart-wrap alt-chart-wrap--tall"><Line data={trendData} options={trendOpts} /></div>
|
||||
</div>
|
||||
|
||||
<div className="alt-chart-card">
|
||||
|
||||
Reference in New Issue
Block a user