@voyant-travel/bookings-react 0.138.3 → 0.138.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/components/booking-detail-page.d.ts.map +1 -1
  2. package/dist/components/booking-detail-page.js +3 -2
  3. package/dist/components/booking-dialog.d.ts.map +1 -1
  4. package/dist/components/booking-dialog.js +2 -19
  5. package/dist/components/booking-item-dialog.d.ts.map +1 -1
  6. package/dist/components/booking-item-dialog.js +16 -5
  7. package/dist/components/booking-item-list.d.ts +2 -1
  8. package/dist/components/booking-item-list.d.ts.map +1 -1
  9. package/dist/components/booking-item-list.js +13 -13
  10. package/dist/components/traveler-dialog.d.ts.map +1 -1
  11. package/dist/components/traveler-dialog.js +15 -1
  12. package/dist/components/traveler-list.d.ts.map +1 -1
  13. package/dist/components/traveler-list.js +30 -12
  14. package/dist/extras/hooks/use-slot-extra-manifest-mutation.d.ts +3 -3
  15. package/dist/extras/hooks/use-slot-extra-manifest.d.ts +1 -1
  16. package/dist/extras/query-options.d.ts +4 -4
  17. package/dist/extras/schemas.d.ts +3 -3
  18. package/dist/hooks/use-booking-action-ledger.d.ts +1 -1
  19. package/dist/hooks/use-supplier-status-mutation.d.ts +2 -2
  20. package/dist/hooks/use-supplier-statuses.d.ts +1 -1
  21. package/dist/i18n/en-base.d.ts +9 -0
  22. package/dist/i18n/en-base.d.ts.map +1 -1
  23. package/dist/i18n/en-base.js +9 -0
  24. package/dist/i18n/en-sections.d.ts +1 -0
  25. package/dist/i18n/en-sections.d.ts.map +1 -1
  26. package/dist/i18n/en-sections.js +1 -0
  27. package/dist/i18n/en.d.ts +10 -0
  28. package/dist/i18n/en.d.ts.map +1 -1
  29. package/dist/i18n/messages-base.d.ts +3 -0
  30. package/dist/i18n/messages-base.d.ts.map +1 -1
  31. package/dist/i18n/messages-sections.d.ts +1 -0
  32. package/dist/i18n/messages-sections.d.ts.map +1 -1
  33. package/dist/i18n/provider.d.ts +20 -0
  34. package/dist/i18n/provider.d.ts.map +1 -1
  35. package/dist/i18n/ro-base.d.ts +9 -0
  36. package/dist/i18n/ro-base.d.ts.map +1 -1
  37. package/dist/i18n/ro-base.js +9 -0
  38. package/dist/i18n/ro-sections.d.ts +1 -0
  39. package/dist/i18n/ro-sections.d.ts.map +1 -1
  40. package/dist/i18n/ro-sections.js +1 -0
  41. package/dist/i18n/ro.d.ts +10 -0
  42. package/dist/i18n/ro.d.ts.map +1 -1
  43. package/dist/journey/components/booking-journey-rules.d.ts.map +1 -1
  44. package/dist/journey/components/booking-journey-rules.js +2 -2
  45. package/dist/query-options.d.ts +4 -4
  46. package/dist/requirements/hooks/use-booking-questions.d.ts +1 -1
  47. package/dist/requirements/query-options.d.ts +4 -4
  48. package/dist/requirements/schemas.d.ts +3 -3
  49. package/dist/schemas.d.ts +6 -6
  50. package/package.json +19 -19
