fix(pleno-vue): widen flagged-wash date window to ±7d (TRU-10) (#315)
Closes the user-reported symptom where washes spanning midnight fell outside the visible date window when navigating from an invoice-period flag. Changes: - Add FLAGGED_WASH_DATE_WINDOW_DAYS = 7 constant - Add shiftDateOnly() helper that pads an ISO-8601 date by ±N days (UTC math, no DST drift) - initialDateFrom/initialDateTo now compute [start - 7d, start + 7d] when a flagged wash is in the route - Add vitest source assertion to lock the new behavior Test result: 68/68 vitest passed (was 67, +1 new test) Refs TRU-10
This commit is contained in:
+60
-2
@@ -5,6 +5,20 @@ import { computed } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import i18n from "@/i18n";
|
||||
|
||||
/**
|
||||
* Number of days to widen the date window on either side of a flagged
|
||||
* wash's `start_time` when navigating to the Selvvask view from a
|
||||
* flag-link in the invoice period review.
|
||||
*
|
||||
* The single-day window shipped in #304 was sufficient when the wash
|
||||
* always landed on the same calendar day, but real-world data shows
|
||||
* washes that "span midnight" (e.g. a wash at 23:50 visible at 00:10)
|
||||
* would fall outside the visible range. Widening to ±7 days makes
|
||||
* the highlighted wash always visible regardless of which side of
|
||||
* midnight it lands on.
|
||||
*/
|
||||
const FLAGGED_WASH_DATE_WINDOW_DAYS = 7;
|
||||
|
||||
const DATE_ONLY_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
||||
|
||||
const parseRouteDateOnly = (value: any) => {
|
||||
@@ -16,6 +30,33 @@ const parseRouteDateOnly = (value: any) => {
|
||||
return `${match[1]}-${match[2]}-${match[3]}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Pad an ISO-8601 date string (`YYYY-MM-DD`) by `±days` and return a
|
||||
* new `YYYY-MM-DD` string. Invalid inputs return "".
|
||||
*/
|
||||
const shiftDateOnly = (dateOnly: string, days: number): string => {
|
||||
if (dateOnly === "") {
|
||||
return "";
|
||||
}
|
||||
const match = DATE_ONLY_PATTERN.exec(dateOnly);
|
||||
if (!match) {
|
||||
return "";
|
||||
}
|
||||
const utc = Date.UTC(
|
||||
Number.parseInt(match[1], 10),
|
||||
Number.parseInt(match[2], 10) - 1,
|
||||
Number.parseInt(match[3], 10),
|
||||
);
|
||||
const shifted = new Date(utc + days * 24 * 60 * 60 * 1000);
|
||||
if (Number.isNaN(shifted.getTime())) {
|
||||
return "";
|
||||
}
|
||||
const yyyy = shifted.getUTCFullYear();
|
||||
const mm = String(shifted.getUTCMonth() + 1).padStart(2, "0");
|
||||
const dd = String(shifted.getUTCDate()).padStart(2, "0");
|
||||
return `${yyyy}-${mm}-${dd}`;
|
||||
};
|
||||
|
||||
const route = useRoute();
|
||||
const highlightedUsageLogId = computed(() => {
|
||||
const parsedId = Number.parseInt(String(route.query.xlvaskUsageLogId || ""), 10);
|
||||
@@ -24,8 +65,25 @@ const highlightedUsageLogId = computed(() => {
|
||||
|
||||
const flaggedWashStartDate = computed(() => parseRouteDateOnly(route.query.xlvaskUsageLogStartTime));
|
||||
|
||||
const initialDateFrom = computed(() => flaggedWashStartDate.value || dates.computed.formattedStartDate.value);
|
||||
const initialDateTo = computed(() => flaggedWashStartDate.value || dates.computed.formattedEndDate.value);
|
||||
/**
|
||||
* Date window for the Selvvask view:
|
||||
* - If a flagged wash start time is in the route, open a ±7d window
|
||||
* around it so the highlighted wash is always visible.
|
||||
* - Otherwise fall back to the current period date range.
|
||||
*/
|
||||
const initialDateFrom = computed(() => {
|
||||
if (flaggedWashStartDate.value) {
|
||||
return shiftDateOnly(flaggedWashStartDate.value, -FLAGGED_WASH_DATE_WINDOW_DAYS);
|
||||
}
|
||||
return dates.computed.formattedStartDate.value;
|
||||
});
|
||||
|
||||
const initialDateTo = computed(() => {
|
||||
if (flaggedWashStartDate.value) {
|
||||
return shiftDateOnly(flaggedWashStartDate.value, FLAGGED_WASH_DATE_WINDOW_DAYS);
|
||||
}
|
||||
return dates.computed.formattedEndDate.value;
|
||||
});
|
||||
|
||||
const selfWashTitle = computed(() => i18n.global.t("nav.self_wash"));
|
||||
</script>
|
||||
|
||||
@@ -600,6 +600,21 @@ describe("Periode tab contract", () => {
|
||||
expect(xlvaskUsagePaginationSource).toContain("buildUsagePaginationParams()");
|
||||
});
|
||||
|
||||
it("widens the date window around a flagged wash start time to ±7 days (TRU-10)", () => {
|
||||
// The original spec called for a [start_time - 7d, start_time + 7d] window
|
||||
// so the highlighted wash is always visible even when it spans midnight
|
||||
// or falls on the edge of the calendar day.
|
||||
expect(periodViewSelfWashSource).toContain("FLAGGED_WASH_DATE_WINDOW_DAYS");
|
||||
expect(periodViewSelfWashSource).toContain("FLAGGED_WASH_DATE_WINDOW_DAYS = 7");
|
||||
expect(periodViewSelfWashSource).toContain("const shiftDateOnly");
|
||||
expect(periodViewSelfWashSource).toContain(
|
||||
"shiftDateOnly(flaggedWashStartDate.value, -FLAGGED_WASH_DATE_WINDOW_DAYS)"
|
||||
);
|
||||
expect(periodViewSelfWashSource).toContain(
|
||||
"shiftDateOnly(flaggedWashStartDate.value, FLAGGED_WASH_DATE_WINDOW_DAYS)"
|
||||
);
|
||||
});
|
||||
|
||||
it("loads Selvvask selector counts and progress from the selected period", () => {
|
||||
expect(periodRightSource).toContain("normalizeXlvaskAutopilotSummary");
|
||||
expect(periodRightSource).toContain("const selfWashCounts = ref(emptySelectorCounts())");
|
||||
|
||||
Reference in New Issue
Block a user