Files
pleno-vue/src/views/dashboards/superUserDashboard/InvoicingBillingPeriod/views/InvoicingBillingPeriodViewSelfWash.vue
T
Jeppe B 7817f0c13b 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
2026-08-16 13:00:17 +02:00

103 lines
3.5 KiB
Vue

<script setup lang="ts">
import XLVaskUsagePagination from "@/components/displays/pagination/models/DepartmentPos/XLVaskUsagePagination.vue";
import { dates } from "@/views/dashboards/superUserDashboard/InvoicingBillingPeriod/imports/InvoicingBillingPeriodImportDates.vue";
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) => {
const rawValue = Array.isArray(value) ? String(value[0] ?? "") : String(value ?? "");
const match = DATE_ONLY_PATTERN.exec(rawValue.trim());
if (!match) {
return "";
}
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);
return Number.isInteger(parsedId) && parsedId > 0 ? parsedId : 0;
});
const flaggedWashStartDate = computed(() => parseRouteDateOnly(route.query.xlvaskUsageLogStartTime));
/**
* 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>
<template>
<section data-testid="invoicing-period-self-wash-view">
<XLVaskUsagePagination
:title="selfWashTitle"
:initial-date-from="initialDateFrom"
:initial-date-to="initialDateTo"
:inherit-period-filters="true"
:load-all-at-once="false"
:highlight-usage-log-id="highlightedUsageLogId"
/>
</section>
</template>