@@ -1 +1 @@
1
- {"version":3,"file":"booking-detail-page.d.ts","sourceRoot":"","sources":["../../src/components/booking-detail-page.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"booking-detail-page.d.ts","sourceRoot":"","sources":["../../src/components/booking-detail-page.tsx"],"names":[],"mappings":"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"}
@@ -58,6 +58,7 @@ export function BookingDetailPage({ id, className, locale, hideBreadcrumb, onBac
58
58
  return (_jsxs("div", { className: cn("flex flex-col items-center justify-center gap-4 py-12", className), children: [_jsx("p", { className: "text-muted-foreground", children: detailMessages.notFound }), onBack ? (_jsx(Button, { variant: "outline", onClick: onBack, children: detailMessages.backToBookings })) : null] }));
59
59
  }
60
60
  const canCancel = ["draft", "on_hold", "confirmed", "in_progress"].includes(booking.status);
61
+ const isCancelled = booking.status === "cancelled";
61
62
  const sellHint = booking.priceOverride?.isManual
62
63
  ? `${detailMessages.summaryPriceOverride}: ${booking.priceOverride.reason}`
63
64
  : undefined;
@@ -86,13 +87,13 @@ export function BookingDetailPage({ id, className, locale, hideBreadcrumb, onBac
86
87
  headerDateRange ? (headerSlotId && onItemResourceOpen ? (_jsx("button", { type: "button", onClick: () => onItemResourceOpen("availabilitySlot", headerSlotId), className: "hover:text-foreground hover:underline", children: headerDateRange }, "dates")) : (_jsx("span", { children: headerDateRange }, "dates"))) : null,
87
88
  headerPax ? _jsx("span", { children: headerPax }, "pax") : null,
88
89
  ].filter(Boolean);
89
- return (_jsxs("div", { "data-slot": "booking-detail-page", className: cn("flex flex-col gap-6 p-6", className), children: [hideBreadcrumb ? null : (_jsxs("div", { className: "flex items-center gap-1.5 text-sm text-muted-foreground", children: [onBack ? (_jsx("button", { type: "button", onClick: onBack, className: "transition-colors hover:text-foreground", children: detailMessages.breadcrumbBookings })) : (_jsx("span", { children: detailMessages.breadcrumbBookings })), _jsx(ChevronRight, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), _jsx("span", { className: "font-normal text-foreground", children: booking.bookingNumber })] })), _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("h1", { className: "text-2xl font-bold tracking-tight", children: booking.bookingNumber }), _jsx(StatusBadge, { status: booking.status, children: getBookingStatusLabel(booking.status, messages.common.bookingStatusLabels) })] }), headerSubtitleParts.length > 0 ? (_jsx("div", { className: "flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground", children: headerSubtitleParts.map((part, idx) => (_jsxs(Fragment, { children: [idx > 0 ? _jsx("span", { className: "text-muted-foreground/60", children: "/" }) : null, part] }, idx))) })) : null] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setEditOpen(true), children: [_jsx(Pencil, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.editAction] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setStatusDialogOpen(true), children: [_jsx(RefreshCw, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.changeStatusAction] }), canCancel ? (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setCancelDialogOpen(true), children: [_jsx(Ban, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.cancelBookingAction] })) : null, _jsxs(Button, { variant: "outline", size: "sm", className: "text-destructive hover:bg-destructive/10 hover:text-destructive", disabled: remove.isPending, onClick: () => setDeleteDialogOpen(true), children: [_jsx(Trash2, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.deleteAction] })] })] }), slots?.header?.(booking), _jsxs("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-4", children: [_jsx(StatCard, { label: detailMessages.summaryTotal, hint: sellHint, children: formatAmount(booking.sellAmountCents, booking.sellCurrency, resolvedLocale, detailMessages.noValue) }), _jsx(StatCard, { label: detailMessages.summaryPaid, badge: paidAmountCents != null && booking.sellAmountCents
90
+ return (_jsxs("div", { "data-slot": "booking-detail-page", className: cn("flex flex-col gap-6 p-6", className), children: [hideBreadcrumb ? null : (_jsxs("div", { className: "flex items-center gap-1.5 text-sm text-muted-foreground", children: [onBack ? (_jsx("button", { type: "button", onClick: onBack, className: "transition-colors hover:text-foreground", children: detailMessages.breadcrumbBookings })) : (_jsx("span", { children: detailMessages.breadcrumbBookings })), _jsx(ChevronRight, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), _jsx("span", { className: "font-normal text-foreground", children: booking.bookingNumber })] })), _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("h1", { className: "text-2xl font-bold tracking-tight", children: booking.bookingNumber }), _jsx(StatusBadge, { status: booking.status, children: getBookingStatusLabel(booking.status, messages.common.bookingStatusLabels) })] }), headerSubtitleParts.length > 0 ? (_jsx("div", { className: "flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground", children: headerSubtitleParts.map((part, idx) => (_jsxs(Fragment, { children: [idx > 0 ? _jsx("span", { className: "text-muted-foreground/60", children: "/" }) : null, part] }, idx))) })) : null] }), isCancelled ? null : (_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setEditOpen(true), children: [_jsx(Pencil, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.editAction] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setStatusDialogOpen(true), children: [_jsx(RefreshCw, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.changeStatusAction] }), canCancel ? (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => setCancelDialogOpen(true), children: [_jsx(Ban, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.cancelBookingAction] })) : null, _jsxs(Button, { variant: "outline", size: "sm", className: "text-destructive hover:bg-destructive/10 hover:text-destructive", disabled: remove.isPending, onClick: () => setDeleteDialogOpen(true), children: [_jsx(Trash2, { className: "mr-1.5 h-3.5 w-3.5", "aria-hidden": "true" }), detailMessages.deleteAction] })] }))] }), slots?.header?.(booking), _jsxs("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-4", children: [_jsx(StatCard, { label: detailMessages.summaryTotal, hint: sellHint, children: formatAmount(booking.sellAmountCents, booking.sellCurrency, resolvedLocale, detailMessages.noValue) }), _jsx(StatCard, { label: detailMessages.summaryPaid, badge: paidAmountCents != null && booking.sellAmountCents
90
91
  ? renderPercentBadge(Math.round((paidAmountCents / booking.sellAmountCents) * 100), paidBadgeClass)
91
92
  : null, children: paidAmountCents != null
92
93
  ? formatAmount(paidAmountCents, booking.sellCurrency, resolvedLocale, detailMessages.noValue)
93
94
  : detailMessages.noValue }), _jsx(StatCard, { label: detailMessages.summaryCostMargin, badge: booking.marginPercent != null
94
95
  ? renderPercentBadge(booking.marginPercent, marginBadgeClass)
95
- : null, children: formatAmount(booking.costAmountCents, booking.sellCurrency, resolvedLocale, detailMessages.noValue) }), _jsx(StatCard, { label: detailMessages.summaryCreated, children: formatDate(booking.createdAt, resolvedLocale, detailMessages.noValue) })] }), slots?.afterSummary?.(booking), _jsxs(Tabs, { defaultValue: "items", value: activeTab, onValueChange: (value) => onTabChange?.(String(value)), children: [_jsxs(TabsList, { className: "w-full justify-start", children: [_jsx(TabsTrigger, { value: "items", children: detailMessages.tabOverview }), _jsx(TabsTrigger, { value: "travelers", children: detailMessages.tabTravelers }), _jsx(TabsTrigger, { value: "finance", children: detailMessages.tabFinance }), slots?.invoicesTab ? (_jsx(TabsTrigger, { value: "invoices", children: slots.invoicesTab.label ?? detailMessages.tabInvoices })) : null, _jsx(TabsTrigger, { value: "documents", children: detailMessages.tabDocuments }), _jsx(TabsTrigger, { value: "suppliers", children: detailMessages.tabSuppliers }), _jsx(TabsTrigger, { value: "activity", children: detailMessages.tabActivity }), _jsx(TabsTrigger, { value: "metadata", children: detailMessages.tabMetadata })] }), _jsxs(TabsContent, { value: "items", className: "mt-4 flex flex-col gap-6", children: [slots?.overviewStart?.(booking), _jsx(BookingItemList, { bookingId: id, onResourceOpen: onItemResourceOpen }), _jsx(BookingGroupSection, { bookingId: id }), visibleInternalNotes(booking.internalNotes) ? (_jsx(Card, { children: _jsxs(CardContent, { className: "py-5", children: [_jsx("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: detailMessages.internalNotesLabel }), _jsx("p", { className: "whitespace-pre-wrap text-sm", children: visibleInternalNotes(booking.internalNotes) })] }) })) : null, slots?.overviewEnd?.(booking)] }), _jsxs(TabsContent, { value: "travelers", className: "mt-4 flex flex-col gap-6", children: [slots?.travelersStart?.(booking), _jsx(BookingBillingContextCard, { booking: booking, onPersonOpen: onPersonOpen, onOrganizationOpen: onOrganizationOpen }), _jsx(TravelerList, { bookingId: id, autoReveal: true })] }), _jsxs(TabsContent, { value: "finance", className: "mt-4 flex flex-col gap-6", children: [_jsx(BookingPaymentScheduleList, { bookingId: id, addScheduleDisabledReason: addScheduleDisabledReason ?? null }), slots?.paymentsContent ? (renderDetailSlot(slots.paymentsContent, booking)) : (_jsx(BookingPaymentsSummary, { bookingId: id, variant: "admin", onViewPayment: onViewPayment, onInvoiceOpen: onInvoiceOpen, onEditPayment: onEditPayment, onDeletePayment: onDeletePayment, headerAction: onRecordPayment ? (_jsx(RecordPaymentHeaderButton, { label: detailMessages.recordPaymentAction, disabledReason: recordPaymentDisabledReason ?? null, onClick: () => onRecordPayment(booking) })) : null })), slots?.financeStart?.(booking), _jsxs(Collapsible, { children: [_jsxs(CollapsibleTrigger, { className: "group flex w-full items-center justify-between rounded-md border bg-background px-4 py-3 text-sm font-semibold hover:bg-muted/30", children: [messages.bookingGuaranteeList.title, _jsx(ChevronDown, { className: "h-4 w-4 transition-transform group-data-panel-open:rotate-180" })] }), _jsx(CollapsibleContent, { className: "mt-3", children: _jsx(BookingGuaranteeList, { bookingId: id }) })] }), slots?.financeEnd?.(booking)] }), slots?.invoicesTab ? (_jsx(TabsContent, { value: "invoices", className: "mt-4 flex flex-col gap-6", children: renderDetailSlot(slots.invoicesTab.content, booking) })) : null, _jsx(TabsContent, { value: "documents", className: "mt-4 flex flex-col gap-4", children: slots?.documents ? (slots.documents(booking)) : (_jsx("p", { className: "rounded-md border border-dashed p-4 text-sm text-muted-foreground", children: detailMessages.documentsSlotEmpty })) }), _jsx(TabsContent, { value: "suppliers", className: "mt-4", children: _jsx(SupplierStatusList, { bookingId: id }) }), _jsxs(TabsContent, { value: "activity", className: "mt-4 flex flex-col gap-6", children: [_jsx(BookingNotes, { bookingId: id }), _jsx(BookingActivityTimeline, { bookingId: id, paymentsVariant: "admin", additionalEvents: slots?.activityExtraEvents, footer: slots?.activityTimelineFooter }), slots?.activityEnd?.(booking)] }), _jsx(TabsContent, { value: "metadata", className: "mt-4", children: _jsx(BookingMetadataList, { booking: booking, messages: detailMessages.metadataSection, statusLabel: getBookingStatusLabel(booking.status, messages.common.bookingStatusLabels), formatDateTime: i18n.formatDateTime, noValue: detailMessages.noValue }) })] }), _jsx(BookingDialog, { open: editOpen, onOpenChange: setEditOpen, booking: booking }), _jsx(StatusChangeDialog, { open: statusDialogOpen, onOpenChange: setStatusDialogOpen, bookingId: id, currentStatus: booking.status }), _jsx(BookingCancellationDialog, { open: cancelDialogOpen, onOpenChange: setCancelDialogOpen, booking: booking }), _jsx(AlertDialog, { open: deleteDialogOpen, onOpenChange: (next) => {
96
+ : null, children: formatAmount(booking.costAmountCents, booking.sellCurrency, resolvedLocale, detailMessages.noValue) }), _jsx(StatCard, { label: detailMessages.summaryCreated, children: formatDate(booking.createdAt, resolvedLocale, detailMessages.noValue) })] }), slots?.afterSummary?.(booking), _jsxs(Tabs, { defaultValue: "items", value: activeTab, onValueChange: (value) => onTabChange?.(String(value)), children: [_jsxs(TabsList, { className: "w-full justify-start", children: [_jsx(TabsTrigger, { value: "items", children: detailMessages.tabOverview }), _jsx(TabsTrigger, { value: "travelers", children: detailMessages.tabTravelers }), _jsx(TabsTrigger, { value: "finance", children: detailMessages.tabFinance }), slots?.invoicesTab ? (_jsx(TabsTrigger, { value: "invoices", children: slots.invoicesTab.label ?? detailMessages.tabInvoices })) : null, _jsx(TabsTrigger, { value: "documents", children: detailMessages.tabDocuments }), _jsx(TabsTrigger, { value: "suppliers", children: detailMessages.tabSuppliers }), _jsx(TabsTrigger, { value: "activity", children: detailMessages.tabActivity }), _jsx(TabsTrigger, { value: "metadata", children: detailMessages.tabMetadata })] }), _jsxs(TabsContent, { value: "items", className: "mt-4 flex flex-col gap-6", children: [slots?.overviewStart?.(booking), _jsx(BookingItemList, { bookingId: id, onResourceOpen: onItemResourceOpen, readOnly: isCancelled }), _jsx(BookingGroupSection, { bookingId: id }), visibleInternalNotes(booking.internalNotes) ? (_jsx(Card, { children: _jsxs(CardContent, { className: "py-5", children: [_jsx("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: detailMessages.internalNotesLabel }), _jsx("p", { className: "whitespace-pre-wrap text-sm", children: visibleInternalNotes(booking.internalNotes) })] }) })) : null, slots?.overviewEnd?.(booking)] }), _jsxs(TabsContent, { value: "travelers", className: "mt-4 flex flex-col gap-6", children: [slots?.travelersStart?.(booking), _jsx(BookingBillingContextCard, { booking: booking, onPersonOpen: onPersonOpen, onOrganizationOpen: onOrganizationOpen }), _jsx(TravelerList, { bookingId: id, autoReveal: true })] }), _jsxs(TabsContent, { value: "finance", className: "mt-4 flex flex-col gap-6", children: [_jsx(BookingPaymentScheduleList, { bookingId: id, addScheduleDisabledReason: addScheduleDisabledReason ?? null }), slots?.paymentsContent ? (renderDetailSlot(slots.paymentsContent, booking)) : (_jsx(BookingPaymentsSummary, { bookingId: id, variant: "admin", onViewPayment: onViewPayment, onInvoiceOpen: onInvoiceOpen, onEditPayment: onEditPayment, onDeletePayment: onDeletePayment, headerAction: onRecordPayment ? (_jsx(RecordPaymentHeaderButton, { label: detailMessages.recordPaymentAction, disabledReason: recordPaymentDisabledReason ?? null, onClick: () => onRecordPayment(booking) })) : null })), slots?.financeStart?.(booking), _jsxs(Collapsible, { children: [_jsxs(CollapsibleTrigger, { className: "group flex w-full items-center justify-between rounded-md border bg-background px-4 py-3 text-sm font-semibold hover:bg-muted/30", children: [messages.bookingGuaranteeList.title, _jsx(ChevronDown, { className: "h-4 w-4 transition-transform group-data-panel-open:rotate-180" })] }), _jsx(CollapsibleContent, { className: "mt-3", children: _jsx(BookingGuaranteeList, { bookingId: id }) })] }), slots?.financeEnd?.(booking)] }), slots?.invoicesTab ? (_jsx(TabsContent, { value: "invoices", className: "mt-4 flex flex-col gap-6", children: renderDetailSlot(slots.invoicesTab.content, booking) })) : null, _jsx(TabsContent, { value: "documents", className: "mt-4 flex flex-col gap-4", children: slots?.documents ? (slots.documents(booking)) : (_jsx("p", { className: "rounded-md border border-dashed p-4 text-sm text-muted-foreground", children: detailMessages.documentsSlotEmpty })) }), _jsx(TabsContent, { value: "suppliers", className: "mt-4", children: _jsx(SupplierStatusList, { bookingId: id }) }), _jsxs(TabsContent, { value: "activity", className: "mt-4 flex flex-col gap-6", children: [_jsx(BookingNotes, { bookingId: id }), _jsx(BookingActivityTimeline, { bookingId: id, paymentsVariant: "admin", additionalEvents: slots?.activityExtraEvents, footer: slots?.activityTimelineFooter }), slots?.activityEnd?.(booking)] }), _jsx(TabsContent, { value: "metadata", className: "mt-4", children: _jsx(BookingMetadataList, { booking: booking, messages: detailMessages.metadataSection, statusLabel: getBookingStatusLabel(booking.status, messages.common.bookingStatusLabels), formatDateTime: i18n.formatDateTime, noValue: detailMessages.noValue }) })] }), _jsx(BookingDialog, { open: editOpen, onOpenChange: setEditOpen, booking: booking }), _jsx(StatusChangeDialog, { open: statusDialogOpen, onOpenChange: setStatusDialogOpen, bookingId: id, currentStatus: booking.status }), _jsx(BookingCancellationDialog, { open: cancelDialogOpen, onOpenChange: setCancelDialogOpen, booking: booking }), _jsx(AlertDialog, { open: deleteDialogOpen, onOpenChange: (next) => {
96
97
  if (!next && !remove.isPending)
97
98
  setDeleteDialogOpen(false);
98
99
  }, children: _jsxs(AlertDialogContent, { size: "sm", children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: detailMessages.deleteConfirm }), _jsx(AlertDialogDescription, { children: booking.bookingNumber
@@ -1 +1 @@
1
- {"version":3,"file":"booking-dialog.d.ts","sourceRoot":"","sources":["../../src/components/booking-dialog.tsx"],"names":[],"mappings":"AA4BA,OAAO,EAAE,KAAK,aAAa,EAAsB,MAAM,aAAa,CAAA;AA8BpE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;IAC5C;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAWD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,SAAS,EACT,gBAAgB,EAChB,aAAa,GACd,EAAE,kBAAkB,+BAqBpB"}
1
+ {"version":3,"file":"booking-dialog.d.ts","sourceRoot":"","sources":["../../src/components/booking-dialog.tsx"],"names":[],"mappings":"AA4BA,OAAO,EAAE,KAAK,aAAa,EAAsB,MAAM,aAAa,CAAA;AA4BpE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;IAC5C;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAYD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,SAAS,EACT,gBAAgB,EAChB,aAAa,GACd,EAAE,kBAAkB,+BAqBpB"}
@@ -26,8 +26,6 @@ function createBookingFormSchema(messages) {
26
26
  "cancelled",
27
27
  ]),
28
28
  sellCurrency: z.string().min(3).max(3, messages.bookingDialog.validation.sellCurrencyInvalid),
29
- sellAmountCents: z.coerce.number().int().min(0).optional().or(z.literal("")).nullable(),
30
- costAmountCents: z.coerce.number().int().min(0).optional().or(z.literal("")).nullable(),
31
29
  startDate: z.string().optional().nullable(),
32
30
  endDate: z.string().optional().nullable(),
33
31
  pax: z.coerce.number().int().positive().optional().or(z.literal("")).nullable(),
@@ -42,6 +40,7 @@ const BOOKING_STATUS_VALUES = [
42
40
  "cancelled",
43
41
  ];
44
42
  const DEFAULT_CURRENCY = "EUR"; // i18n-literal-ok ISO default currency
43
+ const noopCurrencyChange = (_value) => { };
45
44
  /**
46
45
  * Single booking dialog that handles both create and edit:
47
46
  * - Create (no `booking` prop): renders the rich product → option → person
@@ -67,8 +66,6 @@ function BookingEditDialog({ open, onOpenChange, booking, onSuccess }) {
67
66
  bookingNumber: "",
68
67
  status: "draft",
69
68
  sellCurrency: DEFAULT_CURRENCY,
70
- sellAmountCents: "",
71
- costAmountCents: "",
72
69
  startDate: "",
73
70
  endDate: "",
74
71
  pax: "",
@@ -82,8 +79,6 @@ function BookingEditDialog({ open, onOpenChange, booking, onSuccess }) {
82
79
  bookingNumber: booking.bookingNumber,
83
80
  status: booking.status === "on_hold" || booking.status === "expired" ? "draft" : booking.status,
84
81
  sellCurrency: booking.sellCurrency,
85
- sellAmountCents: booking.sellAmountCents ?? "",
86
- costAmountCents: booking.costAmountCents ?? "",
87
82
  startDate: booking.startDate ?? "",
88
83
  endDate: booking.endDate ?? "",
89
84
  pax: booking.pax ?? "",
@@ -95,8 +90,6 @@ function BookingEditDialog({ open, onOpenChange, booking, onSuccess }) {
95
90
  bookingNumber: values.bookingNumber,
96
91
  status: values.status,
97
92
  sellCurrency: values.sellCurrency,
98
- sellAmountCents: typeof values.sellAmountCents === "number" ? values.sellAmountCents : null,
99
- costAmountCents: typeof values.costAmountCents === "number" ? values.costAmountCents : null,
100
93
  startDate: values.startDate || null,
101
94
  endDate: values.endDate || null,
102
95
  pax: values.pax && typeof values.pax === "number" ? values.pax : null,
@@ -116,15 +109,5 @@ function BookingEditDialog({ open, onOpenChange, booking, onSuccess }) {
116
109
  }, onChange: (nextValue) => {
117
110
  form.setValue("startDate", nextValue?.from ?? "", { shouldDirty: true });
118
111
  form.setValue("endDate", nextValue?.to ?? "", { shouldDirty: true });
119
- }, placeholder: messages.bookingDialog.placeholders.travelDates, className: "w-full" })] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.sellAmountCents }), _jsx(CurrencyInput, { value: typeof form.watch("sellAmountCents") === "number"
120
- ? form.watch("sellAmountCents")
121
- : null, onChange: (next) => form.setValue("sellAmountCents", next, {
122
- shouldDirty: true,
123
- shouldValidate: true,
124
- }), currency: form.watch("sellCurrency") })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.costAmountCents }), _jsx(CurrencyInput, { value: typeof form.watch("costAmountCents") === "number"
125
- ? form.watch("costAmountCents")
126
- : null, onChange: (next) => form.setValue("costAmountCents", next, {
127
- shouldDirty: true,
128
- shouldValidate: true,
129
- }), currency: form.watch("sellCurrency") })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.pax }), _jsx(Input, { ...form.register("pax"), type: "number", min: "1", placeholder: messages.bookingDialog.placeholders.pax })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.internalNotes }), _jsx(Textarea, { ...form.register("internalNotes"), placeholder: messages.bookingDialog.placeholders.internalNotes })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), children: messages.common.cancel }), _jsxs(Button, { type: "submit", size: "sm", disabled: isSubmitting, children: [isSubmitting && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), messages.common.saveChanges] })] })] })] }) }));
112
+ }, placeholder: messages.bookingDialog.placeholders.travelDates, className: "w-full" })] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.sellAmountCents }), _jsx(CurrencyInput, { value: booking.sellAmountCents, onChange: noopCurrencyChange, currency: form.watch("sellCurrency"), disabled: true })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.costAmountCents }), _jsx(CurrencyInput, { value: booking.costAmountCents, onChange: noopCurrencyChange, currency: form.watch("sellCurrency"), disabled: true })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.pax }), _jsx(Input, { ...form.register("pax"), type: "number", min: "1", placeholder: messages.bookingDialog.placeholders.pax })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingDialog.fields.internalNotes }), _jsx(Textarea, { ...form.register("internalNotes"), placeholder: messages.bookingDialog.placeholders.internalNotes })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), children: messages.common.cancel }), _jsxs(Button, { type: "submit", size: "sm", disabled: isSubmitting, children: [isSubmitting && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), messages.common.saveChanges] })] })] })] }) }));
130
113
  }
@@ -1 +1 @@
1
- {"version":3,"file":"booking-item-dialog.d.ts","sourceRoot":"","sources":["../../src/components/booking-item-dialog.tsx"],"names":[],"mappings":"AA4BA,OAAO,EAAE,KAAK,iBAAiB,EAA0B,MAAM,aAAa,CAAA;AAuC5E,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,iBAAiB,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,IAAI,EACJ,SAAS,GACV,EAAE,sBAAsB,+BA4SxB"}
1
+ {"version":3,"file":"booking-item-dialog.d.ts","sourceRoot":"","sources":["../../src/components/booking-item-dialog.tsx"],"names":[],"mappings":"AA4BA,OAAO,EAAE,KAAK,iBAAiB,EAA0B,MAAM,aAAa,CAAA;AAkD5E,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,iBAAiB,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,IAAI,EACJ,SAAS,GACV,EAAE,sBAAsB,+BAiTxB"}
@@ -26,7 +26,8 @@ const itemTypes = [
26
26
  const itemStatuses = ["draft", "on_hold", "confirmed", "cancelled", "expired", "fulfilled"];
27
27
  const DEFAULT_CURRENCY = "EUR"; // i18n-literal-ok ISO default currency
28
28
  function createBookingItemFormSchema(messages) {
29
- return z.object({
29
+ return z
30
+ .object({
30
31
  title: z.string().min(1, messages.bookingItemDialog.validation.titleRequired),
31
32
  itemType: z.enum(itemTypes).default("unit"),
32
33
  status: z.enum(itemStatuses).default("draft"),
@@ -40,6 +41,16 @@ function createBookingItemFormSchema(messages) {
40
41
  serviceDate: z.string().optional().nullable(),
41
42
  description: z.string().optional().nullable(),
42
43
  notes: z.string().optional().nullable(),
44
+ })
45
+ .superRefine((value, ctx) => {
46
+ const hasCostAmount = value.unitCostAmountCents != null || value.totalCostAmountCents != null;
47
+ if (hasCostAmount && !value.costCurrency) {
48
+ ctx.addIssue({
49
+ code: "custom",
50
+ message: messages.bookingItemDialog.validation.costCurrencyRequired,
51
+ path: ["costCurrency"],
52
+ });
53
+ }
43
54
  });
44
55
  }
45
56
  export function BookingItemDialog({ open, onOpenChange, bookingId, item, onSuccess, }) {
@@ -139,16 +150,16 @@ export function BookingItemDialog({ open, onOpenChange, bookingId, item, onSucce
139
150
  }), currency: form.watch("sellCurrency"), placeholder: messages.bookingItemDialog.placeholders.unitSellAmountCents })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.totalSellAmountCents }), _jsx(CurrencyInput, { value: form.watch("totalSellAmountCents"), onChange: (next) => form.setValue("totalSellAmountCents", next, {
140
151
  shouldDirty: true,
141
152
  shouldValidate: true,
142
- }), currency: form.watch("sellCurrency"), placeholder: messages.bookingItemDialog.placeholders.totalSellAmountCents })] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.costCurrency }), _jsx(CurrencyCombobox, { value: form.watch("costCurrency") || null, onChange: (next) => form.setValue("costCurrency", next ?? DEFAULT_CURRENCY, {
153
+ }), currency: form.watch("sellCurrency"), placeholder: messages.bookingItemDialog.placeholders.totalSellAmountCents })] })] }), _jsxs("div", { className: "grid grid-cols-3 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.costCurrency }), _jsx(CurrencyCombobox, { value: form.watch("costCurrency") || null, onChange: (next) => form.setValue("costCurrency", next ?? null, {
143
154
  shouldValidate: true,
144
155
  shouldDirty: true,
145
- }) })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.unitCostAmountCents }), _jsx(CurrencyInput, { value: form.watch("unitCostAmountCents"), onChange: (next) => form.setValue("unitCostAmountCents", next, {
156
+ }) }), form.formState.errors.costCurrency && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.costCurrency.message }))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.unitCostAmountCents }), _jsx(CurrencyInput, { value: form.watch("unitCostAmountCents"), onChange: (next) => form.setValue("unitCostAmountCents", next, {
146
157
  shouldDirty: true,
147
158
  shouldValidate: true,
148
- }), currency: form.watch("costCurrency") || form.watch("sellCurrency"), placeholder: messages.bookingItemDialog.placeholders.unitCostAmountCents })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.totalCostAmountCents }), _jsx(CurrencyInput, { value: form.watch("totalCostAmountCents"), onChange: (next) => form.setValue("totalCostAmountCents", next, {
159
+ }), currency: form.watch("costCurrency"), placeholder: messages.bookingItemDialog.placeholders.unitCostAmountCents })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.totalCostAmountCents }), _jsx(CurrencyInput, { value: form.watch("totalCostAmountCents"), onChange: (next) => form.setValue("totalCostAmountCents", next, {
149
160
  shouldDirty: true,
150
161
  shouldValidate: true,
151
- }), currency: form.watch("costCurrency") || form.watch("sellCurrency"), placeholder: messages.bookingItemDialog.placeholders.totalCostAmountCents })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.serviceDate }), _jsx(DatePicker, { value: form.watch("serviceDate") || null, onChange: (next) => form.setValue("serviceDate", next ?? "", {
162
+ }), currency: form.watch("costCurrency"), placeholder: messages.bookingItemDialog.placeholders.totalCostAmountCents })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.serviceDate }), _jsx(DatePicker, { value: form.watch("serviceDate") || null, onChange: (next) => form.setValue("serviceDate", next ?? "", {
152
163
  shouldValidate: true,
153
164
  shouldDirty: true,
154
165
  }), placeholder: messages.bookingItemDialog.placeholders.serviceDate, className: "w-full" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.description }), _jsx(Textarea, { ...form.register("description"), placeholder: messages.bookingItemDialog.placeholders.description })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.bookingItemDialog.fields.notes }), _jsx(Textarea, { ...form.register("notes"), placeholder: messages.bookingItemDialog.placeholders.notes })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), children: messages.common.cancel }), _jsxs(Button, { type: "submit", size: "sm", disabled: isSubmitting, children: [isSubmitting && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), isEditing ? messages.common.saveChanges : messages.bookingItemDialog.actions.addItem] })] })] })] }) }));
@@ -2,6 +2,7 @@ import * as React from "react";
2
2
  export type BookingItemResourceKind = "product" | "availabilitySlot";
3
3
  export interface BookingItemListProps {
4
4
  bookingId: string;
5
+ readOnly?: boolean;
5
6
  /**
6
7
  * Open a linked resource (product / availability slot) in the host app.
7
8
  * When omitted, the snapshot sheet renders the names as plain text
@@ -9,5 +10,5 @@ export interface BookingItemListProps {
9
10
  */
10
11
  onResourceOpen?: (kind: BookingItemResourceKind, id: string) => void;
11
12
  }
12
- export declare function BookingItemList({ bookingId, onResourceOpen }: BookingItemListProps): React.JSX.Element;
13
+ export declare function BookingItemList({ bookingId, readOnly, onResourceOpen, }: BookingItemListProps): React.JSX.Element;
13
14
  //# sourceMappingURL=booking-item-list.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"booking-item-list.d.ts","sourceRoot":"","sources":["../../src/components/booking-item-list.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,kBAAkB,CAAA;AAEpE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,uBAAuB,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CACrE;AAED,wBAAgB,eAAe,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,oBAAoB,qBA+NlF"}
1
+ {"version":3,"file":"booking-item-list.d.ts","sourceRoot":"","sources":["../../src/components/booking-item-list.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,kBAAkB,CAAA;AAEpE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,uBAAuB,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CACrE;AAED,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,QAAgB,EAChB,cAAc,GACf,EAAE,oBAAoB,qBAqOtB"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Button, } from "@voyant-travel/ui/components";
4
4
  import { DataTable } from "@voyant-travel/ui/components/data-table";
5
5
  import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from "@voyant-travel/ui/components/sheet";
@@ -10,7 +10,7 @@ import { useBookingItemMutation, useBookingItems } from "../index.js";
10
10
  import { BookingItemDialog } from "./booking-item-dialog.js";
11
11
  import { IconActionButton } from "./icon-action-button.js";
12
12
  import { StatusBadge } from "./status-badge.js";
13
- export function BookingItemList({ bookingId, onResourceOpen }) {
13
+ export function BookingItemList({ bookingId, readOnly = false, onResourceOpen, }) {
14
14
  const [dialogOpen, setDialogOpen] = React.useState(false);
15
15
  const [editing, setEditing] = React.useState(undefined);
16
16
  const [deleteTarget, setDeleteTarget] = React.useState(null);
@@ -88,20 +88,20 @@ export function BookingItemList({ bookingId, onResourceOpen }) {
88
88
  cell: ({ row }) => (_jsxs("div", { className: "flex items-center justify-end gap-1", children: [_jsx(IconActionButton, { label: messages.bookingItemList.actions.viewItem, icon: _jsx(Eye, { className: "h-3.5 w-3.5" }), onClick: (e) => {
89
89
  e.stopPropagation();
90
90
  setViewing(row.original);
91
- } }), _jsx(IconActionButton, { label: messages.bookingItemList.actions.editItem, icon: _jsx(Pencil, { className: "h-3.5 w-3.5" }), onClick: (e) => {
92
- e.stopPropagation();
93
- setEditing(row.original);
94
- setDialogOpen(true);
95
- } }), _jsx(IconActionButton, { label: messages.bookingItemList.actions.deleteItem, icon: _jsx(Trash2, { className: "h-3.5 w-3.5" }), className: "text-muted-foreground hover:bg-destructive/10 hover:text-destructive", onClick: (e) => {
96
- e.stopPropagation();
97
- setDeleteTarget(row.original);
98
- } })] })),
91
+ } }), readOnly ? null : (_jsxs(_Fragment, { children: [_jsx(IconActionButton, { label: messages.bookingItemList.actions.editItem, icon: _jsx(Pencil, { className: "h-3.5 w-3.5" }), onClick: (e) => {
92
+ e.stopPropagation();
93
+ setEditing(row.original);
94
+ setDialogOpen(true);
95
+ } }), _jsx(IconActionButton, { label: messages.bookingItemList.actions.deleteItem, icon: _jsx(Trash2, { className: "h-3.5 w-3.5" }), className: "text-muted-foreground hover:bg-destructive/10 hover:text-destructive", onClick: (e) => {
96
+ e.stopPropagation();
97
+ setDeleteTarget(row.original);
98
+ } })] }))] })),
99
99
  },
100
- ], [formatCurrency, formatDateTime, messages]);
101
- return (_jsxs("div", { "data-slot": "booking-item-list", className: "flex flex-col gap-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("h2", { className: "flex items-center gap-2 text-base font-semibold", children: [_jsx(Package, { className: "h-4 w-4" }), messages.bookingItemList.title] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => {
100
+ ], [formatCurrency, formatDateTime, messages, readOnly]);
101
+ return (_jsxs("div", { "data-slot": "booking-item-list", className: "flex flex-col gap-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("h2", { className: "flex items-center gap-2 text-base font-semibold", children: [_jsx(Package, { className: "h-4 w-4" }), messages.bookingItemList.title] }), readOnly ? null : (_jsxs(Button, { variant: "outline", size: "sm", onClick: () => {
102
102
  setEditing(undefined);
103
103
  setDialogOpen(true);
104
- }, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), messages.bookingItemList.addItem] })] }), _jsx(DataTable, { columns: columns, data: items, emptyMessage: messages.bookingItemList.empty, showPagination: false }), _jsx(BookingItemDialog, { open: dialogOpen, onOpenChange: (nextOpen) => {
104
+ }, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), messages.bookingItemList.addItem] }))] }), _jsx(DataTable, { columns: columns, data: items, emptyMessage: messages.bookingItemList.empty, showPagination: false }), _jsx(BookingItemDialog, { open: dialogOpen, onOpenChange: (nextOpen) => {
105
105
  setDialogOpen(nextOpen);
106
106
  if (!nextOpen) {
107
107
  setEditing(undefined);
@@ -1 +1 @@
1
- {"version":3,"file":"traveler-dialog.d.ts","sourceRoot":"","sources":["../../src/components/traveler-dialog.tsx"],"names":[],"mappings":"AAoCA,OAAO,EACL,KAAK,qBAAqB,EAG3B,MAAM,aAAa,CAAA;AAoCpB,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,qBAAqB,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,SAAS,GACV,EAAE,mBAAmB,+BA0brB"}
1
+ {"version":3,"file":"traveler-dialog.d.ts","sourceRoot":"","sources":["../../src/components/traveler-dialog.tsx"],"names":[],"mappings":"AAoCA,OAAO,EACL,KAAK,qBAAqB,EAG3B,MAAM,aAAa,CAAA;AA4CpB,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,qBAAqB,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,SAAS,GACV,EAAE,mBAAmB,+BA0drB"}
@@ -14,10 +14,12 @@ import { z } from "zod/v4";
14
14
  import { useBookingsUiMessagesOrDefault } from "../i18n/provider.js";
15
15
  import { useRevealTraveler, useTravelerWithTravelDetailsMutation, } from "../index.js";
16
16
  const identityDocumentTypes = ["passport", "id_card", "driver_license", "visa", "other"];
17
+ const travelerCategories = ["adult", "child", "infant", "senior", "other"];
17
18
  function createTravelerFormSchema(messages) {
18
19
  return z.object({
19
20
  firstName: z.string().min(1, messages.travelerDialog.validation.firstNameRequired),
20
21
  lastName: z.string().min(1, messages.travelerDialog.validation.lastNameRequired),
22
+ travelerCategory: z.enum(travelerCategories).default("adult"),
21
23
  email: z.string().email().optional().or(z.literal("")).nullable(),
22
24
  phone: z.string().optional().nullable(),
23
25
  specialRequests: z.string().optional().nullable(),
@@ -41,6 +43,11 @@ const EMPTY_PII_FORM = {
41
43
  dietaryRequirements: "",
42
44
  accessibilityNeeds: "",
43
45
  };
46
+ function normalizeTravelerCategory(value) {
47
+ return travelerCategories.includes(value)
48
+ ? value
49
+ : "adult";
50
+ }
44
51
  export function TravelerDialog({ open, onOpenChange, bookingId, traveler, onSuccess, }) {
45
52
  const isEditing = Boolean(traveler);
46
53
  const personId = traveler?.personId ?? null;
@@ -65,6 +72,7 @@ export function TravelerDialog({ open, onOpenChange, bookingId, traveler, onSucc
65
72
  defaultValues: {
66
73
  firstName: "",
67
74
  lastName: "",
75
+ travelerCategory: "adult",
68
76
  email: "",
69
77
  phone: "",
70
78
  specialRequests: "",
@@ -82,6 +90,7 @@ export function TravelerDialog({ open, onOpenChange, bookingId, traveler, onSucc
82
90
  form.reset({
83
91
  firstName: traveler.firstName,
84
92
  lastName: traveler.lastName,
93
+ travelerCategory: normalizeTravelerCategory(traveler.travelerCategory),
85
94
  email: traveler.email ?? "",
86
95
  phone: traveler.phone ?? "",
87
96
  specialRequests: traveler.specialRequests ?? "",
@@ -99,6 +108,7 @@ export function TravelerDialog({ open, onOpenChange, bookingId, traveler, onSucc
99
108
  form.reset({
100
109
  firstName: "",
101
110
  lastName: "",
111
+ travelerCategory: "adult",
102
112
  email: "",
103
113
  phone: "",
104
114
  specialRequests: "",
@@ -135,6 +145,7 @@ export function TravelerDialog({ open, onOpenChange, bookingId, traveler, onSucc
135
145
  specialRequests: values.specialRequests || null,
136
146
  isPrimary: traveler?.isPrimary ?? false,
137
147
  participantType: "traveler",
148
+ travelerCategory: values.travelerCategory,
138
149
  documentType: values.documentType,
139
150
  documentNumber: trimOrNull(values.documentNumber),
140
151
  documentExpiry: trimOrNull(values.documentExpiry),
@@ -238,7 +249,10 @@ export function TravelerDialog({ open, onOpenChange, bookingId, traveler, onSucc
238
249
  });
239
250
  return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { size: "lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: isEditing
240
251
  ? messages.travelerDialog.titles.edit
241
- : messages.travelerDialog.titles.create }) }), _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-1 flex-col overflow-hidden", children: [_jsxs(DialogBody, { className: "grid gap-4", children: [_jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.firstName }), _jsx(Input, { ...form.register("firstName"), placeholder: messages.travelerDialog.placeholders.firstName }), form.formState.errors.firstName && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.firstName.message }))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.lastName }), _jsx(Input, { ...form.register("lastName"), placeholder: messages.travelerDialog.placeholders.lastName }), form.formState.errors.lastName && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.lastName.message }))] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.email }), _jsx(Input, { ...form.register("email"), type: "email", placeholder: messages.travelerDialog.placeholders.email })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.phone }), _jsx(PhoneInput, { value: form.watch("phone") ?? "", onChange: (next) => form.setValue("phone", next, { shouldDirty: true }) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.specialRequests }), _jsx(Textarea, { ...form.register("specialRequests"), placeholder: messages.travelerDialog.placeholders.specialRequests })] }), _jsxs("div", { className: "flex flex-col gap-3 border-t pt-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("h3", { className: "text-sm font-semibold", children: messages.travelerDialog.fields.travelDetailsHeading }), personId ? (_jsxs(Button, { type: "button", variant: "ghost", size: "sm", disabled: !snapshot || snapshotQuery.isLoading, onClick: prefillFromProfile, children: [_jsx(Sparkles, { className: "mr-2 h-3.5 w-3.5" }), messages.travelerDialog.actions.prefillFromProfile] })) : null] }), prefilledNotice ? (_jsx("p", { className: "text-xs text-muted-foreground", children: messages.travelerDialog.hints.prefilledFromProfile })) : null, _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.documentType }), _jsxs(Select, { value: form.watch("documentType") ?? "passport", onValueChange: (nextValue) => form.setValue("documentType", nextValue, {
252
+ : messages.travelerDialog.titles.create }) }), _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-1 flex-col overflow-hidden", children: [_jsxs(DialogBody, { className: "grid gap-4", children: [_jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.firstName }), _jsx(Input, { ...form.register("firstName"), placeholder: messages.travelerDialog.placeholders.firstName }), form.formState.errors.firstName && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.firstName.message }))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.lastName }), _jsx(Input, { ...form.register("lastName"), placeholder: messages.travelerDialog.placeholders.lastName }), form.formState.errors.lastName && (_jsx("p", { className: "text-xs text-destructive", children: form.formState.errors.lastName.message }))] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.email }), _jsx(Input, { ...form.register("email"), type: "email", placeholder: messages.travelerDialog.placeholders.email })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.phone }), _jsx(PhoneInput, { value: form.watch("phone") ?? "", onChange: (next) => form.setValue("phone", next, { shouldDirty: true }) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.travelerCategory }), _jsxs(Select, { value: form.watch("travelerCategory") ?? "adult", onValueChange: (nextValue) => form.setValue("travelerCategory", nextValue, {
253
+ shouldDirty: true,
254
+ shouldValidate: true,
255
+ }), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: travelerCategories.map((category) => (_jsx(SelectItem, { value: category, children: messages.travelerDialog.travelerCategoryLabels[category] }, category))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.specialRequests }), _jsx(Textarea, { ...form.register("specialRequests"), placeholder: messages.travelerDialog.placeholders.specialRequests })] }), _jsxs("div", { className: "flex flex-col gap-3 border-t pt-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("h3", { className: "text-sm font-semibold", children: messages.travelerDialog.fields.travelDetailsHeading }), personId ? (_jsxs(Button, { type: "button", variant: "ghost", size: "sm", disabled: !snapshot || snapshotQuery.isLoading, onClick: prefillFromProfile, children: [_jsx(Sparkles, { className: "mr-2 h-3.5 w-3.5" }), messages.travelerDialog.actions.prefillFromProfile] })) : null] }), prefilledNotice ? (_jsx("p", { className: "text-xs text-muted-foreground", children: messages.travelerDialog.hints.prefilledFromProfile })) : null, _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.documentType }), _jsxs(Select, { value: form.watch("documentType") ?? "passport", onValueChange: (nextValue) => form.setValue("documentType", nextValue, {
242
256
  shouldDirty: true,
243
257
  shouldValidate: true,
244
258
  }), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: identityDocumentTypes.map((type) => (_jsx(SelectItem, { value: type, children: messages.travelerDialog.documentTypeLabels[type] }, type))) })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.documentNumber }), _jsx(Input, { ...form.register("documentNumber"), placeholder: messages.travelerDialog.placeholders.documentNumber })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: messages.travelerDialog.fields.documentExpiry }), _jsx(DatePicker, { value: form.watch("documentExpiry") || null, onChange: (nextValue) => form.setValue("documentExpiry", nextValue ?? "", {
@@ -1 +1 @@
1
- {"version":3,"file":"traveler-list.d.ts","sourceRoot":"","sources":["../../src/components/traveler-list.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAc9B,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,UAAkB,EAAE,EAAE,iBAAiB,qBA2RhF"}
1
+ {"version":3,"file":"traveler-list.d.ts","sourceRoot":"","sources":["../../src/components/traveler-list.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAc9B,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,UAAkB,EAAE,EAAE,iBAAiB,qBAiRhF"}
@@ -51,7 +51,7 @@ export function TravelerList({ bookingId, autoReveal = false }) {
51
51
  return next;
52
52
  });
53
53
  }, []);
54
- const isRevealed = React.useCallback((travelerId) => autoReveal || revealedIds.has(travelerId), [autoReveal, revealedIds]);
54
+ const isRevealed = React.useCallback((travelerId) => autoReveal || allAlreadyRevealed || revealedIds.has(travelerId), [allAlreadyRevealed, autoReveal, revealedIds]);
55
55
  const deleteMessages = messages.travelerList.actions.deleteConfirm;
56
56
  const handleConfirmDelete = async () => {
57
57
  if (!deleteTarget)
@@ -88,13 +88,7 @@ export function TravelerList({ bookingId, autoReveal = false }) {
88
88
  {
89
89
  id: "documents",
90
90
  header: messages.travelerList.columns.documents,
91
- cell: ({ row }) => {
92
- const documents = documentsByTraveler.get(row.original.id) ?? [];
93
- if (documents.length === 0) {
94
- return (_jsx("span", { className: "text-muted-foreground text-xs", children: messages.travelerList.values.documentsUnavailable }));
95
- }
96
- return (_jsxs("div", { className: "flex flex-wrap gap-1.5", children: [documents.slice(0, 2).map((document) => (_jsx(MiniPill, { children: document.type.replaceAll("_", " ") }, document.id))), documents.length > 2 ? _jsxs(MiniPill, { children: ["+", documents.length - 2] }) : null] }));
97
- },
91
+ cell: ({ row }) => (_jsx(TravelerDocumentsCell, { bookingId: bookingId, traveler: row.original, revealed: isRevealed(row.original.id), documents: documentsByTraveler.get(row.original.id) ?? [] })),
98
92
  },
99
93
  {
100
94
  id: "actions",
@@ -196,12 +190,35 @@ function RolePills({ traveler }) {
196
190
  const pills = [];
197
191
  if (traveler.isPrimary)
198
192
  pills.push(messages.travelerList.roles.primary);
199
- if (traveler.travelerCategory)
200
- pills.push(traveler.travelerCategory);
193
+ if (traveler.travelerCategory) {
194
+ pills.push(messages.travelerDialog.travelerCategoryLabels[traveler.travelerCategory] ?? traveler.travelerCategory);
195
+ }
201
196
  if (pills.length === 0)
202
197
  return _jsx("span", { className: "text-muted-foreground text-xs", children: "\u2014" });
203
198
  return (_jsx("div", { className: "flex flex-wrap gap-1.5", children: pills.map((label) => (_jsx(MiniPill, { children: label }, label))) }));
204
199
  }
200
+ function TravelerDocumentsCell({ bookingId, traveler, revealed, documents, }) {
201
+ const { travelDetails, loading } = useRevealed(bookingId, traveler, revealed);
202
+ const messages = useBookingsUiMessagesOrDefault();
203
+ const travelDocumentLabel = getTravelDocumentLabel(travelDetails, messages);
204
+ if (loading)
205
+ return _jsx(RowLoading, {});
206
+ if (!revealed && documents.length === 0) {
207
+ return (_jsx("span", { className: "text-muted-foreground text-xs", children: messages.travelerList.values.documentsHidden }));
208
+ }
209
+ if (documents.length === 0 && !travelDocumentLabel) {
210
+ return (_jsx("span", { className: "text-muted-foreground text-xs", children: messages.travelerList.values.documentsUnavailable }));
211
+ }
212
+ return (_jsxs("div", { className: "flex flex-wrap gap-1.5", children: [travelDocumentLabel ? _jsx(MiniPill, { children: travelDocumentLabel }) : null, documents.slice(0, travelDocumentLabel ? 1 : 2).map((document) => (_jsx(MiniPill, { children: document.type.replaceAll("_", " ") }, document.id))), documents.length > (travelDocumentLabel ? 1 : 2) ? (_jsxs(MiniPill, { children: ["+", documents.length - (travelDocumentLabel ? 1 : 2)] })) : null] }));
213
+ }
214
+ function getTravelDocumentLabel(travelDetails, messages) {
215
+ if (!travelDetails)
216
+ return null;
217
+ if (!travelDetails.documentNumber && !travelDetails.documentExpiry)
218
+ return null;
219
+ const documentType = travelDetails.documentType ?? "passport";
220
+ return messages.travelerDialog.documentTypeLabels[documentType];
221
+ }
205
222
  function TravelerSnapshotBody({ bookingId, traveler, documents, }) {
206
223
  const messages = useBookingsUiMessagesOrDefault();
207
224
  const labels = messages.travelerList.snapshot;
@@ -223,8 +240,9 @@ function TravelerSnapshotBody({ bookingId, traveler, documents, }) {
223
240
  roles.push(messages.travelerList.roles.primary);
224
241
  if (travelDetails?.isLeadTraveler)
225
242
  roles.push(messages.travelerList.roles.lead);
226
- if (display.travelerCategory)
227
- roles.push(display.travelerCategory);
243
+ if (display.travelerCategory) {
244
+ roles.push(messages.travelerDialog.travelerCategoryLabels[display.travelerCategory] ?? display.travelerCategory);
245
+ }
228
246
  return (_jsxs("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children: [loading ? (_jsx("div", { className: "py-4", children: _jsx(RowLoading, {}) })) : null, _jsxs(SnapshotSection, { title: labels.sectionContact, children: [_jsx(SnapshotRow, { label: labels.nameLabel, value: fullName }), _jsx(SnapshotRow, { label: labels.emailLabel, value: email }), _jsx(SnapshotRow, { label: labels.phoneLabel, value: phone }), _jsx(SnapshotRow, { label: labels.languageLabel, value: display.preferredLanguage || empty }), _jsx(SnapshotRow, { label: labels.roleLabel, value: roles.length > 0 ? (_jsx("div", { className: "flex flex-wrap gap-1.5", children: roles.map((label) => (_jsx(MiniPill, { children: label }, label))) })) : (empty) })] }), _jsxs(SnapshotSection, { title: labels.sectionTravel, children: [_jsx(SnapshotRow, { label: labels.dobLabel, value: formatDobAge(dob, empty) }), _jsx(SnapshotRow, { label: labels.nationalityLabel, value: travelDetails?.nationality || empty }), _jsx(SnapshotRow, { label: labels.documentLabel, value: documentValue }), _jsx(SnapshotRow, { label: labels.documentExpiryLabel, value: formatDateValue(travelDetails?.documentExpiry) ?? empty }), _jsx(SnapshotRow, { label: labels.dietaryLabel, value: travelDetails?.dietaryRequirements || empty, multiline: true }), _jsx(SnapshotRow, { label: labels.accessibilityLabel, value: travelDetails?.accessibilityNeeds || empty, multiline: true }), _jsx(SnapshotRow, { label: labels.specialRequestsLabel, value: display.specialRequests || empty, multiline: true }), _jsx(SnapshotRow, { label: labels.notesLabel, value: display.notes || empty, multiline: true })] }), _jsx(SnapshotSection, { title: labels.sectionDocuments, children: documents.length === 0 ? (_jsx("div", { className: "px-3 py-3 text-sm text-muted-foreground", children: labels.noDocuments })) : (documents.map((document) => (_jsx(SnapshotRow, { label: formatMessage(messages.travelerList.context.documentLabel, {
229
247
  type: document.type.replaceAll("_", " "),
230
248
  }), value: document.fileName }, document.id)))) }), _jsxs(SnapshotSection, { title: labels.sectionMeta, children: [_jsx(SnapshotRow, { label: labels.createdAtLabel, value: formatTimestamp(traveler.createdAt) ?? empty }), _jsx(SnapshotRow, { label: labels.updatedAtLabel, value: formatTimestamp(traveler.updatedAt) ?? empty })] })] }));
@@ -12,7 +12,7 @@ export declare function useSlotExtraManifestMutation(slotId: string): {
12
12
  productExtraId: string;
13
13
  optionExtraConfigId?: string | null | undefined;
14
14
  status?: "selected" | "cancelled" | "fulfilled" | "no_show" | undefined;
15
- collectionStatus?: "not_required" | "pending" | "collected" | "waived" | "refunded" | undefined;
15
+ collectionStatus?: "pending" | "not_required" | "collected" | "waived" | "refunded" | undefined;
16
16
  collectionCurrency?: string | null | undefined;
17
17
  collectionAmountCents?: number | null | undefined;
18
18
  notes?: string | null | undefined;
@@ -27,7 +27,7 @@ export declare function useSlotExtraManifestMutation(slotId: string): {
27
27
  productExtraId: string;
28
28
  optionExtraConfigId?: string | null | undefined;
29
29
  status?: "selected" | "cancelled" | "fulfilled" | "no_show" | undefined;
30
- collectionStatus?: "not_required" | "pending" | "collected" | "waived" | "refunded" | undefined;
30
+ collectionStatus?: "pending" | "not_required" | "collected" | "waived" | "refunded" | undefined;
31
31
  collectionCurrency?: string | null | undefined;
32
32
  collectionAmountCents?: number | null | undefined;
33
33
  notes?: string | null | undefined;
@@ -39,7 +39,7 @@ export declare function useSlotExtraManifestMutation(slotId: string): {
39
39
  }, Error, {
40
40
  productExtraId: string;
41
41
  travelerIds: string[];
42
- collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
42
+ collectionStatus: "pending" | "not_required" | "collected" | "waived" | "refunded";
43
43
  collectionCurrency?: string | null | undefined;
44
44
  collectionAmountCents?: number | null | undefined;
45
45
  notes?: string | null | undefined;
@@ -55,7 +55,7 @@ export declare function useSlotExtraManifest(slotId: string | null | undefined,
55
55
  status: "selected" | "cancelled" | "fulfilled" | "no_show";
56
56
  selected: boolean;
57
57
  collectionMode: "cash_on_trip" | "external" | "included" | "none" | "booking_total";
58
- collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
58
+ collectionStatus: "pending" | "not_required" | "collected" | "waived" | "refunded";
59
59
  collectionCurrency: string | null;
60
60
  collectionAmountCents: number | null;
61
61
  collectedAt: string | null;
@@ -243,7 +243,7 @@ export declare function getSlotExtraManifestQueryOptions(client: FetchWithValida
243
243
  status: "selected" | "cancelled" | "fulfilled" | "no_show";
244
244
  selected: boolean;
245
245
  collectionMode: "cash_on_trip" | "external" | "included" | "none" | "booking_total";
246
- collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
246
+ collectionStatus: "pending" | "not_required" | "collected" | "waived" | "refunded";
247
247
  collectionCurrency: string | null;
248
248
  collectionAmountCents: number | null;
249
249
  collectedAt: string | null;
@@ -307,7 +307,7 @@ export declare function getSlotExtraManifestQueryOptions(client: FetchWithValida
307
307
  status: "selected" | "cancelled" | "fulfilled" | "no_show";
308
308
  selected: boolean;
309
309
  collectionMode: "cash_on_trip" | "external" | "included" | "none" | "booking_total";
310
- collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
310
+ collectionStatus: "pending" | "not_required" | "collected" | "waived" | "refunded";
311
311
  collectionCurrency: string | null;
312
312
  collectionAmountCents: number | null;
313
313
  collectedAt: string | null;
@@ -372,7 +372,7 @@ export declare function getSlotExtraManifestQueryOptions(client: FetchWithValida
372
372
  status: "selected" | "cancelled" | "fulfilled" | "no_show";
373
373
  selected: boolean;
374
374
  collectionMode: "cash_on_trip" | "external" | "included" | "none" | "booking_total";
375
- collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
375
+ collectionStatus: "pending" | "not_required" | "collected" | "waived" | "refunded";
376
376
  collectionCurrency: string | null;
377
377
  collectionAmountCents: number | null;
378
378
  collectedAt: string | null;
@@ -439,7 +439,7 @@ export declare function getSlotExtraManifestQueryOptions(client: FetchWithValida
439
439
  status: "selected" | "cancelled" | "fulfilled" | "no_show";
440
440
  selected: boolean;
441
441
  collectionMode: "cash_on_trip" | "external" | "included" | "none" | "booking_total";
442
- collectionStatus: "not_required" | "pending" | "collected" | "waived" | "refunded";
442
+ collectionStatus: "pending" | "not_required" | "collected" | "waived" | "refunded";
443
443
  collectionCurrency: string | null;
444
444
  collectionAmountCents: number | null;
445
445
  collectedAt: string | null;
@@ -175,8 +175,8 @@ export declare const slotExtraManifestSelectionSchema: z.ZodObject<{
175
175
  booking_total: "booking_total";
176
176
  }>;
177
177
  collectionStatus: z.ZodEnum<{
178
- not_required: "not_required";
179
178
  pending: "pending";
179
+ not_required: "not_required";
180
180
  collected: "collected";
181
181
  waived: "waived";
182
182
  refunded: "refunded";
@@ -278,8 +278,8 @@ export declare const slotExtraManifestSchema: z.ZodObject<{
278
278
  booking_total: "booking_total";
279
279
  }>;
280
280
  collectionStatus: z.ZodEnum<{
281
- not_required: "not_required";
282
281
  pending: "pending";
282
+ not_required: "not_required";
283
283
  collected: "collected";
284
284
  waived: "waived";
285
285
  refunded: "refunded";
@@ -383,8 +383,8 @@ export declare const slotExtraManifestResponse: z.ZodObject<{
383
383
  booking_total: "booking_total";
384
384
  }>;
385
385
  collectionStatus: z.ZodEnum<{
386
- not_required: "not_required";
387
386
  pending: "pending";
387
+ not_required: "not_required";
388
388
  collected: "collected";
389
389
  waived: "waived";
390
390
  refunded: "refunded";
@@ -18,7 +18,7 @@ export declare function useBookingActionLedger(bookingId: string | null | undefi
18
18
  actionVersion: string;
19
19
  actionKind: "reverse" | "read" | "create" | "update" | "delete" | "execute" | "approve" | "reject" | "compensate" | "duplicate";
20
20
  status: "cancelled" | "expired" | "requested" | "awaiting_approval" | "approved" | "denied" | "succeeded" | "failed" | "reversed" | "compensated" | "superseded";
21
- evaluatedRisk: "low" | "medium" | "high" | "critical";
21
+ evaluatedRisk: "high" | "low" | "medium" | "critical";
22
22
  actorType: string | null;
23
23
  principalType: "user" | "api_key" | "agent" | "workflow" | "system";
24
24
  principalId: string;
@@ -16,7 +16,7 @@ export declare function useSupplierStatusMutation(bookingId: string): {
16
16
  bookingId: string;
17
17
  supplierServiceId: string | null;
18
18
  serviceName: string;
19
- status: "cancelled" | "pending" | "confirmed" | "rejected";
19
+ status: "pending" | "cancelled" | "confirmed" | "rejected";
20
20
  supplierReference: string | null;
21
21
  costCurrency: string;
22
22
  costAmountCents: number;
@@ -30,7 +30,7 @@ export declare function useSupplierStatusMutation(bookingId: string): {
30
30
  bookingId: string;
31
31
  supplierServiceId: string | null;
32
32
  serviceName: string;
33
- status: "cancelled" | "pending" | "confirmed" | "rejected";
33
+ status: "pending" | "cancelled" | "confirmed" | "rejected";
34
34
  supplierReference: string | null;
35
35
  costCurrency: string;
36
36
  costAmountCents: number;