feat(freight-backoffice): consolidate Mantine from/to date filters into range pickers

Replaces every remaining split from/to Mantine DateInput/DatePickerInput pair
with a single DatePickerInput type="range", sharing one preset list (Today,
Last 7/30 days, this/last month, YTD) via getDateRangePresets(). Covers
ListControls (18 consumers), FleetResourcePage, ContractRequestsPage,
BookingRequestsPage (created + scheduled ranges), WagonCancellationsPage,
BatchBoardPage, ClearanceDocumentsPage, ShipmentRequestsPage.

Native Mantine range picker, not the shadcn DateRangePicker, to match each
page's existing design system instead of clashing with it.

Reports date-range filter (ReportFilters.tsx) intentionally left untouched.
This commit is contained in:
Nathnael
2026-08-13 08:45:29 +00:00
parent efc5a24380
commit 58b47318e9
9 changed files with 146 additions and 176 deletions

View File

@@ -2,6 +2,7 @@ import { Button, Group, TextInput } from "@mantine/core";
import { DatePickerInput } from "@mantine/dates";
import { Search, X } from "lucide-react";
import type { ReactNode } from "react";
import { getDateRangePresets } from "./dateRangePresets";
export interface ListControlsProps {
search: string;
@@ -54,28 +55,19 @@ const ListControls = ({
)}
{showDateRange && (
<>
<DatePickerInput
label={dateLabel ? `${dateLabel} from` : "From"}
placeholder="Any"
value={dateFrom}
onChange={onDateFromChange}
// Cannot start after it ends — the picker refuses the invalid range
// instead of silently returning nothing.
maxDate={dateTo ?? undefined}
clearable
w={150}
/>
<DatePickerInput
label={dateLabel ? `${dateLabel} to` : "To"}
placeholder="Any"
value={dateTo}
onChange={onDateToChange}
minDate={dateFrom ?? undefined}
clearable
w={150}
/>
</>
<DatePickerInput
type="range"
label={dateLabel ?? "Date range"}
placeholder="Any"
value={[dateFrom, dateTo]}
onChange={([from, to]) => {
onDateFromChange(from);
onDateToChange(to);
}}
presets={getDateRangePresets()}
clearable
w={230}
/>
)}
{children}

View File

@@ -0,0 +1,41 @@
import {
format,
startOfDay,
endOfDay,
startOfMonth,
endOfMonth,
startOfYear,
subDays,
subMonths,
} from "date-fns";
import type { DatePickerPreset } from "@mantine/dates";
const iso = (date: Date) => format(date, "yyyy-MM-dd");
/**
* Shared "Today / Last 7 days / …" presets for every Mantine
* `<DatePickerInput type="range" presets={getDateRangePresets()} />` in the app,
* so every from/to filter offers the same shortcuts. Computed fresh per call
* (not a module-level constant) so "Today" stays today.
*/
export function getDateRangePresets(): DatePickerPreset<"range">[] {
const today = new Date();
return [
{ label: "Today", value: [iso(startOfDay(today)), iso(endOfDay(today))] },
{
label: "Yesterday",
value: [iso(startOfDay(subDays(today, 1))), iso(endOfDay(subDays(today, 1)))],
},
{ label: "Last 7 days", value: [iso(startOfDay(subDays(today, 6))), iso(endOfDay(today))] },
{ label: "Last 30 days", value: [iso(startOfDay(subDays(today, 29))), iso(endOfDay(today))] },
{ label: "This month", value: [iso(startOfMonth(today)), iso(endOfDay(today))] },
{
label: "Last month",
value: [
iso(startOfMonth(subMonths(today, 1))),
iso(endOfMonth(subMonths(today, 1))),
],
},
{ label: "Year to date", value: [iso(startOfYear(today)), iso(endOfDay(today))] },
];
}