diff --git a/apps/edr-freight-web/backoffice/src/pages/operations/LastMilePage.tsx b/apps/edr-freight-web/backoffice/src/pages/operations/LastMilePage.tsx
index e879685be..075d73705 100644
--- a/apps/edr-freight-web/backoffice/src/pages/operations/LastMilePage.tsx
+++ b/apps/edr-freight-web/backoffice/src/pages/operations/LastMilePage.tsx
@@ -1,15 +1,19 @@
import { useMemo, useState } from "react";
-import { Truck } from "lucide-react";
+import { Eye, MoreHorizontal, RefreshCw, Truck } from "lucide-react";
import type { ColumnDef } from "@edr/ui-common";
import { DataTable, DataTableFooter, usePagination } from "@edr/ui-common";
import {
+ ActionIcon,
Badge,
Box,
Button,
Card,
+ Divider,
Group,
+ Menu,
Modal,
Select,
+ SimpleGrid,
Stack,
Text,
TextInput,
@@ -28,6 +32,13 @@ interface LastMileJob {
cargo: string;
status: LastMileStatus;
assignedVehicle: string | null;
+ // Booking info shown in the Assign / View Detail modals.
+ serviceType: string;
+ weight: string;
+ originYard: string;
+ contactName: string;
+ contactPhone: string;
+ requestedDate: string;
}
// Placeholder data — replace with a real last-mile service once the API exists.
@@ -40,6 +51,12 @@ const PLACEHOLDER_JOBS: LastMileJob[] = [
cargo: "20ft container · Electronics",
status: "UNASSIGNED",
assignedVehicle: null,
+ serviceType: "Door-to-door (Last Mile)",
+ weight: "12.4 t",
+ originYard: "Indode Dry Port",
+ contactName: "Selam Bekele",
+ contactPhone: "+251 911 234 567",
+ requestedDate: "2026-06-22",
},
{
id: "2",
@@ -49,6 +66,12 @@ const PLACEHOLDER_JOBS: LastMileJob[] = [
cargo: "Bulk · 18t Cement",
status: "ASSIGNED",
assignedVehicle: "Isuzu FVR (3-AA-45821)",
+ serviceType: "Terminal-to-door (Last Mile)",
+ weight: "18.0 t",
+ originYard: "Dire Dawa Terminal",
+ contactName: "Yonas Tadesse",
+ contactPhone: "+251 912 887 010",
+ requestedDate: "2026-06-21",
},
{
id: "3",
@@ -58,6 +81,12 @@ const PLACEHOLDER_JOBS: LastMileJob[] = [
cargo: "40ft container · Machinery",
status: "UNASSIGNED",
assignedVehicle: null,
+ serviceType: "Door-to-door (Last Mile)",
+ weight: "24.7 t",
+ originYard: "Mojo Dry Port",
+ contactName: "Hanna Girma",
+ contactPhone: "+251 913 445 221",
+ requestedDate: "2026-06-23",
},
];
@@ -68,6 +97,44 @@ const VEHICLE_OPTIONS = [
{ value: "mercedes-actros-90113", label: "Mercedes Actros (3-AA-90113)" },
];
+const InfoRow = ({ label, value }: { label: string; value: string }) => (
+
+
+ {label}
+
+ {value}
+
+);
+
+const BookingInfo = ({ job }: { job: LastMileJob }) => (
+
+
+
+ {job.bookingRef}
+
+ {job.status === "ASSIGNED" ? "Assigned" : "Unassigned"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
const LastMilePage = () => {
const { toast } = useToast();
const { pagination, setPagination } = usePagination({ pageSize: 10 });
@@ -76,9 +143,15 @@ const LastMilePage = () => {
const [search, setSearch] = useState("");
const [assignOpen, setAssignOpen] = useState(false);
+ const [detailOpen, setDetailOpen] = useState(false);
const [activeJobId, setActiveJobId] = useState(null);
const [vehicleValue, setVehicleValue] = useState(null);
+ const activeJob = useMemo(
+ () => jobs.find((job) => job.id === activeJobId) ?? null,
+ [jobs, activeJobId],
+ );
+
const filteredJobs = useMemo(() => {
const term = search.trim().toLowerCase();
if (!term) return jobs;
@@ -97,17 +170,28 @@ const LastMilePage = () => {
}, [filteredJobs, pagination.pageIndex, pagination.pageSize]);
const openAssign = (jobId: string | null) => {
- setActiveJobId(jobId);
+ const resolved = jobId ?? filteredJobs.find((job) => job.status === "UNASSIGNED")?.id ?? null;
+ setActiveJobId(resolved);
setVehicleValue(null);
setAssignOpen(true);
};
+ const openDetail = (jobId: string) => {
+ setActiveJobId(jobId);
+ setDetailOpen(true);
+ };
+
const closeAssign = () => {
setAssignOpen(false);
setActiveJobId(null);
setVehicleValue(null);
};
+ const closeDetail = () => {
+ setDetailOpen(false);
+ setActiveJobId(null);
+ };
+
const handleAssign = () => {
const jobId = activeJobId ?? filteredJobs.find((job) => job.status === "UNASSIGNED")?.id;
if (!jobId || !vehicleValue) {
@@ -191,18 +275,43 @@ const LastMilePage = () => {
id: "actions",
header: "Actions",
meta: { headerClassName, cellClassName: `${cellClassName} whitespace-nowrap` },
- cell: ({ row }) => (
-
- }
- onClick={() => openAssign(row.original.id)}
- >
- {row.original.status === "ASSIGNED" ? "Reassign" : "Assign"}
-
-
- ),
+ cell: ({ row }) => {
+ const isAssigned = row.original.status === "ASSIGNED";
+ return (
+
+
+
+ );
+ },
},
];
}, []);
@@ -268,10 +377,19 @@ const LastMilePage = () => {
opened={assignOpen}
onClose={closeAssign}
title={Assign Vehicle}
+ size="lg"
radius="lg"
centered
>
+ {activeJob ? (
+
+ ) : (
+
+ No unassigned deliveries available.
+
+ )}
+
+
+
+ Delivery Detail}
+ size="lg"
+ radius="lg"
+ centered
+ >
+
+ {activeJob && }
+
+