feat: default journal period to last 7 days
Frontend verify / commits (pull_request) Successful in 50s
Frontend verify / security (pull_request) Failing after 13s
Frontend verify / verify (pull_request) Skipped

This commit is contained in:
2026-10-06 22:05:41 +03:00
parent c25f6bd85b
commit 0ea8d7b62d
11 changed files with 121 additions and 34 deletions
+15 -1
View File
@@ -1,6 +1,11 @@
import { describe, expect, it } from "vitest";
import { compareDateDesc, isValidPeriod, moscowDate } from "./calendar";
import {
compareDateDesc,
defaultPeriod,
isValidPeriod,
moscowDate,
} from "./calendar";
import { calendarDate } from "./calendar.schema";
describe("calendar dates", () => {
@@ -33,6 +38,15 @@ describe("calendar dates", () => {
expect(moscowDate(new Date("2026-12-31T21:00:00Z"))).toBe("2027-01-01");
});
it("defaults to the last 7 days including today", () => {
const [from, to] = defaultPeriod();
expect(calendarDate.safeParse(from).success).toBe(true);
expect(to).toBe(moscowDate(new Date()));
expect((Date.parse(to) - Date.parse(from)) / 86_400_000).toBe(6);
expect(from <= to).toBe(true);
});
it("compares dates newest first and keeps dateless rows last", () => {
const dates = [null, "2026-01-01", "2026-03-01", "2026-02-01"];
+12 -1
View File
@@ -9,6 +9,9 @@ function isValidPeriod(from: null | string, to: null | string) {
);
}
const DAY_MS = 86_400_000;
const DEFAULT_PERIOD_DAYS = 6;
const moscowFormatter = new Intl.DateTimeFormat("en-CA", {
day: "2-digit",
month: "2-digit",
@@ -22,6 +25,14 @@ function compareDateDesc(a: null | string, b: null | string) {
return (b ?? "").localeCompare(a ?? "");
}
// Last 7 days including today. An empty period always means this range.
function defaultPeriod(): [string, string] {
const to = new Date();
const from = new Date(to.getTime() - DEFAULT_PERIOD_DAYS * DAY_MS);
return [moscowDate(from), moscowDate(to)];
}
function moscowDate(value: Date): string {
const parts = moscowFormatter.formatToParts(value);
@@ -31,4 +42,4 @@ function moscowDate(value: Date): string {
return `${part("year")}-${part("month")}-${part("day")}`;
}
export { compareDateDesc, isValidPeriod, moscowDate };
export { compareDateDesc, defaultPeriod, isValidPeriod, moscowDate };
+1 -1
View File
@@ -1,4 +1,4 @@
export { compareDateDesc, isValidPeriod, moscowDate } from "./calendar";
export { compareDateDesc, defaultPeriod, isValidPeriod, moscowDate } from "./calendar";
export { calendarDate } from "./calendar.schema";
export {
formatChartValue,
+13 -4
View File
@@ -1,13 +1,22 @@
import { useEffect } from "react";
import { useEffect, useState } from "react";
import { useSearchParams } from "react-router";
import { isValidPeriod } from "./calendar";
import { defaultPeriod, isValidPeriod } from "./calendar";
function useUrlPeriod() {
const [parameters, setParameters] = useSearchParams();
const from = parameters.get("from");
const to = parameters.get("to");
const isValid = isValidPeriod(from, to);
const hasPeriod = from !== null || to !== null;
const [[defaultFrom, defaultTo]] = useState<[string, string]>(defaultPeriod);
const resolve = (value: null | string, fallback: string) => {
if (!isValid) return null;
return hasPeriod ? value : fallback;
};
useEffect(() => {
if (isValid || (!parameters.has("from") && !parameters.has("to"))) return;
const normalized = new URLSearchParams(parameters);
@@ -17,10 +26,10 @@ function useUrlPeriod() {
}, [isValid, parameters, setParameters]);
return {
from: isValid ? from : null,
from: resolve(from, defaultFrom),
parameters,
setParameters,
to: isValid ? to : null,
to: resolve(to, defaultTo),
};
}