diff --git a/frontend/src/pages/BookingDetail.tsx b/frontend/src/pages/BookingDetail.tsx
index 0c29cf0..4303610 100644
--- a/frontend/src/pages/BookingDetail.tsx
+++ b/frontend/src/pages/BookingDetail.tsx
@@ -4,6 +4,8 @@ import { api } from "../api/client";
import type { Booking, RegisterReturnResult } from "../api/types";
import { StatusBadge } from "../components/Badge";
import { ReturnForm, ReturnResultPanel } from "../components/ReturnForm";
+import { Icon } from "../components/Icons";
+import { ErrorState, LoadingState, PageHeader } from "../components/PageChrome";
export function BookingDetail() {
const { publicRef } = useParams<{ publicRef: string }>();
@@ -31,15 +33,14 @@ export function BookingDetail() {
load();
}
- if (error) return
{error}
;
- if (!booking) return Loading booking…
;
+ if (error) return ;
+ if (!booking) return ;
return (
-
← Back to bookings
-
{booking.public_ref}
-
-
+ Booking ledger
+ } />
+
- Customer
- {booking.customer_name} ({booking.customer_ref})
- Vehicle
- {booking.vehicle_ref}
- Starts
- {new Date(booking.starts_at).toLocaleString("en-GB", { timeZone: "Europe/Brussels" })}
@@ -47,7 +48,7 @@ export function BookingDetail() {
- Start odometer
- {booking.start_odometer_km ?? "—"} km
- End odometer
- {booking.end_odometer_km ?? "—"} km
- Requirements complete
- {booking.requirements_complete ? "Yes" : "No"}
-
+
{returnResult &&
}
{!returnResult && booking.status === "active" && (
diff --git a/frontend/src/pages/Bookings.tsx b/frontend/src/pages/Bookings.tsx
index b2fe9b2..ac02d2a 100644
--- a/frontend/src/pages/Bookings.tsx
+++ b/frontend/src/pages/Bookings.tsx
@@ -3,6 +3,7 @@ import { Link } from "react-router-dom";
import { api } from "../api/client";
import type { Booking } from "../api/types";
import { StatusBadge } from "../components/Badge";
+import { EmptyState, ErrorState, LoadingState, PageHeader } from "../components/PageChrome";
const STATUS_OPTIONS = ["reserved", "active", "returned", "cancelled", "blocked"];
@@ -10,8 +11,13 @@ export function Bookings() {
const [bookings, setBookings] = useState
(null);
const [error, setError] = useState(null);
const [status, setStatus] = useState("");
+ const [query, setQuery] = useState("");
+ const [page, setPage] = useState(1);
+ const perPage = 25;
useEffect(() => {
+ setBookings(null);
+ setError(null);
const params = new URLSearchParams();
if (status) params.set("status", status);
api
@@ -22,12 +28,16 @@ export function Bookings() {
return (
-
Bookings
+
- {error &&
{error}
}
- {!error && !bookings &&
Loading bookings…
}
- {bookings && bookings.length === 0 &&
No bookings match these filters.
}
+ {error &&
}
+ {!error && !bookings &&
}
+ {bookings && bookings.length === 0 &&
}
- {bookings && bookings.length > 0 && (
-
+ {bookings && bookings.length > 0 && (() => {
+ const filtered = bookings.filter((b) => `${b.public_ref} ${b.customer_name} ${b.vehicle_ref}`.toLowerCase().includes(query.toLowerCase()));
+ const totalPages = Math.max(1, Math.ceil(filtered.length / perPage));
+ const visible = filtered.slice((page - 1) * perPage, page * perPage);
+ return filtered.length === 0 ? : {filtered.length} bookingsPage {page} of {totalPages}
Bookings
@@ -57,24 +70,24 @@ export function Bookings() {
{bookings.map((b) => (
- |
+ |
{b.public_ref}
|
- {b.customer_name} |
-
+ | {b.customer_name} |
+
{b.vehicle_ref}
|
-
+ |
{new Date(b.starts_at).toLocaleDateString("en-GB")} → {new Date(b.ends_at).toLocaleDateString("en-GB")}
|
-
+ |
|
))}
-
- )}
+
{(page - 1) * perPage + 1}–{Math.min(page * perPage, filtered.length)} of {filtered.length}
;
+ })()}
);
}
diff --git a/frontend/src/pages/VehicleDetail.tsx b/frontend/src/pages/VehicleDetail.tsx
index aba10f5..fe6f3fd 100644
--- a/frontend/src/pages/VehicleDetail.tsx
+++ b/frontend/src/pages/VehicleDetail.tsx
@@ -3,6 +3,8 @@ import { Link, useParams } from "react-router-dom";
import { api } from "../api/client";
import type { VehicleDetail as VehicleDetailData } from "../api/types";
import { SeverityBadge, StatusBadge } from "../components/Badge";
+import { Icon } from "../components/Icons";
+import { ErrorState, LoadingState, PageHeader } from "../components/PageChrome";
const TABS = ["overview", "bookings", "inspections", "maintenance", "quality"] as const;
type Tab = (typeof TABS)[number];
@@ -23,21 +25,15 @@ export function VehicleDetail() {
.catch(() => setError("This vehicle could not be found."));
}, [publicRef]);
- if (error) return {error}
;
- if (!vehicle) return Loading vehicle…
;
+ if (error) return ;
+ if (!vehicle) return ;
return (
-
← Back to vehicles
-
- {vehicle.public_ref} — {vehicle.make} {vehicle.model}
-
-
-
- {vehicle.attention && Needs attention}
-
+
Fleet registry
+
{vehicle.attention && Needs attention} } />
-
+
{TABS.map((t) => (
);
}