Files
edr-platform/apps/edr-freight-web/portal/src/features/bookingWindows/useBookingWindowSocket.ts
Marshal 05b13e84a8 enhance booking and contract notification systems
- Added detailed logging for socket connection events in useBookingWindowSocket.
- Introduced new notification types for contract status and schedule updates.
- Updated notification visuals to include new icons for contract status.
- Enhanced notification href resolution for contract status and schedule updates.
- Implemented booking lifecycle notifier service for customer and staff notifications.
- Created contract notifier service for managing contract lifecycle notifications.
- Added end-to-end tests for booking window socket functionality.
2026-07-06 21:03:08 +00:00

73 lines
2.2 KiB
TypeScript

import {
BOOKING_WINDOW_WS_EVENTS,
BOOKING_WINDOW_WS_NAMESPACE,
type BookingWindowPhaseEvent,
} from "@edr/types";
import { useQueryClient } from "@tanstack/react-query";
import { useEffect } from "react";
import { io } from "socket.io-client";
import { API_BASE_URL } from "@/constants/apiConfig";
function getAuthToken(): string | undefined {
return document.cookie
.split("; ")
.find((row) => row.startsWith("auth-token="))
?.split("=")[1];
}
// The socket namespace lives at the server root, not under the `/api` REST
// prefix — strip a trailing `/api` if the base URL carries one.
const SOCKET_ORIGIN = String(API_BASE_URL ?? "").replace(/\/api\/?$/, "");
/**
* Subscribes to live booking-window pushes. Every phase transition the window
* engine applies (open, doc review, payment, reopen, done) invalidates the
* cached window lists, so the home-page "Booking Windows" card flips the
* moment the backend does — the 60s poll remains only as a fallback.
*/
export function useBookingWindowSocket(enabled: boolean) {
const qc = useQueryClient();
useEffect(() => {
if (!enabled) return;
const token = getAuthToken();
if (!token) return;
const socket = io(`${SOCKET_ORIGIN}/${BOOKING_WINDOW_WS_NAMESPACE}`, {
auth: { token },
transports: ["websocket"],
withCredentials: true,
});
// Deliberate console breadcrumbs: "live updates not arriving" is only
// diagnosable from the browser when connect/reject outcomes are visible.
socket.on("connect", () =>
console.debug("[booking-windows] socket connected", socket.id),
);
socket.on("connect_error", (err) =>
console.warn("[booking-windows] socket connect failed:", err.message),
);
socket.on("disconnect", (reason) =>
console.debug("[booking-windows] socket disconnected:", reason),
);
socket.on(
BOOKING_WINDOW_WS_EVENTS.PHASE,
(_event: BookingWindowPhaseEvent) => {
qc.invalidateQueries({
queryKey: ["train-scheduling", "myBookingWindows"],
});
qc.invalidateQueries({
queryKey: ["train-scheduling", "contractBookingWindows"],
});
},
);
return () => {
socket.off();
socket.disconnect();
};
}, [enabled, qc]);
}