updates on the reverse logistics
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import dayjs from 'dayjs';
|
||||
import { Ban, Bell, Bike, Clock, FileSpreadsheet, PackageSearch, Truck } from 'lucide-react';
|
||||
import { Ban, Bell, Bike, Clock, FileSpreadsheet, PackageCheck, PackageSearch, RotateCcw, Truck, Undo2 } from 'lucide-react';
|
||||
import {
|
||||
Alert, Button, DataTable, DatePicker, Drawer, EmptyState, Field, IconButton, SearchInput, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Modal,
|
||||
Stack, StatusBadge, Surface, Tabs, Textarea, ZoneSelector,
|
||||
@@ -17,6 +17,8 @@ import { currency, exportRows, km as formatKm, matchesQuery, orDash, useDebounce
|
||||
import { toDateRange } from '@/lib/dateRange';
|
||||
import { pickupSourceTypeLabel } from '@/lib/orderFlow';
|
||||
import { summariseRouting } from '@/lib/routingSummary';
|
||||
import { useAuth } from '@/lib/AuthContext';
|
||||
import { ResolveRtoModal, StartRtoModal, rtoActionsFor } from '@/components/doormile/RtoDialogs';
|
||||
|
||||
/**
|
||||
* Deliveries — orders that have moved past merely being created.
|
||||
@@ -45,6 +47,9 @@ const STATUS_TABS = [
|
||||
{ value: 'skipped', label: 'Skipped', countKey: 'skippedLength' },
|
||||
{ value: 'delivered', label: 'Delivered', countKey: 'coveredLength' },
|
||||
{ value: 'cancelled', label: 'Cancelled', countKey: 'cancelLength' },
|
||||
// Reverse logistics: parcels going back to the sender, and those back.
|
||||
{ value: 'rto', label: 'In return', countKey: 'rtoLength' },
|
||||
{ value: 'returned', label: 'Returned', countKey: 'returnedLength' },
|
||||
];
|
||||
|
||||
const KNOWN_STATUSES = STATUS_TABS.map((tab) => tab.value).concat('canceled');
|
||||
@@ -89,6 +94,11 @@ export default function Deliveries() {
|
||||
const [nextStatus, setNextStatus] = useState('delivered');
|
||||
const [cancelRow, setCancelRow] = useState(null);
|
||||
const [cancelReason, setCancelReason] = useState('');
|
||||
// Reverse logistics. Starting/closing a return is a Doormile-staff action;
|
||||
// a client login sees the statuses but no buttons (the server refuses too).
|
||||
const { isClient } = useAuth();
|
||||
const [rtoRow, setRtoRow] = useState(null);
|
||||
const [resolveRto, setResolveRto] = useState({ row: null, mode: 'cancel' });
|
||||
|
||||
const dateParams = useMemo(() => toDateRange(selectedDate), [selectedDate]);
|
||||
|
||||
@@ -309,7 +319,7 @@ export default function Deliveries() {
|
||||
key: 'actions',
|
||||
header: 'Actions',
|
||||
align: 'right',
|
||||
width: '130px',
|
||||
width: '170px',
|
||||
cell: (row) => (
|
||||
<div className="flex justify-end gap-1">
|
||||
<IconButton
|
||||
@@ -320,7 +330,10 @@ export default function Deliveries() {
|
||||
onClick={() => setDetailRow(row)}
|
||||
/>
|
||||
|
||||
{row.orderstatus !== 'delivered' && row.milerprofileid ? (
|
||||
{/* Not on parcels in or through a return: the generic "process
|
||||
deliveries" text is wrong for them, and starting a return
|
||||
already pushes the rider a return-specific message. */}
|
||||
{!['delivered', 'rto', 'returned'].includes(String(row.orderstatus || '').toLowerCase()) && row.milerprofileid ? (
|
||||
<IconButton
|
||||
label="Notify rider"
|
||||
icon={Bell}
|
||||
@@ -349,18 +362,51 @@ export default function Deliveries() {
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<IconButton
|
||||
label="Update status"
|
||||
icon={Truck}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setStatusRow(row);
|
||||
setNextStatus('delivered');
|
||||
}}
|
||||
/>
|
||||
{!isClient && rtoActionsFor(row).canStart ? (
|
||||
<IconButton
|
||||
label="Return to sender"
|
||||
icon={Undo2}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setRtoRow(row)}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{!['delivered', 'cancelled', 'canceled'].includes(String(row.orderstatus || '').toLowerCase()) ? (
|
||||
{!isClient && rtoActionsFor(row).canResolve ? (
|
||||
<>
|
||||
<IconButton
|
||||
label="Re-attempt delivery"
|
||||
icon={RotateCcw}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setResolveRto({ row, mode: 'cancel' })}
|
||||
/>
|
||||
<IconButton
|
||||
label="Mark returned"
|
||||
icon={PackageCheck}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setResolveRto({ row, mode: 'complete' })}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
{/* A parcel in or through a return is moved only by the return
|
||||
actions above — the server refuses a plain status change. */}
|
||||
{!['rto', 'returned'].includes(String(row.orderstatus || '').toLowerCase()) ? (
|
||||
<IconButton
|
||||
label="Update status"
|
||||
icon={Truck}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setStatusRow(row);
|
||||
setNextStatus('delivered');
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{!['delivered', 'cancelled', 'canceled', 'rto', 'returned'].includes(String(row.orderstatus || '').toLowerCase()) ? (
|
||||
<IconButton
|
||||
label="Cancel delivery"
|
||||
icon={Ban}
|
||||
@@ -376,7 +422,7 @@ export default function Deliveries() {
|
||||
),
|
||||
},
|
||||
],
|
||||
[notifyMiler]
|
||||
[notifyMiler, isClient]
|
||||
);
|
||||
|
||||
const exportColumns = [
|
||||
@@ -697,6 +743,13 @@ export default function Deliveries() {
|
||||
</Field>
|
||||
</Modal>
|
||||
|
||||
<StartRtoModal row={rtoRow} onClose={() => setRtoRow(null)} />
|
||||
<ResolveRtoModal
|
||||
row={resolveRto.row}
|
||||
mode={resolveRto.mode}
|
||||
onClose={() => setResolveRto({ row: null, mode: 'cancel' })}
|
||||
/>
|
||||
|
||||
<OrderDetailDrawer row={detailRow} onClose={() => setDetailRow(null)} />
|
||||
</Stack>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user