mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 04:48:18 +00:00
feat(freight-backoffice): add DateRangePicker, replace ad-hoc from/to date filters
Adds a shadcn Popover+Calendar range picker with presets (Today, Last 7/30 days, this/last month, YTD) and Apply/Cancel. Swaps it into every shadcn-family from-to date filter: activity log, sector reports, incoming records (EN branch), CombinedFilterBar (13 consumers), user records, audit log — also fixes an uncontrolled-input bug on the audit log date fields. Mantine-based ListControls/ReportFilters left untouched (different UI kit).
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/shared/common/ui/select";
|
||||
import { DateRangePicker, parseDay, formatDay } from "@/shared/common/ui/date-range-picker";
|
||||
|
||||
export interface ReportFilterOption {
|
||||
id: string;
|
||||
@@ -167,33 +168,18 @@ export function SectorReportFilters({
|
||||
</Select>
|
||||
</label>
|
||||
|
||||
<label className="space-y-1.5 text-xs font-medium">
|
||||
<label className="space-y-1.5 text-xs font-medium sm:col-span-2">
|
||||
<span className="flex items-center gap-2">
|
||||
<CalendarDays className="size-4 text-primary" />
|
||||
From date
|
||||
Date range
|
||||
</span>
|
||||
<input
|
||||
type="date"
|
||||
value={fromDate}
|
||||
max={toDate || undefined}
|
||||
<DateRangePicker
|
||||
value={{ from: parseDay(fromDate), to: parseDay(toDate) }}
|
||||
onChange={(range) => {
|
||||
onFromDateChange(formatDay(range.from));
|
||||
onToDateChange(formatDay(range.to));
|
||||
}}
|
||||
disabled={!unitId || loading}
|
||||
onChange={(event) => onFromDateChange(event.target.value)}
|
||||
className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label className="space-y-1.5 text-xs font-medium">
|
||||
<span className="flex items-center gap-2">
|
||||
<CalendarDays className="size-4 text-primary" />
|
||||
To date
|
||||
</span>
|
||||
<input
|
||||
type="date"
|
||||
value={toDate}
|
||||
min={fromDate || undefined}
|
||||
disabled={!unitId || loading}
|
||||
onChange={(event) => onToDateChange(event.target.value)}
|
||||
className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
|
||||
/>
|
||||
</label>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState, useEffect, useMemo, useCallback } from "react";
|
||||
import { DataTable } from "@/record-management/common/DataTable";
|
||||
import { Button } from "@/shared/common/ui/button";
|
||||
import { Input } from "@/shared/common/ui/input";
|
||||
import { DateRangePicker, parseDay, formatDay } from "@/shared/common/ui/date-range-picker";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -383,23 +384,13 @@ const ExternalIncomingRecords = () => {
|
||||
) : (
|
||||
<div className="flex flex-col sm:flex-row gap-2">
|
||||
{lang.startsWith("en") ? (
|
||||
<>
|
||||
<label className="mt-2">From: </label>
|
||||
<Input
|
||||
type="date"
|
||||
value={fromDispatchedDate}
|
||||
onChange={(e) => setFromDispatchedDate(e.target.value)}
|
||||
className="w-[150px]"
|
||||
/>
|
||||
<label className="mt-2">To: </label>
|
||||
<Input
|
||||
type="date"
|
||||
value={toDispatchedDate}
|
||||
onChange={(e) => setToDispatchedDate(e.target.value)}
|
||||
min={fromDispatchedDate}
|
||||
className="w-[150px]"
|
||||
/>
|
||||
</>
|
||||
<DateRangePicker
|
||||
value={{ from: parseDay(fromDispatchedDate), to: parseDay(toDispatchedDate) }}
|
||||
onChange={(range) => {
|
||||
setFromDispatchedDate(formatDay(range.from));
|
||||
setToDispatchedDate(formatDay(range.to));
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
{/* From Date */}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState, useEffect, useMemo, useCallback } from "react";
|
||||
import { DataTable } from "@/record-management/common/DataTable";
|
||||
import { Button } from "@/shared/common/ui/button";
|
||||
import { Input } from "@/shared/common/ui/input";
|
||||
import { DateRangePicker, parseDay, formatDay } from "@/shared/common/ui/date-range-picker";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -326,23 +327,13 @@ const InternalIncomingRecordsV2 = () => {
|
||||
) : (
|
||||
<div className="flex flex-col sm:flex-row gap-2">
|
||||
{lang.startsWith("en") ? (
|
||||
<>
|
||||
<label className="mt-2">From: </label>
|
||||
<Input
|
||||
type="date"
|
||||
value={fromDispatchedDate}
|
||||
onChange={(e) => setFromDispatchedDate(e.target.value)}
|
||||
className="w-[150px]"
|
||||
/>
|
||||
<label className="mt-2">To: </label>
|
||||
<Input
|
||||
type="date"
|
||||
value={toDispatchedDate}
|
||||
onChange={(e) => setToDispatchedDate(e.target.value)}
|
||||
min={fromDispatchedDate}
|
||||
className="w-[150px]"
|
||||
/>
|
||||
</>
|
||||
<DateRangePicker
|
||||
value={{ from: parseDay(fromDispatchedDate), to: parseDay(toDispatchedDate) }}
|
||||
onChange={(range) => {
|
||||
setFromDispatchedDate(formatDay(range.from));
|
||||
setToDispatchedDate(formatDay(range.to));
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
{/* From Date */}
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
} from "@/shared/common/ui/select";
|
||||
import { Input } from "@/shared/common/ui/input";
|
||||
import { Button } from "@/shared/common/ui/button";
|
||||
import { DateRangePicker, parseDay, formatDay } from "@/shared/common/ui/date-range-picker";
|
||||
import { Badge } from "@/shared/common/ui/badge";
|
||||
import { AdvancedTable } from "@/shared/common/ui/table/AdvancedTable";
|
||||
import { useLocalizedName } from "@/shared/common/localizedName";
|
||||
@@ -521,29 +522,13 @@ const UserRecords = () => {
|
||||
{selectedFilter?.type === "dateRange" ? (
|
||||
<div className="flex flex-col sm:flex-row gap-2">
|
||||
{lang.startsWith("en") ? (
|
||||
<>
|
||||
<label className="mt-2">From: </label>
|
||||
<Input
|
||||
type="date"
|
||||
value={fromDate}
|
||||
onChange={(e) => setFromDate(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") handleAddFilter();
|
||||
}}
|
||||
className="w-[150px]"
|
||||
/>
|
||||
<label className="mt-2">To: </label>
|
||||
<Input
|
||||
type="date"
|
||||
value={toDate}
|
||||
onChange={(e) => setToDate(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") handleAddFilter();
|
||||
}}
|
||||
min={fromDate}
|
||||
className="w-[150px]"
|
||||
/>
|
||||
</>
|
||||
<DateRangePicker
|
||||
value={{ from: parseDay(fromDate), to: parseDay(toDate) }}
|
||||
onChange={(range) => {
|
||||
setFromDate(formatDay(range.from));
|
||||
setToDate(formatDay(range.to));
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<div className="relative">
|
||||
|
||||
Reference in New Issue
Block a user