updates on the datepicker on the orders page and the deliveries page
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import dayjs from 'dayjs';
|
||||
import { Ban, Bell, Bike, FileSpreadsheet, Package, PackageSearch, Truck } from 'lucide-react';
|
||||
import {
|
||||
Alert, Button, DataTable, Drawer, EmptyState, Field, IconButton, Input,
|
||||
Alert, Button, DataTable, DatePicker, Drawer, EmptyState, Field, IconButton, Input,
|
||||
PageHeader, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Modal,
|
||||
Stack, StatusBadge, Surface, Tabs, Textarea, ZoneSelector,
|
||||
} from '@/components/ds';
|
||||
@@ -62,7 +63,8 @@ const SETTABLE_STATUSES = [
|
||||
];
|
||||
|
||||
export default function Deliveries() {
|
||||
const [range, setRange] = useState({ from: '', to: '' });
|
||||
const todayStr = dayjs().format('YYYY-MM-DD');
|
||||
const [selectedDate, setSelectedDate] = useState(todayStr);
|
||||
const [tab, setTab] = useState('all');
|
||||
const [batch, setBatch] = useState('all');
|
||||
const [search, setSearch] = useState('');
|
||||
@@ -80,11 +82,17 @@ export default function Deliveries() {
|
||||
const [cancelRow, setCancelRow] = useState(null);
|
||||
const [cancelReason, setCancelReason] = useState('');
|
||||
|
||||
const dateParams = useMemo(() => {
|
||||
if (!selectedDate || selectedDate === 'all') return { from: '', to: '' };
|
||||
if (typeof selectedDate === 'string') return { from: selectedDate, to: selectedDate };
|
||||
return { from: selectedDate.from || '', to: selectedDate.to || '' };
|
||||
}, [selectedDate]);
|
||||
|
||||
const { data, isLoading, isFetching } = useDeliveries({
|
||||
page,
|
||||
pageSize: 100,
|
||||
from: range.from,
|
||||
to: range.to,
|
||||
from: dateParams.from,
|
||||
to: dateParams.to,
|
||||
});
|
||||
const { data: counts } = useDeliveryCounts();
|
||||
const { data: riders = [] } = useRiderOptions();
|
||||
@@ -195,7 +203,7 @@ export default function Deliveries() {
|
||||
means anything. */
|
||||
useEffect(() => {
|
||||
setPage(1);
|
||||
}, [tab, batch, tenantId, riderId, debouncedSearch, range.from, range.to]);
|
||||
}, [tab, batch, tenantId, riderId, debouncedSearch, dateParams.from, dateParams.to]);
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
@@ -375,30 +383,23 @@ export default function Deliveries() {
|
||||
<PageHeader
|
||||
icon={Truck}
|
||||
title="Deliveries"
|
||||
subtitle={`${counts?.total ?? 0} dispatched · ${
|
||||
!range.from && !range.to
|
||||
subtitle={`${batchRows.length} dispatched · ${
|
||||
!dateParams.from && !dateParams.to
|
||||
? 'All dates'
|
||||
: range.from === range.to
|
||||
? range.from
|
||||
: `${range.from || '…'} → ${range.to || '…'}`
|
||||
: selectedDate === todayStr
|
||||
? 'Today'
|
||||
: selectedDate === dayjs().subtract(1, 'day').format('YYYY-MM-DD')
|
||||
? 'Yesterday'
|
||||
: dateParams.from === dateParams.to
|
||||
? dayjs(dateParams.from).format('DD MMM YYYY')
|
||||
: `${dayjs(dateParams.from).format('DD MMM')} → ${dayjs(dateParams.to).format('DD MMM YYYY')}`
|
||||
}`}
|
||||
actions={
|
||||
<>
|
||||
<Input
|
||||
type="date"
|
||||
value={range.from}
|
||||
onChange={(e) => setRange((current) => ({ ...current, from: e.target.value }))}
|
||||
aria-label="From date"
|
||||
className="w-40"
|
||||
/>
|
||||
<Input
|
||||
type="date"
|
||||
value={range.to}
|
||||
onChange={(e) => setRange((current) => ({ ...current, to: e.target.value }))}
|
||||
aria-label="To date"
|
||||
className="w-40"
|
||||
/>
|
||||
</>
|
||||
<DatePicker
|
||||
value={selectedDate}
|
||||
onChange={setSelectedDate}
|
||||
allowAll
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -418,7 +419,7 @@ export default function Deliveries() {
|
||||
actions={
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => exportRows(rows, exportColumns, `deliveries-${tab}-${range.from || 'all'}`)}
|
||||
onClick={() => exportRows(rows, exportColumns, `deliveries-${tab}-${dateParams.from || 'all'}`)}
|
||||
disabled={rows.length === 0}
|
||||
>
|
||||
<FileSpreadsheet className="mr-1.5 h-4 w-4" /> Export
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||
import { motion } from 'framer-motion';
|
||||
import dayjs from 'dayjs';
|
||||
import { Ban, Bike, FileSpreadsheet, MapPin, Package, Plus, Sparkles, Truck, Upload, UserCheck } from 'lucide-react';
|
||||
import { Button, ConfirmModal, DataTable, EmptyState, Modal, PageHeader, SearchInput, Stack, StatusBadge, Tabs, ZoneSelector } from '@/components/ds';
|
||||
import { Button, ConfirmModal, DataTable, DatePicker, EmptyState, Modal, PageHeader, SearchInput, Stack, StatusBadge, Tabs, ZoneSelector } from '@/components/ds';
|
||||
import { useBulkCancelBookings, useCustomers, useRiderOptions } from '@/lib/doormileHooks';
|
||||
import { useZone } from '@/lib/ZoneContext';
|
||||
import { createAutomationDeliveries } from '@/api/doormile';
|
||||
@@ -75,6 +75,8 @@ export default function Orders() {
|
||||
const queryClient = useQueryClient();
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
const todayStr = dayjs().format('YYYY-MM-DD');
|
||||
const [selectedDate, setSelectedDate] = useState(todayStr);
|
||||
const [tab, setTab] = useState('pending');
|
||||
const [search, setSearch] = useState(searchParams.get('search') || '');
|
||||
const debouncedSearch = useDebouncedValue(search);
|
||||
@@ -115,9 +117,28 @@ export default function Orders() {
|
||||
});
|
||||
}, [bookings]);
|
||||
|
||||
const dateFilteredBookings = useMemo(() => {
|
||||
if (!selectedDate || selectedDate === 'all') return sortedBookings;
|
||||
return sortedBookings.filter((booking) => {
|
||||
const at = parseDoormileTimestamp(booking.createdat);
|
||||
if (!at.isValid()) return false;
|
||||
if (typeof selectedDate === 'string') {
|
||||
return at.format('YYYY-MM-DD') === selectedDate;
|
||||
}
|
||||
if (selectedDate.from && selectedDate.to) {
|
||||
const day = at.format('YYYY-MM-DD');
|
||||
return day >= selectedDate.from && day <= selectedDate.to;
|
||||
}
|
||||
if (selectedDate.from) {
|
||||
return at.format('YYYY-MM-DD') >= selectedDate.from;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}, [sortedBookings, selectedDate]);
|
||||
|
||||
const zoneBookings = useMemo(() => {
|
||||
return sortedBookings.filter(matchesZone);
|
||||
}, [sortedBookings, matchesZone]);
|
||||
return dateFilteredBookings.filter(matchesZone);
|
||||
}, [dateFilteredBookings, matchesZone]);
|
||||
|
||||
const customerMap = useMemo(() => {
|
||||
const map = new Map();
|
||||
@@ -158,7 +179,7 @@ export default function Orders() {
|
||||
— the assign buttons act on the selection, not on what is on screen. */
|
||||
useEffect(() => {
|
||||
setSelectedIds([]);
|
||||
}, [tab, selectedZoneId]);
|
||||
}, [tab, selectedZoneId, selectedDate]);
|
||||
|
||||
const selectedOrders = useMemo(
|
||||
() => rows.filter((row) => selectedIds.includes(row.bookingid)),
|
||||
@@ -395,6 +416,11 @@ export default function Orders() {
|
||||
</div>
|
||||
|
||||
<div className="flex min-w-0 flex-1 flex-wrap items-center justify-end gap-2 sm:flex-none">
|
||||
<DatePicker
|
||||
value={selectedDate}
|
||||
onChange={setSelectedDate}
|
||||
allowAll
|
||||
/>
|
||||
<ZoneSelector />
|
||||
<SearchInput
|
||||
value={search}
|
||||
@@ -409,7 +435,10 @@ export default function Orders() {
|
||||
)}
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => exportRows(rows, exportColumns, `orders-${tab}-${dayjs().format('YYYYMMDD')}`)}
|
||||
onClick={() => {
|
||||
const dateTag = typeof selectedDate === 'string' ? selectedDate : selectedDate?.from || 'all';
|
||||
exportRows(rows, exportColumns, `orders-${tab}-${dateTag}`);
|
||||
}}
|
||||
disabled={rows.length === 0}
|
||||
>
|
||||
<FileSpreadsheet className="mr-1.5 h-4 w-4" /> Export
|
||||
@@ -439,6 +468,11 @@ export default function Orders() {
|
||||
{rows.length === (counts[tab] ?? 0)
|
||||
? `${counts[tab] ?? 0} orders`
|
||||
: `${rows.length} of ${counts[tab] ?? 0} orders`}
|
||||
{selectedDate && selectedDate !== 'all' && (
|
||||
<span className="font-medium text-ink-2">
|
||||
{' '}· Date: {selectedDate === todayStr ? 'Today' : typeof selectedDate === 'string' ? selectedDate : `${selectedDate.from} → ${selectedDate.to}`}
|
||||
</span>
|
||||
)}
|
||||
{!isAllZones && (
|
||||
<span className="font-medium text-ink-2"> · Zone: {selectedZone.hubname}</span>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user