@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.
- package/dist/components/booking-detail-page.d.ts.map +1 -1
- package/dist/components/booking-detail-page.js +3 -2
- package/dist/components/booking-dialog.d.ts.map +1 -1
- package/dist/components/booking-dialog.js +2 -19
- package/dist/components/booking-item-dialog.d.ts.map +1 -1
- package/dist/components/booking-item-dialog.js +16 -5
- package/dist/components/booking-item-list.d.ts +2 -1
- package/dist/components/booking-item-list.d.ts.map +1 -1
- package/dist/components/booking-item-list.js +13 -13
- package/dist/components/traveler-dialog.d.ts.map +1 -1
- package/dist/components/traveler-dialog.js +15 -1
- package/dist/components/traveler-list.d.ts.map +1 -1
- package/dist/components/traveler-list.js +30 -12
- package/dist/extras/hooks/use-slot-extra-manifest-mutation.d.ts +3 -3
- package/dist/extras/hooks/use-slot-extra-manifest.d.ts +1 -1
- package/dist/extras/query-options.d.ts +4 -4
- package/dist/extras/schemas.d.ts +3 -3
- package/dist/hooks/use-booking-action-ledger.d.ts +1 -1
- package/dist/hooks/use-supplier-status-mutation.d.ts +2 -2
- package/dist/hooks/use-supplier-statuses.d.ts +1 -1
- package/dist/i18n/en-base.d.ts +9 -0
- package/dist/i18n/en-base.d.ts.map +1 -1
- package/dist/i18n/en-base.js +9 -0
- package/dist/i18n/en-sections.d.ts +1 -0
- package/dist/i18n/en-sections.d.ts.map +1 -1
- package/dist/i18n/en-sections.js +1 -0
- package/dist/i18n/en.d.ts +10 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/messages-base.d.ts +3 -0
- package/dist/i18n/messages-base.d.ts.map +1 -1
- package/dist/i18n/messages-sections.d.ts +1 -0
- package/dist/i18n/messages-sections.d.ts.map +1 -1
- package/dist/i18n/provider.d.ts +20 -0
- package/dist/i18n/provider.d.ts.map +1 -1
- package/dist/i18n/ro-base.d.ts +9 -0
- package/dist/i18n/ro-base.d.ts.map +1 -1
- package/dist/i18n/ro-base.js +9 -0
- package/dist/i18n/ro-sections.d.ts +1 -0
- package/dist/i18n/ro-sections.d.ts.map +1 -1
- package/dist/i18n/ro-sections.js +1 -0
- package/dist/i18n/ro.d.ts +10 -0
- package/dist/i18n/ro.d.ts.map +1 -1
- package/dist/journey/components/booking-journey-rules.d.ts.map +1 -1
- package/dist/journey/components/booking-journey-rules.js +2 -2
- package/dist/query-options.d.ts +4 -4
- package/dist/requirements/hooks/use-booking-questions.d.ts +1 -1
- package/dist/requirements/query-options.d.ts +4 -4
- package/dist/requirements/schemas.d.ts +3 -3
- package/dist/schemas.d.ts +6 -6
- 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;
|
|
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:
|
|
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;
|
|
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
|
|
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 ??
|
|
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")
|
|
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")
|
|
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,
|
|
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,
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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;
|
|
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.
|
|
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,
|
|
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?: "
|
|
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?: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
442
|
+
collectionStatus: "pending" | "not_required" | "collected" | "waived" | "refunded";
|
|
443
443
|
collectionCurrency: string | null;
|
|
444
444
|
collectionAmountCents: number | null;
|
|
445
445
|
collectedAt: string | null;
|
package/dist/extras/schemas.d.ts
CHANGED
|
@@ -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: "
|
|
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: "
|
|
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: "
|
|
33
|
+
status: "pending" | "cancelled" | "confirmed" | "rejected";
|
|
34
34
|
supplierReference: string | null;
|
|
35
35
|
costCurrency: string;
|
|
36
36
|
costAmountCents: number;
|