feat(logistics): add shipment action controls to shipment detail page
This commit is contained in:
parent
2e65ab08d8
commit
d583fe6de6
1 changed files with 113 additions and 0 deletions
113
src/components/frontend/logistics/ShipmentActions.tsx
Normal file
113
src/components/frontend/logistics/ShipmentActions.tsx
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import type { Shipment } from "@/payload-types";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { cancelShipment, toggleAutoReturn } from "@/app/(frontend)/logistics/shipments/actions";
|
||||
import { RotateCcwIcon, XIcon } from "lucide-react";
|
||||
|
||||
interface ShipmentActionsProps {
|
||||
shipment: Shipment;
|
||||
}
|
||||
|
||||
export function ShipmentActions({ shipment }: ShipmentActionsProps) {
|
||||
const router = useRouter();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [showCancelDialog, setShowCancelDialog] = useState(false);
|
||||
|
||||
const isActive =
|
||||
shipment.status === "dispatched" || shipment.status === "in_transit";
|
||||
|
||||
if (!isActive) return null;
|
||||
|
||||
async function handleCancel() {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
const result = await cancelShipment(shipment.id);
|
||||
if (result.success) {
|
||||
setShowCancelDialog(false);
|
||||
router.refresh();
|
||||
} else {
|
||||
setError(result.error ?? "Failed to cancel shipment.");
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
async function handleToggleAutoReturn() {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
const result = await toggleAutoReturn(
|
||||
shipment.id,
|
||||
!shipment.autoReturn,
|
||||
);
|
||||
if (result.success) {
|
||||
router.refresh();
|
||||
} else {
|
||||
setError(result.error ?? "Failed to toggle auto-return.");
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
{error && (
|
||||
<span className="text-xs text-red-400">{error}</span>
|
||||
)}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleToggleAutoReturn}
|
||||
disabled={loading}
|
||||
>
|
||||
<RotateCcwIcon className="size-3.5 mr-1.5" />
|
||||
{shipment.autoReturn ? "Disable" : "Enable"} Auto-Return
|
||||
</Button>
|
||||
<Dialog open={showCancelDialog} onOpenChange={setShowCancelDialog}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="destructive" size="sm" disabled={loading}>
|
||||
<XIcon className="size-3.5 mr-1.5" />
|
||||
Cancel Shipment
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Cancel Shipment</DialogTitle>
|
||||
<DialogDescription>
|
||||
Are you sure you want to cancel this shipment? All cargo will be
|
||||
returned to the origin structure and the vehicle will be parked
|
||||
at the origin.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setShowCancelDialog(false)}
|
||||
>
|
||||
Keep Shipment
|
||||
</Button>
|
||||
<Button
|
||||
variant="destructive"
|
||||
onClick={handleCancel}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? "Cancelling..." : "Cancel Shipment"}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue