fix(period): [ and ] snap odd ranges to calendar months, fresh visit opens the current period
This commit is contained in:
1 parent
741e5a49ba
commit
92db7d4093
2 files changed
+47
-8
No files matched your search
+40
-1
@@ -130,12 +130,39 @@ function unitOf(range: Range, view: ViewRange): ViewRange | null {
|
||||
);
|
||||
}
|
||||
|
||||
export function shiftPeriod(range: Range, view: ViewRange, dir: 1 | -1): Range {
|
||||
function wholeMonths(range: Range): number {
|
||||
const after = addDays(range.end, 1);
|
||||
if (!(range.start.endsWith("-01") && after.endsWith("-01"))) {
|
||||
return 0;
|
||||
}
|
||||
const months = (value: string) =>
|
||||
Number(value.slice(0, 4)) * 12 + Number(value.slice(5, 7));
|
||||
return months(after) - months(range.start);
|
||||
}
|
||||
|
||||
function calendarShift(
|
||||
range: Range,
|
||||
view: ViewRange,
|
||||
dir: 1 | -1
|
||||
): Range | null {
|
||||
const unit = unitOf(range, view);
|
||||
if (unit) {
|
||||
const anchor = dir === 1 ? periodOf(range.start, unit).end : range.start;
|
||||
return periodOf(addDays(anchor, dir), unit);
|
||||
}
|
||||
const months = wholeMonths(range);
|
||||
if (months === 0) {
|
||||
return null;
|
||||
}
|
||||
const start = addMonths(range.start, dir * months);
|
||||
return { end: addDays(addMonths(start, months), -1), start };
|
||||
}
|
||||
|
||||
export function shiftPeriod(range: Range, view: ViewRange, dir: 1 | -1): Range {
|
||||
const calendar = calendarShift(range, view, dir);
|
||||
if (calendar) {
|
||||
return calendar;
|
||||
}
|
||||
const days = daysBetween(range.start, range.end) + 1;
|
||||
return {
|
||||
end: addDays(range.end, dir * days),
|
||||
@@ -143,6 +170,18 @@ export function shiftPeriod(range: Range, view: ViewRange, dir: 1 | -1): Range {
|
||||
};
|
||||
}
|
||||
|
||||
export function stepPeriod(range: Range, view: ViewRange, dir: 1 | -1): Range {
|
||||
const calendar = calendarShift(range, view, dir);
|
||||
if (calendar) {
|
||||
return calendar;
|
||||
}
|
||||
const unit = isDynamic(view) ? "1M" : view;
|
||||
const edge = dir === 1 ? range.end : range.start;
|
||||
const own = periodOf(edge, unit);
|
||||
const reached = (dir === 1 ? own.end : own.start) === edge;
|
||||
return reached ? periodOf(addDays(edge, dir), unit) : own;
|
||||
}
|
||||
|
||||
export function daysBetween(a: string, b: string): number {
|
||||
return Math.round((parse(b).getTime() - parse(a).getTime()) / 86_400_000);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
isDynamic,
|
||||
periodOf,
|
||||
type Range,
|
||||
shiftPeriod,
|
||||
stepPeriod,
|
||||
today,
|
||||
type ViewRange,
|
||||
} from "#lib/dates.js";
|
||||
@@ -23,7 +23,7 @@ export interface Preset {
|
||||
|
||||
function stored(): Range | null {
|
||||
try {
|
||||
const value = JSON.parse(localStorage.getItem(STORAGE_KEY) ?? "null");
|
||||
const value = JSON.parse(sessionStorage.getItem(STORAGE_KEY) ?? "null");
|
||||
return ISO_DATE.test(value?.start) && ISO_DATE.test(value?.end)
|
||||
? value
|
||||
: null;
|
||||
@@ -71,7 +71,7 @@ class Period {
|
||||
const range = rangeFromUrl(url) ?? stored() ?? periodOf(today(), view);
|
||||
this.start = range.start;
|
||||
this.end = range.end;
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(range));
|
||||
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(range));
|
||||
this.ready = true;
|
||||
}
|
||||
|
||||
@@ -97,11 +97,11 @@ class Period {
|
||||
}
|
||||
this.start = range.start;
|
||||
this.end = range.end;
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(range));
|
||||
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(range));
|
||||
}
|
||||
|
||||
shift(dir: 1 | -1) {
|
||||
this.set(shiftPeriod(this.range, this.view, dir));
|
||||
this.set(stepPeriod(this.range, this.view, dir));
|
||||
}
|
||||
|
||||
reset() {
|
||||
@@ -113,8 +113,8 @@ class Period {
|
||||
const { view } = this;
|
||||
const presets: Preset[] = [];
|
||||
if (!isDynamic(view)) {
|
||||
const prev = shiftPeriod(this.range, view, -1);
|
||||
const next = shiftPeriod(this.range, view, 1);
|
||||
const prev = stepPeriod(this.range, view, -1);
|
||||
const next = stepPeriod(this.range, view, 1);
|
||||
presets.push({ hint: "[", label: periodLabel(prev, view), range: prev });
|
||||
presets.push({ hint: "]", label: periodLabel(next, view), range: next });
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user