diff --git a/src/pages/DashboardPage.tsx b/src/pages/DashboardPage.tsx index 5976ad6..fad6af8 100644 --- a/src/pages/DashboardPage.tsx +++ b/src/pages/DashboardPage.tsx @@ -24,9 +24,11 @@ import { } from "@/components/ui/table"; import { Progress } from "@/components/ui/progress"; import { apiGet } from "@/lib/api"; -import type { Booking, DashboardPayload } from "@/lib/types"; import { formatDate, formatMoney } from "@/lib/format"; import { roomDisplayName } from "@/lib/room-utils"; +import { Spinner } from "@/components/ui/spinner"; +import { useAuthStore } from "@/store/authStore"; +import type { Booking, DashboardPayload } from "@/lib/types"; const tooltipStyle = { backgroundColor: "var(--navy)", @@ -35,18 +37,111 @@ const tooltipStyle = { color: "#fff", }; +type HotelSummaryResponse = { + arrivalsToday?: number; + arrivals?: number; + departuresToday?: number; + departures?: number; + unpaidHolds?: number; + revenueMonth?: string | number; + bookingsByStatus?: Record; +}; + +function isDashboardPayload(d: unknown): d is DashboardPayload { + return typeof d === "object" && d !== null && "bookingSeries" in d; +} + +function isHotelSummary(d: unknown): d is HotelSummaryResponse { + if (typeof d !== "object" || d === null) return false; + const x = d as HotelSummaryResponse; + return ( + typeof x.arrivalsToday === "number" || + typeof x.arrivals === "number" || + x.bookingsByStatus !== undefined + ); +} + export function DashboardPage() { - const [data, setData] = useState(null); + const selectedPropertyId = useAuthStore((s) => s.selectedPropertyId); + const [data, setData] = useState( + null + ); const [err, setErr] = useState(null); useEffect(() => { - apiGet("/dashboard") + setErr(null); + setData(null); + apiGet(`/dashboard/summary`) .then(setData) .catch((e) => setErr(String(e))); - }, []); + }, [selectedPropertyId]); if (err) return

{err}

; - if (!data) return

Loading…

; + if (!data) return ( +
+ +
+ ); + + if (isHotelSummary(data) && !isDashboardPayload(data)) { + const arrivals = data.arrivalsToday ?? data.arrivals ?? 0; + const departures = data.departuresToday ?? data.departures ?? 0; + const revenueRaw = data.revenueMonth ?? 0; + const revenueNum = + typeof revenueRaw === "string" ? parseFloat(revenueRaw) : Number(revenueRaw); + + return ( +
+
+

Dashboard

+
+
+ {[ + { label: "Arrivals today", value: arrivals }, + { label: "Departures today", value: departures }, + { label: "Unpaid holds", value: data.unpaidHolds ?? 0 }, + { + label: "Revenue (month)", + value: formatMoney(Number.isFinite(revenueNum) ? revenueNum : 0), + }, + ].map((c) => ( + + + + {c.label} + + + +

{c.value}

+
+
+ ))} +
+ {data.bookingsByStatus && Object.keys(data.bookingsByStatus).length > 0 ? ( + + + Bookings by status + + + {Object.entries(data.bookingsByStatus).map(([k, v]) => ( + + {k}: {v} + + ))} + + + ) : null} +
+ ); + } + + if (!isDashboardPayload(data)) { + return ( +

+ Unexpected dashboard response. Try again or check the API. +

+ ); + } return (
@@ -263,7 +358,7 @@ export function DashboardPage() { {formatDate(b.checkIn)} → {formatDate(b.checkOut)} - {roomDisplayName(b.roomId)} + {b.roomDisplayLabel ?? roomDisplayName(b.roomId)} {b.status} diff --git a/src/pages/PaymentsPage.tsx b/src/pages/PaymentsPage.tsx index 295dd7b..6b1622f 100644 --- a/src/pages/PaymentsPage.tsx +++ b/src/pages/PaymentsPage.tsx @@ -11,15 +11,17 @@ import { TableRow, } from "@/components/ui/table"; import { apiGet } from "@/lib/api"; +import { useAuthStore } from "@/store/authStore"; import type { Payment } from "@/lib/types"; import { formatDateTime, formatMoney } from "@/lib/format"; export function PaymentsPage() { + const selectedPropertyId = useAuthStore((s) => s.selectedPropertyId); const [rows, setRows] = useState([]); useEffect(() => { apiGet<{ data: Payment[] }>("/payments").then((r) => setRows(r.data)); - }, []); + }, [selectedPropertyId]); return (
diff --git a/src/pages/TransactionsPage.tsx b/src/pages/TransactionsPage.tsx index 2174ac7..8d9c1cc 100644 --- a/src/pages/TransactionsPage.tsx +++ b/src/pages/TransactionsPage.tsx @@ -11,17 +11,19 @@ import { TableRow, } from "@/components/ui/table"; import { apiGet } from "@/lib/api"; +import { useAuthStore } from "@/store/authStore"; import type { Transaction } from "@/lib/types"; import { formatDateTime, formatMoney } from "@/lib/format"; export function TransactionsPage() { + const selectedPropertyId = useAuthStore((s) => s.selectedPropertyId); const [rows, setRows] = useState([]); useEffect(() => { apiGet<{ data: Transaction[] }>("/transactions").then((r) => setRows(r.data) ); - }, []); + }, [selectedPropertyId]); return (