mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
@@ -112,6 +112,15 @@ export default function ConfirmationPage() {
|
||||
// backgrounded tabs, so that can take a very long time.
|
||||
staleTime: 0,
|
||||
enabled: !!bookingId,
|
||||
// Keep polling after CONFIRMED until tickets are issued — ticket generation runs
|
||||
// async after the booking transaction commits (see finalizePaymentSuccess in
|
||||
// payments.service.ts), so the first CONFIRMED fetch often returns an empty
|
||||
// tickets array.
|
||||
refetchInterval: (query) => {
|
||||
const data = query.state.data;
|
||||
if (!data || data.status !== "CONFIRMED") return false;
|
||||
return (data.tickets?.length ?? 0) >= passengers.length ? false : FAST_POLL_INTERVAL_MS;
|
||||
},
|
||||
});
|
||||
|
||||
// Poll the payment intent while the booking is PENDING_PAYMENT — fast during the
|
||||
@@ -153,7 +162,7 @@ export default function ConfirmationPage() {
|
||||
};
|
||||
|
||||
const handleDownloadVoucher = async () => {
|
||||
if (!pnr) {
|
||||
if (!pnr || !bookingId) {
|
||||
alert("Booking data not available. Please try again.");
|
||||
return;
|
||||
}
|
||||
@@ -164,23 +173,28 @@ export default function ConfirmationPage() {
|
||||
|
||||
setIsGeneratingVoucher(true);
|
||||
try {
|
||||
const { generatePassengerVoucherPDF } =
|
||||
await import("@/lib/generate-voucher");
|
||||
const { generatePassengerVoucherPDF } = await import("@/lib/generate-voucher");
|
||||
|
||||
// Always fetch fresh booking data so tickets are present even if the cached
|
||||
// _booking raced ahead of ticket generation (tickets are written async after
|
||||
// the booking is confirmed — see finalizePaymentSuccess in payments.service.ts).
|
||||
const freshBooking: BookingWithTicket = await apiClient.get(`/bookings/${bookingId}`);
|
||||
const bookingData = freshBooking ?? _booking;
|
||||
|
||||
const activeSchedule = isRoundTrip ? outboundSchedule : selectedSchedule;
|
||||
// The server-confirmed settled amount/currency (what was actually charged) is
|
||||
// authoritative — prefer it over the ETB booking fare once available. Shown exactly
|
||||
// as returned by the API (no /100, no per-passenger split) on every passenger's
|
||||
// voucher — see fareIsMajorUnits below.
|
||||
const settledAmountMinor = _booking?.payment?.amountMinor;
|
||||
const settledCurrency = _booking?.payment?.currency;
|
||||
const settledAmountMinor = bookingData?.payment?.amountMinor;
|
||||
const settledCurrency = bookingData?.payment?.currency;
|
||||
const hasSettledAmount = settledAmountMinor != null && !!settledCurrency;
|
||||
// Derive display currency from nationality (same logic as review/payment pages)
|
||||
const nat = (searchCriteria?.nationality ?? '').toUpperCase();
|
||||
const passengerDisplayCurrency = nat === 'DJIBOUTIAN' ? 'DJF' : nat === 'ETHIOPIAN' ? 'ETB' : 'USD';
|
||||
const voucherCurrency = hasSettledAmount ? settledCurrency! : passengerDisplayCurrency;
|
||||
const createdAt = _booking?.createdAt || new Date().toISOString();
|
||||
const status = _booking?.status || "CONFIRMED";
|
||||
const createdAt = bookingData?.createdAt || new Date().toISOString();
|
||||
const status = bookingData?.status || "CONFIRMED";
|
||||
|
||||
// Compute per-passenger fares (in ETB) using the same logic as the review/payment
|
||||
// pages. reviewedPassengerFares is the authoritative source; rebuild from package
|
||||
@@ -206,7 +220,7 @@ export default function ConfirmationPage() {
|
||||
return isPkgChild ? pkgChildFare : pkgAdultFare;
|
||||
}
|
||||
const totalFare =
|
||||
reviewedTotalMinor ?? paidAmountMinor ?? _booking?.totalMinor ?? 0;
|
||||
reviewedTotalMinor ?? paidAmountMinor ?? bookingData?.totalMinor ?? 0;
|
||||
return Math.round(totalFare / passengers.length);
|
||||
};
|
||||
|
||||
@@ -254,11 +268,9 @@ export default function ConfirmationPage() {
|
||||
// synchronous user-activation window and risk iOS Safari silently blocking them.
|
||||
for (let i = 0; i < passengers.length; i++) {
|
||||
const p = passengers[i];
|
||||
// Same match-by-name-then-position as the on-screen ticket list above — no
|
||||
// fabricated placeholder if there's no backend ticket data (see generate-voucher.ts).
|
||||
const matchedTicket =
|
||||
_booking?.tickets?.find((t) => t.passengerName === p.name) ??
|
||||
_booking?.tickets?.[i] ??
|
||||
bookingData?.tickets?.find((t) => t.passengerName === p.name) ??
|
||||
bookingData?.tickets?.[i] ??
|
||||
null;
|
||||
const ticketNumber = matchedTicket?.barcodePayload || "Not yet issued";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user