Money tracker: vertical month/year gridlines on wealth chart, keep range in ?range= URL param
All checks were successful
Deploy production / deploy (push) Successful in 2m36s
All checks were successful
Deploy production / deploy (push) Successful in 2m36s
This commit is contained in:
@@ -360,3 +360,45 @@ export function clipSeries(series: ChartSeries[], from: string | null): ChartSer
|
||||
return { ...line, points };
|
||||
});
|
||||
}
|
||||
|
||||
/** Reads a `?range=` value, falling back to one year for anything unknown. */
|
||||
export function parseHistoryRange(value: string | null | undefined): HistoryRange {
|
||||
return value === '3y' || value === 'all' ? value : '1y';
|
||||
}
|
||||
|
||||
export type GridMode = 'months' | 'years';
|
||||
export type GridLine = { date: string; year: boolean };
|
||||
|
||||
/**
|
||||
* Vertical gridlines between two dates (inclusive): the first of every month (`months`),
|
||||
* or only 1 January (`years`). Lines on 1 January are flagged so they can be drawn stronger.
|
||||
*/
|
||||
export function timeGrid(from: string, until: string, mode: GridMode): GridLine[] {
|
||||
const lines: GridLine[] = [];
|
||||
if (!from || !until || from > until) return lines;
|
||||
let year = Number(from.slice(0, 4));
|
||||
let month = Number(from.slice(5, 7)) - 1;
|
||||
if (from.slice(8) !== '01') month++;
|
||||
for (let guard = 0; guard < 1200; guard++) {
|
||||
if (month > 11) {
|
||||
month = 0;
|
||||
year++;
|
||||
}
|
||||
if (mode === 'years' && month !== 0) {
|
||||
month = 12;
|
||||
continue;
|
||||
}
|
||||
const date = `${year}-${String(month + 1).padStart(2, '0')}-01`;
|
||||
if (date > until) break;
|
||||
lines.push({ date, year: month === 0 });
|
||||
month++;
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
/** Year labels for the `years` grid, thinned to every 2nd/5th/10th year when crowded. */
|
||||
export function yearLabels(lines: GridLine[], maxLabels: number): string[] {
|
||||
const years = lines.filter((line) => line.year).map((line) => line.date);
|
||||
const step = [1, 2, 5, 10, 20].find((size) => Math.ceil(years.length / size) <= maxLabels) ?? 50;
|
||||
return years.filter((date) => Number(date.slice(0, 4)) % step === 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user