@voyant-travel/bookings-react 0.119.3
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/LICENSE +201 -0
- package/README.md +87 -0
- package/dist/admin/booking-contract-dialog.d.ts +22 -0
- package/dist/admin/booking-contract-dialog.d.ts.map +1 -0
- package/dist/admin/booking-contract-dialog.js +161 -0
- package/dist/admin/booking-detail-host.d.ts +103 -0
- package/dist/admin/booking-detail-host.d.ts.map +1 -0
- package/dist/admin/booking-detail-host.js +127 -0
- package/dist/admin/booking-detail-skeleton.d.ts +7 -0
- package/dist/admin/booking-detail-skeleton.d.ts.map +1 -0
- package/dist/admin/booking-detail-skeleton.js +24 -0
- package/dist/admin/booking-documents-table.d.ts +13 -0
- package/dist/admin/booking-documents-table.d.ts.map +1 -0
- package/dist/admin/booking-documents-table.js +259 -0
- package/dist/admin/booking-invoice-sheet.d.ts +18 -0
- package/dist/admin/booking-invoice-sheet.d.ts.map +1 -0
- package/dist/admin/booking-invoice-sheet.js +101 -0
- package/dist/admin/booking-journey-host.d.ts +24 -0
- package/dist/admin/booking-journey-host.d.ts.map +1 -0
- package/dist/admin/booking-journey-host.js +278 -0
- package/dist/admin/bookings-host.d.ts +26 -0
- package/dist/admin/bookings-host.d.ts.map +1 -0
- package/dist/admin/bookings-host.js +18 -0
- package/dist/admin/bookings-list-skeleton.d.ts +10 -0
- package/dist/admin/bookings-list-skeleton.d.ts.map +1 -0
- package/dist/admin/bookings-list-skeleton.js +25 -0
- package/dist/admin/index.d.ts +273 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +331 -0
- package/dist/admin/journey-billing-duplicate-warning.d.ts +3 -0
- package/dist/admin/journey-billing-duplicate-warning.d.ts.map +1 -0
- package/dist/admin/journey-billing-duplicate-warning.js +26 -0
- package/dist/admin/journey-departure-picker.d.ts +7 -0
- package/dist/admin/journey-departure-picker.d.ts.map +1 -0
- package/dist/admin/journey-departure-picker.js +100 -0
- package/dist/admin/journey-units-picker.d.ts +11 -0
- package/dist/admin/journey-units-picker.d.ts.map +1 -0
- package/dist/admin/journey-units-picker.js +60 -0
- package/dist/admin/journey-voucher-picker.d.ts +3 -0
- package/dist/admin/journey-voucher-picker.d.ts.map +1 -0
- package/dist/admin/journey-voucher-picker.js +71 -0
- package/dist/admin/pages/booking-compose-page.d.ts +9 -0
- package/dist/admin/pages/booking-compose-page.d.ts.map +1 -0
- package/dist/admin/pages/booking-compose-page.js +17 -0
- package/dist/admin/pages/booking-detail-page.d.ts +11 -0
- package/dist/admin/pages/booking-detail-page.d.ts.map +1 -0
- package/dist/admin/pages/booking-detail-page.js +14 -0
- package/dist/admin/pages/booking-journey-page.d.ts +12 -0
- package/dist/admin/pages/booking-journey-page.d.ts.map +1 -0
- package/dist/admin/pages/booking-journey-page.js +26 -0
- package/dist/admin/pages/booking-new-page.d.ts +15 -0
- package/dist/admin/pages/booking-new-page.d.ts.map +1 -0
- package/dist/admin/pages/booking-new-page.js +50 -0
- package/dist/admin/pages/bookings-index-page.d.ts +20 -0
- package/dist/admin/pages/bookings-index-page.d.ts.map +1 -0
- package/dist/admin/pages/bookings-index-page.js +18 -0
- package/dist/admin/person-bookings-widget.d.ts +13 -0
- package/dist/admin/person-bookings-widget.d.ts.map +1 -0
- package/dist/admin/person-bookings-widget.js +48 -0
- package/dist/admin/slots.d.ts +31 -0
- package/dist/admin/slots.d.ts.map +1 -0
- package/dist/admin/slots.js +30 -0
- package/dist/admin/use-booking-action-ledger-events.d.ts +15 -0
- package/dist/admin/use-booking-action-ledger-events.d.ts.map +1 -0
- package/dist/admin/use-booking-action-ledger-events.js +66 -0
- package/dist/client.d.ts +14 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +59 -0
- package/dist/components/booking-activity-timeline.d.ts +32 -0
- package/dist/components/booking-activity-timeline.d.ts.map +1 -0
- package/dist/components/booking-activity-timeline.js +147 -0
- package/dist/components/booking-billing-dialog.d.ts +16 -0
- package/dist/components/booking-billing-dialog.d.ts.map +1 -0
- package/dist/components/booking-billing-dialog.js +315 -0
- package/dist/components/booking-cancellation-dialog.d.ts +18 -0
- package/dist/components/booking-cancellation-dialog.d.ts.map +1 -0
- package/dist/components/booking-cancellation-dialog.js +79 -0
- package/dist/components/booking-combobox.d.ts +13 -0
- package/dist/components/booking-combobox.d.ts.map +1 -0
- package/dist/components/booking-combobox.js +44 -0
- package/dist/components/booking-create-form-utils.d.ts +56 -0
- package/dist/components/booking-create-form-utils.d.ts.map +1 -0
- package/dist/components/booking-create-form-utils.js +216 -0
- package/dist/components/booking-create-page.d.ts +14 -0
- package/dist/components/booking-create-page.d.ts.map +1 -0
- package/dist/components/booking-create-page.js +11 -0
- package/dist/components/booking-create-preview-card.d.ts +26 -0
- package/dist/components/booking-create-preview-card.d.ts.map +1 -0
- package/dist/components/booking-create-preview-card.js +107 -0
- package/dist/components/booking-create-product-extras-picker.d.ts +18 -0
- package/dist/components/booking-create-product-extras-picker.d.ts.map +1 -0
- package/dist/components/booking-create-product-extras-picker.js +82 -0
- package/dist/components/booking-create-sheet.d.ts +34 -0
- package/dist/components/booking-create-sheet.d.ts.map +1 -0
- package/dist/components/booking-create-sheet.js +811 -0
- package/dist/components/booking-create-utils.d.ts +66 -0
- package/dist/components/booking-create-utils.d.ts.map +1 -0
- package/dist/components/booking-create-utils.js +185 -0
- package/dist/components/booking-detail-page.d.ts +126 -0
- package/dist/components/booking-detail-page.d.ts.map +1 -0
- package/dist/components/booking-detail-page.js +264 -0
- package/dist/components/booking-dialog.d.ts +28 -0
- package/dist/components/booking-dialog.d.ts.map +1 -0
- package/dist/components/booking-dialog.js +130 -0
- package/dist/components/booking-document-dialog.d.ts +8 -0
- package/dist/components/booking-document-dialog.d.ts.map +1 -0
- package/dist/components/booking-document-dialog.js +83 -0
- package/dist/components/booking-document-list.d.ts +5 -0
- package/dist/components/booking-document-list.d.ts.map +1 -0
- package/dist/components/booking-document-list.js +43 -0
- package/dist/components/booking-group-link-dialog.d.ts +10 -0
- package/dist/components/booking-group-link-dialog.d.ts.map +1 -0
- package/dist/components/booking-group-link-dialog.js +79 -0
- package/dist/components/booking-group-section.d.ts +27 -0
- package/dist/components/booking-group-section.d.ts.map +1 -0
- package/dist/components/booking-group-section.js +51 -0
- package/dist/components/booking-guarantee-dialog.d.ts +10 -0
- package/dist/components/booking-guarantee-dialog.d.ts.map +1 -0
- package/dist/components/booking-guarantee-dialog.js +123 -0
- package/dist/components/booking-guarantee-list.d.ts +5 -0
- package/dist/components/booking-guarantee-list.d.ts.map +1 -0
- package/dist/components/booking-guarantee-list.js +86 -0
- package/dist/components/booking-item-dialog.d.ts +10 -0
- package/dist/components/booking-item-dialog.d.ts.map +1 -0
- package/dist/components/booking-item-dialog.js +155 -0
- package/dist/components/booking-item-list.d.ts +12 -0
- package/dist/components/booking-item-list.d.ts.map +1 -0
- package/dist/components/booking-item-list.js +191 -0
- package/dist/components/booking-item-travelers.d.ts +6 -0
- package/dist/components/booking-item-travelers.d.ts.map +1 -0
- package/dist/components/booking-item-travelers.js +57 -0
- package/dist/components/booking-list-filters.d.ts +43 -0
- package/dist/components/booking-list-filters.d.ts.map +1 -0
- package/dist/components/booking-list-filters.js +192 -0
- package/dist/components/booking-list.d.ts +50 -0
- package/dist/components/booking-list.d.ts.map +1 -0
- package/dist/components/booking-list.js +352 -0
- package/dist/components/booking-note-dialog.d.ts +16 -0
- package/dist/components/booking-note-dialog.d.ts.map +1 -0
- package/dist/components/booking-note-dialog.js +41 -0
- package/dist/components/booking-notes.d.ts +5 -0
- package/dist/components/booking-notes.d.ts.map +1 -0
- package/dist/components/booking-notes.js +45 -0
- package/dist/components/booking-payment-reconciliation-banner.d.ts +5 -0
- package/dist/components/booking-payment-reconciliation-banner.d.ts.map +1 -0
- package/dist/components/booking-payment-reconciliation-banner.js +91 -0
- package/dist/components/booking-payment-schedule-dialog.d.ts +10 -0
- package/dist/components/booking-payment-schedule-dialog.d.ts.map +1 -0
- package/dist/components/booking-payment-schedule-dialog.js +117 -0
- package/dist/components/booking-payment-schedule-list.d.ts +10 -0
- package/dist/components/booking-payment-schedule-list.d.ts.map +1 -0
- package/dist/components/booking-payment-schedule-list.js +217 -0
- package/dist/components/booking-payments-summary.d.ts +83 -0
- package/dist/components/booking-payments-summary.d.ts.map +1 -0
- package/dist/components/booking-payments-summary.js +176 -0
- package/dist/components/booking-quick-view-sheet.d.ts +14 -0
- package/dist/components/booking-quick-view-sheet.d.ts.map +1 -0
- package/dist/components/booking-quick-view-sheet.js +283 -0
- package/dist/components/bookings-page.d.ts +19 -0
- package/dist/components/bookings-page.d.ts.map +1 -0
- package/dist/components/bookings-page.js +9 -0
- package/dist/components/file-dropzone.d.ts +25 -0
- package/dist/components/file-dropzone.d.ts.map +1 -0
- package/dist/components/file-dropzone.js +102 -0
- package/dist/components/icon-action-button.d.ts +18 -0
- package/dist/components/icon-action-button.d.ts.map +1 -0
- package/dist/components/icon-action-button.js +13 -0
- package/dist/components/option-units-stepper-section.d.ts +111 -0
- package/dist/components/option-units-stepper-section.d.ts.map +1 -0
- package/dist/components/option-units-stepper-section.js +276 -0
- package/dist/components/payment-schedule-section.d.ts +91 -0
- package/dist/components/payment-schedule-section.d.ts.map +1 -0
- package/dist/components/payment-schedule-section.js +206 -0
- package/dist/components/person-picker-section.d.ts +71 -0
- package/dist/components/person-picker-section.d.ts.map +1 -0
- package/dist/components/person-picker-section.js +160 -0
- package/dist/components/price-breakdown-section.d.ts +83 -0
- package/dist/components/price-breakdown-section.d.ts.map +1 -0
- package/dist/components/price-breakdown-section.js +278 -0
- package/dist/components/product-picker-section.d.ts +29 -0
- package/dist/components/product-picker-section.d.ts.map +1 -0
- package/dist/components/product-picker-section.js +74 -0
- package/dist/components/shared-room-section.d.ts +40 -0
- package/dist/components/shared-room-section.d.ts.map +1 -0
- package/dist/components/shared-room-section.js +99 -0
- package/dist/components/status-badge.d.ts +24 -0
- package/dist/components/status-badge.d.ts.map +1 -0
- package/dist/components/status-badge.js +65 -0
- package/dist/components/status-change-dialog.d.ts +10 -0
- package/dist/components/status-change-dialog.d.ts.map +1 -0
- package/dist/components/status-change-dialog.js +57 -0
- package/dist/components/supplier-status-dialog.d.ts +10 -0
- package/dist/components/supplier-status-dialog.d.ts.map +1 -0
- package/dist/components/supplier-status-dialog.js +98 -0
- package/dist/components/supplier-status-list.d.ts +5 -0
- package/dist/components/supplier-status-list.d.ts.map +1 -0
- package/dist/components/supplier-status-list.js +115 -0
- package/dist/components/traveler-category-buttons.d.ts +26 -0
- package/dist/components/traveler-category-buttons.d.ts.map +1 -0
- package/dist/components/traveler-category-buttons.js +35 -0
- package/dist/components/traveler-dialog.d.ts +10 -0
- package/dist/components/traveler-dialog.d.ts.map +1 -0
- package/dist/components/traveler-dialog.js +256 -0
- package/dist/components/traveler-list.d.ts +6 -0
- package/dist/components/traveler-list.d.ts.map +1 -0
- package/dist/components/traveler-list.js +295 -0
- package/dist/components/travelers-section-controls.d.ts +52 -0
- package/dist/components/travelers-section-controls.d.ts.map +1 -0
- package/dist/components/travelers-section-controls.js +206 -0
- package/dist/components/travelers-section.d.ts +159 -0
- package/dist/components/travelers-section.d.ts.map +1 -0
- package/dist/components/travelers-section.js +355 -0
- package/dist/components/voucher-picker-section.d.ts +50 -0
- package/dist/components/voucher-picker-section.d.ts.map +1 -0
- package/dist/components/voucher-picker-section.js +79 -0
- package/dist/extras/client.d.ts +14 -0
- package/dist/extras/client.d.ts.map +1 -0
- package/dist/extras/client.js +58 -0
- package/dist/extras/components/extra-catalog-card.d.ts +13 -0
- package/dist/extras/components/extra-catalog-card.d.ts.map +1 -0
- package/dist/extras/components/extra-catalog-card.js +52 -0
- package/dist/extras/components/product-combobox.d.ts +9 -0
- package/dist/extras/components/product-combobox.d.ts.map +1 -0
- package/dist/extras/components/product-combobox.js +46 -0
- package/dist/extras/components/slot-extras-manifest-panel.d.ts +6 -0
- package/dist/extras/components/slot-extras-manifest-panel.d.ts.map +1 -0
- package/dist/extras/components/slot-extras-manifest-panel.js +108 -0
- package/dist/extras/hooks/index.d.ts +5 -0
- package/dist/extras/hooks/index.d.ts.map +1 -0
- package/dist/extras/hooks/index.js +4 -0
- package/dist/extras/hooks/use-product-extra.d.ts +24 -0
- package/dist/extras/hooks/use-product-extra.d.ts.map +1 -0
- package/dist/extras/hooks/use-product-extra.js +12 -0
- package/dist/extras/hooks/use-product-extras.d.ts +30 -0
- package/dist/extras/hooks/use-product-extras.d.ts.map +1 -0
- package/dist/extras/hooks/use-product-extras.js +12 -0
- package/dist/extras/hooks/use-slot-extra-manifest-mutation.d.ts +48 -0
- package/dist/extras/hooks/use-slot-extra-manifest-mutation.d.ts.map +1 -0
- package/dist/extras/hooks/use-slot-extra-manifest-mutation.js +26 -0
- package/dist/extras/hooks/use-slot-extra-manifest.d.ts +68 -0
- package/dist/extras/hooks/use-slot-extra-manifest.d.ts.map +1 -0
- package/dist/extras/hooks/use-slot-extra-manifest.js +11 -0
- package/dist/extras/i18n/en.d.ts +52 -0
- package/dist/extras/i18n/en.d.ts.map +1 -0
- package/dist/extras/i18n/en.js +51 -0
- package/dist/extras/i18n/index.d.ts +5 -0
- package/dist/extras/i18n/index.d.ts.map +1 -0
- package/dist/extras/i18n/index.js +3 -0
- package/dist/extras/i18n/messages.d.ts +37 -0
- package/dist/extras/i18n/messages.d.ts.map +1 -0
- package/dist/extras/i18n/messages.js +1 -0
- package/dist/extras/i18n/provider.d.ts +126 -0
- package/dist/extras/i18n/provider.d.ts.map +1 -0
- package/dist/extras/i18n/provider.js +44 -0
- package/dist/extras/i18n/ro.d.ts +52 -0
- package/dist/extras/i18n/ro.d.ts.map +1 -0
- package/dist/extras/i18n/ro.js +51 -0
- package/dist/extras/index.d.ts +7 -0
- package/dist/extras/index.d.ts.map +1 -0
- package/dist/extras/index.js +6 -0
- package/dist/extras/provider.d.ts +2 -0
- package/dist/extras/provider.d.ts.map +1 -0
- package/dist/extras/provider.js +1 -0
- package/dist/extras/query-keys.d.ts +16 -0
- package/dist/extras/query-keys.d.ts.map +1 -0
- package/dist/extras/query-keys.js +8 -0
- package/dist/extras/query-options.d.ts +455 -0
- package/dist/extras/query-options.d.ts.map +1 -0
- package/dist/extras/query-options.js +44 -0
- package/dist/extras/schemas.d.ts +416 -0
- package/dist/extras/schemas.d.ts.map +1 -0
- package/dist/extras/schemas.js +89 -0
- package/dist/extras/ui.d.ts +4 -0
- package/dist/extras/ui.d.ts.map +1 -0
- package/dist/extras/ui.js +3 -0
- package/dist/extras.d.ts +10 -0
- package/dist/extras.d.ts.map +1 -0
- package/dist/extras.js +9 -0
- package/dist/hooks/index.d.ts +36 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +35 -0
- package/dist/hooks/use-booking-action-ledger.d.ts +63 -0
- package/dist/hooks/use-booking-action-ledger.d.ts.map +1 -0
- package/dist/hooks/use-booking-action-ledger.js +34 -0
- package/dist/hooks/use-booking-activity.d.ts +17 -0
- package/dist/hooks/use-booking-activity.d.ts.map +1 -0
- package/dist/hooks/use-booking-activity.js +12 -0
- package/dist/hooks/use-booking-cancel-mutation.d.ts +69 -0
- package/dist/hooks/use-booking-cancel-mutation.d.ts.map +1 -0
- package/dist/hooks/use-booking-cancel-mutation.js +24 -0
- package/dist/hooks/use-booking-contract-generation.d.ts +31 -0
- package/dist/hooks/use-booking-contract-generation.d.ts.map +1 -0
- package/dist/hooks/use-booking-contract-generation.js +36 -0
- package/dist/hooks/use-booking-convert-mutation.d.ts +81 -0
- package/dist/hooks/use-booking-convert-mutation.d.ts.map +1 -0
- package/dist/hooks/use-booking-convert-mutation.js +24 -0
- package/dist/hooks/use-booking-create-mutation.d.ts +337 -0
- package/dist/hooks/use-booking-create-mutation.d.ts.map +1 -0
- package/dist/hooks/use-booking-create-mutation.js +43 -0
- package/dist/hooks/use-booking-documents.d.ts +41 -0
- package/dist/hooks/use-booking-documents.d.ts.map +1 -0
- package/dist/hooks/use-booking-documents.js +46 -0
- package/dist/hooks/use-booking-dual-create-mutation.d.ts +338 -0
- package/dist/hooks/use-booking-dual-create-mutation.d.ts.map +1 -0
- package/dist/hooks/use-booking-dual-create-mutation.js +45 -0
- package/dist/hooks/use-booking-group-for-booking.d.ts +24 -0
- package/dist/hooks/use-booking-group-for-booking.d.ts.map +1 -0
- package/dist/hooks/use-booking-group-for-booking.js +12 -0
- package/dist/hooks/use-booking-group-member-mutation.d.ts +27 -0
- package/dist/hooks/use-booking-group-member-mutation.d.ts.map +1 -0
- package/dist/hooks/use-booking-group-member-mutation.js +38 -0
- package/dist/hooks/use-booking-group-mutation.d.ts +40 -0
- package/dist/hooks/use-booking-group-mutation.d.ts.map +1 -0
- package/dist/hooks/use-booking-group-mutation.js +32 -0
- package/dist/hooks/use-booking-group.d.ts +85 -0
- package/dist/hooks/use-booking-group.d.ts.map +1 -0
- package/dist/hooks/use-booking-group.js +12 -0
- package/dist/hooks/use-booking-groups.d.ts +21 -0
- package/dist/hooks/use-booking-groups.d.ts.map +1 -0
- package/dist/hooks/use-booking-groups.js +12 -0
- package/dist/hooks/use-booking-item-mutation.d.ts +101 -0
- package/dist/hooks/use-booking-item-mutation.d.ts.map +1 -0
- package/dist/hooks/use-booking-item-mutation.js +42 -0
- package/dist/hooks/use-booking-item-travelers.d.ts +32 -0
- package/dist/hooks/use-booking-item-travelers.d.ts.map +1 -0
- package/dist/hooks/use-booking-item-travelers.js +48 -0
- package/dist/hooks/use-booking-items.d.ts +36 -0
- package/dist/hooks/use-booking-items.d.ts.map +1 -0
- package/dist/hooks/use-booking-items.js +12 -0
- package/dist/hooks/use-booking-mutation.d.ts +158 -0
- package/dist/hooks/use-booking-mutation.d.ts.map +1 -0
- package/dist/hooks/use-booking-mutation.js +39 -0
- package/dist/hooks/use-booking-note-mutation.d.ts +39 -0
- package/dist/hooks/use-booking-note-mutation.d.ts.map +1 -0
- package/dist/hooks/use-booking-note-mutation.js +44 -0
- package/dist/hooks/use-booking-notes.d.ts +15 -0
- package/dist/hooks/use-booking-notes.d.ts.map +1 -0
- package/dist/hooks/use-booking-notes.js +12 -0
- package/dist/hooks/use-booking-primary-product.d.ts +28 -0
- package/dist/hooks/use-booking-primary-product.d.ts.map +1 -0
- package/dist/hooks/use-booking-primary-product.js +20 -0
- package/dist/hooks/use-booking-status-mutation.d.ts +156 -0
- package/dist/hooks/use-booking-status-mutation.d.ts.map +1 -0
- package/dist/hooks/use-booking-status-mutation.js +54 -0
- package/dist/hooks/use-booking-tax-preview.d.ts +29 -0
- package/dist/hooks/use-booking-tax-preview.d.ts.map +1 -0
- package/dist/hooks/use-booking-tax-preview.js +21 -0
- package/dist/hooks/use-booking.d.ts +67 -0
- package/dist/hooks/use-booking.d.ts.map +1 -0
- package/dist/hooks/use-booking.js +12 -0
- package/dist/hooks/use-bookings.d.ts +71 -0
- package/dist/hooks/use-bookings.d.ts.map +1 -0
- package/dist/hooks/use-bookings.js +12 -0
- package/dist/hooks/use-pricing-preview.d.ts +61 -0
- package/dist/hooks/use-pricing-preview.d.ts.map +1 -0
- package/dist/hooks/use-pricing-preview.js +18 -0
- package/dist/hooks/use-public-booking-session-flow-mutation.d.ts +148 -0
- package/dist/hooks/use-public-booking-session-flow-mutation.d.ts.map +1 -0
- package/dist/hooks/use-public-booking-session-flow-mutation.js +35 -0
- package/dist/hooks/use-public-booking-session-state.d.ts +16 -0
- package/dist/hooks/use-public-booking-session-state.d.ts.map +1 -0
- package/dist/hooks/use-public-booking-session-state.js +12 -0
- package/dist/hooks/use-public-booking-session.d.ts +101 -0
- package/dist/hooks/use-public-booking-session.d.ts.map +1 -0
- package/dist/hooks/use-public-booking-session.js +12 -0
- package/dist/hooks/use-reveal-traveler.d.ts +54 -0
- package/dist/hooks/use-reveal-traveler.d.ts.map +1 -0
- package/dist/hooks/use-reveal-traveler.js +18 -0
- package/dist/hooks/use-sharing-groups.d.ts +41 -0
- package/dist/hooks/use-sharing-groups.d.ts.map +1 -0
- package/dist/hooks/use-sharing-groups.js +20 -0
- package/dist/hooks/use-supplier-status-mutation.d.ts +46 -0
- package/dist/hooks/use-supplier-status-mutation.d.ts.map +1 -0
- package/dist/hooks/use-supplier-status-mutation.js +39 -0
- package/dist/hooks/use-supplier-statuses.d.ts +20 -0
- package/dist/hooks/use-supplier-statuses.d.ts.map +1 -0
- package/dist/hooks/use-supplier-statuses.js +12 -0
- package/dist/hooks/use-traveler-mutation.d.ts +55 -0
- package/dist/hooks/use-traveler-mutation.d.ts.map +1 -0
- package/dist/hooks/use-traveler-mutation.js +42 -0
- package/dist/hooks/use-traveler-with-travel-details-mutation.d.ts +120 -0
- package/dist/hooks/use-traveler-with-travel-details-mutation.d.ts.map +1 -0
- package/dist/hooks/use-traveler-with-travel-details-mutation.js +43 -0
- package/dist/hooks/use-travelers.d.ts +23 -0
- package/dist/hooks/use-travelers.d.ts.map +1 -0
- package/dist/hooks/use-travelers.js +12 -0
- package/dist/i18n/en-base.d.ts +295 -0
- package/dist/i18n/en-base.d.ts.map +1 -0
- package/dist/i18n/en-base.js +294 -0
- package/dist/i18n/en-create-list.d.ts +327 -0
- package/dist/i18n/en-create-list.d.ts.map +1 -0
- package/dist/i18n/en-create-list.js +326 -0
- package/dist/i18n/en-journey.d.ts +229 -0
- package/dist/i18n/en-journey.d.ts.map +1 -0
- package/dist/i18n/en-journey.js +228 -0
- package/dist/i18n/en-operations.d.ts +382 -0
- package/dist/i18n/en-operations.d.ts.map +1 -0
- package/dist/i18n/en-operations.js +381 -0
- package/dist/i18n/en-sections.d.ts +360 -0
- package/dist/i18n/en-sections.d.ts.map +1 -0
- package/dist/i18n/en-sections.js +359 -0
- package/dist/i18n/en.d.ts +1581 -0
- package/dist/i18n/en.d.ts.map +1 -0
- package/dist/i18n/en.js +12 -0
- package/dist/i18n/index.d.ts +5 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +3 -0
- package/dist/i18n/messages-base.d.ts +251 -0
- package/dist/i18n/messages-base.d.ts.map +1 -0
- package/dist/i18n/messages-base.js +1 -0
- package/dist/i18n/messages-create-list.d.ts +310 -0
- package/dist/i18n/messages-create-list.d.ts.map +1 -0
- package/dist/i18n/messages-create-list.js +1 -0
- package/dist/i18n/messages-journey.d.ts +198 -0
- package/dist/i18n/messages-journey.d.ts.map +1 -0
- package/dist/i18n/messages-journey.js +1 -0
- package/dist/i18n/messages-operations.d.ts +362 -0
- package/dist/i18n/messages-operations.d.ts.map +1 -0
- package/dist/i18n/messages-operations.js +1 -0
- package/dist/i18n/messages-sections.d.ts +312 -0
- package/dist/i18n/messages-sections.d.ts.map +1 -0
- package/dist/i18n/messages-sections.js +1 -0
- package/dist/i18n/messages.d.ts +7 -0
- package/dist/i18n/messages.d.ts.map +1 -0
- package/dist/i18n/messages.js +1 -0
- package/dist/i18n/provider.d.ts +3185 -0
- package/dist/i18n/provider.d.ts.map +1 -0
- package/dist/i18n/provider.js +45 -0
- package/dist/i18n/ro-base.d.ts +295 -0
- package/dist/i18n/ro-base.d.ts.map +1 -0
- package/dist/i18n/ro-base.js +294 -0
- package/dist/i18n/ro-create-list.d.ts +327 -0
- package/dist/i18n/ro-create-list.d.ts.map +1 -0
- package/dist/i18n/ro-create-list.js +326 -0
- package/dist/i18n/ro-journey.d.ts +229 -0
- package/dist/i18n/ro-journey.d.ts.map +1 -0
- package/dist/i18n/ro-journey.js +228 -0
- package/dist/i18n/ro-operations.d.ts +382 -0
- package/dist/i18n/ro-operations.d.ts.map +1 -0
- package/dist/i18n/ro-operations.js +381 -0
- package/dist/i18n/ro-sections.d.ts +360 -0
- package/dist/i18n/ro-sections.d.ts.map +1 -0
- package/dist/i18n/ro-sections.js +359 -0
- package/dist/i18n/ro.d.ts +1581 -0
- package/dist/i18n/ro.d.ts.map +1 -0
- package/dist/i18n/ro.js +12 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/journey/components/booking-journey-rules.d.ts +48 -0
- package/dist/journey/components/booking-journey-rules.d.ts.map +1 -0
- package/dist/journey/components/booking-journey-rules.js +235 -0
- package/dist/journey/components/booking-journey.d.ts +3 -0
- package/dist/journey/components/booking-journey.d.ts.map +1 -0
- package/dist/journey/components/booking-journey.js +368 -0
- package/dist/journey/components/configure-step-skeleton.d.ts +8 -0
- package/dist/journey/components/configure-step-skeleton.d.ts.map +1 -0
- package/dist/journey/components/configure-step-skeleton.js +11 -0
- package/dist/journey/components/contract-preview-dialog.d.ts +47 -0
- package/dist/journey/components/contract-preview-dialog.d.ts.map +1 -0
- package/dist/journey/components/contract-preview-dialog.js +124 -0
- package/dist/journey/components/journey-steps/accommodation-step.d.ts +3 -0
- package/dist/journey/components/journey-steps/accommodation-step.d.ts.map +1 -0
- package/dist/journey/components/journey-steps/accommodation-step.js +71 -0
- package/dist/journey/components/journey-steps/addons-step.d.ts +3 -0
- package/dist/journey/components/journey-steps/addons-step.d.ts.map +1 -0
- package/dist/journey/components/journey-steps/addons-step.js +40 -0
- package/dist/journey/components/journey-steps/billing-step.d.ts +8 -0
- package/dist/journey/components/journey-steps/billing-step.d.ts.map +1 -0
- package/dist/journey/components/journey-steps/billing-step.js +78 -0
- package/dist/journey/components/journey-steps/configure-steps.d.ts +28 -0
- package/dist/journey/components/journey-steps/configure-steps.d.ts.map +1 -0
- package/dist/journey/components/journey-steps/configure-steps.js +232 -0
- package/dist/journey/components/journey-steps/documents-step.d.ts +11 -0
- package/dist/journey/components/journey-steps/documents-step.d.ts.map +1 -0
- package/dist/journey/components/journey-steps/documents-step.js +36 -0
- package/dist/journey/components/journey-steps/payment-step.d.ts +29 -0
- package/dist/journey/components/journey-steps/payment-step.d.ts.map +1 -0
- package/dist/journey/components/journey-steps/payment-step.js +225 -0
- package/dist/journey/components/journey-steps/review-step.d.ts +27 -0
- package/dist/journey/components/journey-steps/review-step.d.ts.map +1 -0
- package/dist/journey/components/journey-steps/review-step.js +18 -0
- package/dist/journey/components/journey-steps/shared.d.ts +75 -0
- package/dist/journey/components/journey-steps/shared.d.ts.map +1 -0
- package/dist/journey/components/journey-steps/shared.js +108 -0
- package/dist/journey/components/journey-steps/travelers-step.d.ts +7 -0
- package/dist/journey/components/journey-steps/travelers-step.d.ts.map +1 -0
- package/dist/journey/components/journey-steps/travelers-step.js +201 -0
- package/dist/journey/components/journey-steps.d.ts +21 -0
- package/dist/journey/components/journey-steps.d.ts.map +1 -0
- package/dist/journey/components/journey-steps.js +20 -0
- package/dist/journey/components/side-panel.d.ts +17 -0
- package/dist/journey/components/side-panel.d.ts.map +1 -0
- package/dist/journey/components/side-panel.js +245 -0
- package/dist/journey/components/stacked-journey.d.ts +30 -0
- package/dist/journey/components/stacked-journey.d.ts.map +1 -0
- package/dist/journey/components/stacked-journey.js +50 -0
- package/dist/journey/components/step-header.d.ts +7 -0
- package/dist/journey/components/step-header.d.ts.map +1 -0
- package/dist/journey/components/step-header.js +12 -0
- package/dist/journey/index.d.ts +18 -0
- package/dist/journey/index.d.ts.map +1 -0
- package/dist/journey/index.js +17 -0
- package/dist/journey/lib/draft-state.d.ts +35 -0
- package/dist/journey/lib/draft-state.d.ts.map +1 -0
- package/dist/journey/lib/draft-state.js +57 -0
- package/dist/journey/lib/pax-band-dependencies.d.ts +27 -0
- package/dist/journey/lib/pax-band-dependencies.d.ts.map +1 -0
- package/dist/journey/lib/pax-band-dependencies.js +50 -0
- package/dist/journey/lib/payment-schedule.d.ts +19 -0
- package/dist/journey/lib/payment-schedule.d.ts.map +1 -0
- package/dist/journey/lib/payment-schedule.js +90 -0
- package/dist/journey/types.d.ts +403 -0
- package/dist/journey/types.d.ts.map +1 -0
- package/dist/journey/types.js +19 -0
- package/dist/provider.d.ts +2 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +1 -0
- package/dist/query-keys.d.ts +74 -0
- package/dist/query-keys.d.ts.map +1 -0
- package/dist/query-keys.js +26 -0
- package/dist/query-options.d.ts +2534 -0
- package/dist/query-options.d.ts.map +1 -0
- package/dist/query-options.js +233 -0
- package/dist/requirements/client.d.ts +14 -0
- package/dist/requirements/client.d.ts.map +1 -0
- package/dist/requirements/client.js +59 -0
- package/dist/requirements/components/booking-requirements-contact-tab.d.ts +8 -0
- package/dist/requirements/components/booking-requirements-contact-tab.d.ts.map +1 -0
- package/dist/requirements/components/booking-requirements-contact-tab.js +8 -0
- package/dist/requirements/components/booking-requirements-questions-tab.d.ts +14 -0
- package/dist/requirements/components/booking-requirements-questions-tab.d.ts.map +1 -0
- package/dist/requirements/components/booking-requirements-questions-tab.js +17 -0
- package/dist/requirements/constants.d.ts +114 -0
- package/dist/requirements/constants.d.ts.map +1 -0
- package/dist/requirements/constants.js +45 -0
- package/dist/requirements/hooks/index.d.ts +6 -0
- package/dist/requirements/hooks/index.d.ts.map +1 -0
- package/dist/requirements/hooks/index.js +6 -0
- package/dist/requirements/hooks/use-booking-questions.d.ts +24 -0
- package/dist/requirements/hooks/use-booking-questions.d.ts.map +1 -0
- package/dist/requirements/hooks/use-booking-questions.js +9 -0
- package/dist/requirements/hooks/use-contact-requirements.d.ts +22 -0
- package/dist/requirements/hooks/use-contact-requirements.d.ts.map +1 -0
- package/dist/requirements/hooks/use-contact-requirements.js +9 -0
- package/dist/requirements/hooks/use-products.d.ts +16 -0
- package/dist/requirements/hooks/use-products.d.ts.map +1 -0
- package/dist/requirements/hooks/use-products.js +9 -0
- package/dist/requirements/hooks/use-question-options.d.ts +19 -0
- package/dist/requirements/hooks/use-question-options.d.ts.map +1 -0
- package/dist/requirements/hooks/use-question-options.js +9 -0
- package/dist/requirements/hooks/use-transport-requirements.d.ts +30 -0
- package/dist/requirements/hooks/use-transport-requirements.d.ts.map +1 -0
- package/dist/requirements/hooks/use-transport-requirements.js +9 -0
- package/dist/requirements/i18n/en.d.ts +94 -0
- package/dist/requirements/i18n/en.d.ts.map +1 -0
- package/dist/requirements/i18n/en.js +93 -0
- package/dist/requirements/i18n/index.d.ts +5 -0
- package/dist/requirements/i18n/index.d.ts.map +1 -0
- package/dist/requirements/i18n/index.js +3 -0
- package/dist/requirements/i18n/messages.d.ts +59 -0
- package/dist/requirements/i18n/messages.d.ts.map +1 -0
- package/dist/requirements/i18n/messages.js +1 -0
- package/dist/requirements/i18n/provider.d.ts +210 -0
- package/dist/requirements/i18n/provider.d.ts.map +1 -0
- package/dist/requirements/i18n/provider.js +44 -0
- package/dist/requirements/i18n/ro.d.ts +94 -0
- package/dist/requirements/i18n/ro.d.ts.map +1 -0
- package/dist/requirements/i18n/ro.js +93 -0
- package/dist/requirements/index.d.ts +9 -0
- package/dist/requirements/index.d.ts.map +1 -0
- package/dist/requirements/index.js +8 -0
- package/dist/requirements/provider.d.ts +2 -0
- package/dist/requirements/provider.d.ts.map +1 -0
- package/dist/requirements/provider.js +1 -0
- package/dist/requirements/query-keys.d.ts +33 -0
- package/dist/requirements/query-keys.d.ts.map +1 -0
- package/dist/requirements/query-keys.js +13 -0
- package/dist/requirements/query-options.d.ts +371 -0
- package/dist/requirements/query-options.d.ts.map +1 -0
- package/dist/requirements/query-options.js +80 -0
- package/dist/requirements/schemas.d.ts +320 -0
- package/dist/requirements/schemas.d.ts.map +1 -0
- package/dist/requirements/schemas.js +121 -0
- package/dist/requirements/ui.d.ts +4 -0
- package/dist/requirements/ui.d.ts.map +1 -0
- package/dist/requirements/ui.js +3 -0
- package/dist/requirements/utils.d.ts +2 -0
- package/dist/requirements/utils.d.ts.map +1 -0
- package/dist/requirements/utils.js +4 -0
- package/dist/schemas.d.ts +2070 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +507 -0
- package/dist/status-presentation.d.ts +34 -0
- package/dist/status-presentation.d.ts.map +1 -0
- package/dist/status-presentation.js +38 -0
- package/dist/ui.d.ts +43 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +42 -0
- package/package.json +256 -0
- package/src/requirements/styles.css +1 -0
- package/src/styles.css +13 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
// agent-quality: file-size exception -- owner: bookings-react; existing UI surface stays co-located until a dedicated split preserves behavior and tests.
|
|
2
|
+
"use client";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { useBookingCommit, useBookingDraft, useBookingDraftShape, useBookingHold, useBookingQuote, } from "@voyant-travel/catalog-react/booking-engine";
|
|
5
|
+
import { Button } from "@voyant-travel/ui/components/button";
|
|
6
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
7
|
+
import { useBookingsUiMessagesOrDefault } from "../../i18n/index.js";
|
|
8
|
+
import { emptyDraft, totalPax } from "../lib/draft-state.js";
|
|
9
|
+
import { JOURNEY_STEP_ORDER, } from "../types.js";
|
|
10
|
+
import { buildCommitParty, canAdvanceFromStep, defaultMinimalShape, isStepVisible, makeHoldSignature, resolveInitialStatus, stackedStepComplete, warningsForStep, } from "./booking-journey-rules.js";
|
|
11
|
+
import { ConfigureStepSkeleton } from "./configure-step-skeleton.js";
|
|
12
|
+
import { ContractPreviewDialog } from "./contract-preview-dialog.js";
|
|
13
|
+
import { AccommodationStep, AddonsStep, BillingStep, DepartureStep, DocumentsStep, FinalizeControls, OptionsStep, PaymentStep, ReviewStep, TravelersStep, } from "./journey-steps.js";
|
|
14
|
+
import { PriceSidePanel } from "./side-panel.js";
|
|
15
|
+
import { StackedJourney } from "./stacked-journey.js";
|
|
16
|
+
import { StepHeader } from "./step-header.js";
|
|
17
|
+
export function BookingJourney(props) {
|
|
18
|
+
const messages = useBookingsUiMessagesOrDefault();
|
|
19
|
+
const surface = props.surface ?? "admin";
|
|
20
|
+
// Admin books on a single stacked page (nothing hidden); the storefront
|
|
21
|
+
// keeps the guided one-step-at-a-time wizard. Two deliberately separate
|
|
22
|
+
// flows — see BookingJourneyProps.layout.
|
|
23
|
+
const layout = props.layout ?? (surface === "admin" ? "stacked" : "wizard");
|
|
24
|
+
const [draft, setDraft] = useState(() => {
|
|
25
|
+
const base = emptyDraft({
|
|
26
|
+
module: props.entityModule,
|
|
27
|
+
id: props.entityId,
|
|
28
|
+
// Empty when storefront — the public engine route resolves
|
|
29
|
+
// it server-side from (entityModule, entityId).
|
|
30
|
+
sourceKind: props.sourceKind ?? "",
|
|
31
|
+
sourceConnectionId: props.sourceConnectionId,
|
|
32
|
+
sourceRef: props.sourceRef,
|
|
33
|
+
}, { buyerType: props.defaultBuyerType ?? (surface === "admin" ? "B2B" : "B2C") });
|
|
34
|
+
// Seed Configure when the caller passed pre-locked state —
|
|
35
|
+
// detail page picks departure + pax, booking flow only handles
|
|
36
|
+
// travelers + addons + payment.
|
|
37
|
+
if (props.initialConfigure) {
|
|
38
|
+
const seed = props.initialConfigure;
|
|
39
|
+
const seedPax = seed.pax;
|
|
40
|
+
base.configure = Object.assign({}, base.configure, seed, {
|
|
41
|
+
pax: { ...base.configure.pax, ...(seedPax ?? {}) },
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (props.initialAccommodation) {
|
|
45
|
+
const seed = props.initialAccommodation;
|
|
46
|
+
base.accommodation = Object.assign({ rooms: [], travelerAssignments: {} }, base.accommodation ?? {}, seed);
|
|
47
|
+
}
|
|
48
|
+
return base;
|
|
49
|
+
});
|
|
50
|
+
const fallbackShape = useMemo(() => props.fallbackShape ?? defaultMinimalShape(), [props.fallbackShape]);
|
|
51
|
+
// Server-side draft sync — PUT on each step transition. The shell
|
|
52
|
+
// doesn't read from the server in Phase B (drafts are recovery
|
|
53
|
+
// surface, not source of truth) but the wire is in place.
|
|
54
|
+
const draftSync = useBookingDraft({
|
|
55
|
+
surface,
|
|
56
|
+
draftId: props.draftId,
|
|
57
|
+
enableLoad: false,
|
|
58
|
+
});
|
|
59
|
+
// Live quote — debounced 250ms.
|
|
60
|
+
const quote = useBookingQuote({
|
|
61
|
+
surface,
|
|
62
|
+
draft,
|
|
63
|
+
});
|
|
64
|
+
const shape = useBookingDraftShape({
|
|
65
|
+
surface,
|
|
66
|
+
quote: quote.data,
|
|
67
|
+
fallback: fallbackShape,
|
|
68
|
+
});
|
|
69
|
+
// Step navigation — only show steps the descriptor says are relevant.
|
|
70
|
+
const hideConfigure = props.hideConfigure === true;
|
|
71
|
+
const steps = useMemo(() => JOURNEY_STEP_ORDER.filter((s) => {
|
|
72
|
+
// `hideConfigure` skips the configure phase — now split across the
|
|
73
|
+
// Departure + Options steps.
|
|
74
|
+
if (hideConfigure && (s === "departure" || s === "options"))
|
|
75
|
+
return false;
|
|
76
|
+
// Internal notes + document generation are operator-only.
|
|
77
|
+
if (s === "documents" && surface !== "admin")
|
|
78
|
+
return false;
|
|
79
|
+
return isStepVisible(s, shape);
|
|
80
|
+
}), [shape, hideConfigure, surface]);
|
|
81
|
+
// The stacked admin layout drops the Review block — the side panel shows the
|
|
82
|
+
// live summary + Confirm at all times, so a separate review section is
|
|
83
|
+
// redundant.
|
|
84
|
+
const stackedSteps = useMemo(() => steps.filter((s) => s !== "review"), [steps]);
|
|
85
|
+
const [currentStep, setCurrentStep] = useState(() => steps[0] ?? "departure");
|
|
86
|
+
const [visited, setVisited] = useState(() => new Set([steps[0] ?? "departure"]));
|
|
87
|
+
// If the descriptor changes and removes the current step, reset to
|
|
88
|
+
// the first available step. (Edge case: shape goes from
|
|
89
|
+
// owned→sourced and the relevant step set narrows.)
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (!steps.includes(currentStep)) {
|
|
92
|
+
setCurrentStep(steps[0] ?? "departure");
|
|
93
|
+
}
|
|
94
|
+
}, [steps, currentStep]);
|
|
95
|
+
// PUT the draft to the server to keep the recovery surface fresh
|
|
96
|
+
// without saving on every keystroke. Wizard saves on each step
|
|
97
|
+
// transition; the stacked admin page has no steps, so it saves on
|
|
98
|
+
// each settled quote (a natural, debounced cadence). The mutation
|
|
99
|
+
// reads the latest draft + quote from the closure on each fire.
|
|
100
|
+
const saveTrigger = layout === "wizard" ? currentStep : (quote.data?.quoteId ?? "");
|
|
101
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: intentional — fires on save trigger only
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
draftSync.save.mutate({
|
|
104
|
+
draft: { ...draft, quoteId: quote.data?.quoteId },
|
|
105
|
+
currentStep,
|
|
106
|
+
currentQuoteId: quote.data?.quoteId,
|
|
107
|
+
});
|
|
108
|
+
}, [saveTrigger]);
|
|
109
|
+
// Commit
|
|
110
|
+
const commit = useBookingCommit({
|
|
111
|
+
surface,
|
|
112
|
+
draftId: props.draftId,
|
|
113
|
+
onCommitted: props.onCommitted,
|
|
114
|
+
});
|
|
115
|
+
// Inventory hold — fired when the user advances past Configure
|
|
116
|
+
// with a slot + pax picked. Failures are non-blocking (the engine
|
|
117
|
+
// re-validates capacity at commit time anyway); we just don't
|
|
118
|
+
// want to silently let two shoppers race past Configure with one
|
|
119
|
+
// capacity unit between them.
|
|
120
|
+
const holdApi = useBookingHold({ surface });
|
|
121
|
+
const holdState = useRef({});
|
|
122
|
+
const holdSignature = makeHoldSignature(draft, props.entityModule, props.entityId);
|
|
123
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: signature change is the only trigger; refs + closure read latest values -- owner: bookings-react; existing suppression is intentional pending typed cleanup.
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
// Wizard: don't hold while still on the configure steps. Stacked:
|
|
126
|
+
// everything's on one page, so the signature (slot + pax present)
|
|
127
|
+
// is the trigger.
|
|
128
|
+
if (layout === "wizard" && (currentStep === "departure" || currentStep === "options"))
|
|
129
|
+
return;
|
|
130
|
+
if (!holdSignature)
|
|
131
|
+
return;
|
|
132
|
+
if (holdState.current.signature === holdSignature)
|
|
133
|
+
return;
|
|
134
|
+
// Inquiry mode is the lead-form path — capture the lead without
|
|
135
|
+
// burning capacity. The operator follows up before any inventory
|
|
136
|
+
// is touched.
|
|
137
|
+
if (draft.payment.intent === "inquiry")
|
|
138
|
+
return;
|
|
139
|
+
const previousToken = holdState.current.holdToken;
|
|
140
|
+
holdState.current = { signature: holdSignature };
|
|
141
|
+
void holdApi
|
|
142
|
+
.place({
|
|
143
|
+
entityModule: props.entityModule,
|
|
144
|
+
entityId: props.entityId,
|
|
145
|
+
draftId: props.draftId,
|
|
146
|
+
parameters: {
|
|
147
|
+
slotId: draft.configure.departureSlotId,
|
|
148
|
+
paxCount: totalPax(draft),
|
|
149
|
+
productId: props.entityId,
|
|
150
|
+
},
|
|
151
|
+
})
|
|
152
|
+
.then((result) => {
|
|
153
|
+
holdState.current = { holdToken: result.holdToken, signature: holdSignature };
|
|
154
|
+
})
|
|
155
|
+
.catch(() => {
|
|
156
|
+
// Non-blocking — see comment above.
|
|
157
|
+
});
|
|
158
|
+
if (previousToken) {
|
|
159
|
+
void holdApi
|
|
160
|
+
.release({ entityModule: props.entityModule, holdToken: previousToken })
|
|
161
|
+
.catch(() => { });
|
|
162
|
+
}
|
|
163
|
+
}, [holdSignature, currentStep]);
|
|
164
|
+
const available = quote.data?.available !== false;
|
|
165
|
+
const canAdvance = canAdvanceFromStep(currentStep, draft, shape, available);
|
|
166
|
+
const warnings = warningsForStep(currentStep, draft, shape, messages);
|
|
167
|
+
// Stacked layout: there's no "current" step, but the section nav still
|
|
168
|
+
// nudges toward the first thing that isn't done yet, and the final
|
|
169
|
+
// Confirm is gated until every section passes its check.
|
|
170
|
+
const firstIncomplete = useMemo(() => stackedSteps.find((s) => !stackedStepComplete(s, draft, shape, available)) ??
|
|
171
|
+
stackedSteps[stackedSteps.length - 1] ??
|
|
172
|
+
stackedSteps[0] ??
|
|
173
|
+
"departure", [stackedSteps, draft, shape, available]);
|
|
174
|
+
const canCommit = useMemo(() => stackedSteps.every((s) => canAdvanceFromStep(s, draft, shape, available)), [stackedSteps, draft, shape, available]);
|
|
175
|
+
const [isAdvanceGuardPending, setIsAdvanceGuardPending] = useState(false);
|
|
176
|
+
const [advanceGuardError, setAdvanceGuardError] = useState(null);
|
|
177
|
+
const idx = steps.indexOf(currentStep);
|
|
178
|
+
const next = steps[idx + 1];
|
|
179
|
+
const prev = steps[idx - 1];
|
|
180
|
+
const advance = async () => {
|
|
181
|
+
if (!next || !canAdvance || isAdvanceGuardPending)
|
|
182
|
+
return;
|
|
183
|
+
setAdvanceGuardError(null);
|
|
184
|
+
if (props.onBeforeStepAdvance) {
|
|
185
|
+
setIsAdvanceGuardPending(true);
|
|
186
|
+
try {
|
|
187
|
+
const guardResult = await props.onBeforeStepAdvance({
|
|
188
|
+
currentStep,
|
|
189
|
+
nextStep: next,
|
|
190
|
+
draft,
|
|
191
|
+
pricing: quote.data?.pricing ?? null,
|
|
192
|
+
quoteId: quote.data?.quoteId,
|
|
193
|
+
surface,
|
|
194
|
+
});
|
|
195
|
+
if (guardResult &&
|
|
196
|
+
typeof guardResult === "object" &&
|
|
197
|
+
"draft" in guardResult &&
|
|
198
|
+
guardResult.draft) {
|
|
199
|
+
setDraft(guardResult.draft);
|
|
200
|
+
}
|
|
201
|
+
if (guardResult === false) {
|
|
202
|
+
setAdvanceGuardError(messages.bookingJourney.validation.completeStepBeforeContinuing);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (guardResult &&
|
|
206
|
+
typeof guardResult === "object" &&
|
|
207
|
+
"allow" in guardResult &&
|
|
208
|
+
guardResult.allow === false) {
|
|
209
|
+
setAdvanceGuardError(guardResult.message ?? messages.bookingJourney.validation.completeStepBeforeContinuing);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
setAdvanceGuardError(error instanceof Error
|
|
215
|
+
? error.message
|
|
216
|
+
: messages.bookingJourney.validation.unableToContinue);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
setIsAdvanceGuardPending(false);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
setCurrentStep(next);
|
|
224
|
+
setVisited((s) => new Set(s).add(next));
|
|
225
|
+
};
|
|
226
|
+
const goBack = () => {
|
|
227
|
+
if (!prev)
|
|
228
|
+
return;
|
|
229
|
+
setCurrentStep(prev);
|
|
230
|
+
};
|
|
231
|
+
const jumpTo = (step) => {
|
|
232
|
+
if (!visited.has(step) && step !== currentStep)
|
|
233
|
+
return;
|
|
234
|
+
setCurrentStep(step);
|
|
235
|
+
};
|
|
236
|
+
const [contractDialogOpen, setContractDialogOpen] = useState(false);
|
|
237
|
+
// Tracks the multi-step storefront checkout flow (book →
|
|
238
|
+
// checkout-start → redirect). The legacy in-process commit has
|
|
239
|
+
// its own `commit.isPending` so the Confirm button merges both
|
|
240
|
+
// when deciding whether to show a spinner.
|
|
241
|
+
const [isHandlingCheckout, setIsHandlingCheckout] = useState(false);
|
|
242
|
+
const contractConfig = props.contract;
|
|
243
|
+
const contractVariables = useMemo(() => {
|
|
244
|
+
if (!contractConfig)
|
|
245
|
+
return {};
|
|
246
|
+
return contractConfig.resolveVariables({ draft, pricing: quote.data?.pricing ?? null });
|
|
247
|
+
}, [contractConfig, draft, quote.data?.pricing]);
|
|
248
|
+
const commitDraft = async () => {
|
|
249
|
+
if (!quote.data?.quoteId)
|
|
250
|
+
return;
|
|
251
|
+
await commit.mutateAsync({
|
|
252
|
+
draft: { ...draft, quoteId: quote.data.quoteId },
|
|
253
|
+
quoteId: quote.data.quoteId,
|
|
254
|
+
// The owned commit reads the buyer + travelers off `party`, not the
|
|
255
|
+
// draft — without this the create rejects with "no billing person/org".
|
|
256
|
+
party: buildCommitParty(draft),
|
|
257
|
+
initialStatus: resolveInitialStatus(draft),
|
|
258
|
+
paymentIntent: { type: draft.payment.intent === "card" ? "card" : "hold" },
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
const handleAccepted = async (acceptance) => {
|
|
262
|
+
if (!props.onContractAccepted) {
|
|
263
|
+
await commitDraft();
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
setIsHandlingCheckout(true);
|
|
267
|
+
try {
|
|
268
|
+
await props.onContractAccepted(acceptance, {
|
|
269
|
+
draft,
|
|
270
|
+
pricing: quote.data?.pricing ?? null,
|
|
271
|
+
quoteId: quote.data?.quoteId,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
finally {
|
|
275
|
+
setIsHandlingCheckout(false);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
const onConfirm = async () => {
|
|
279
|
+
if (!quote.data?.quoteId)
|
|
280
|
+
return;
|
|
281
|
+
// 1. Contract is wired → open the dialog. Acceptance triggers
|
|
282
|
+
// onContractAccepted (the storefront's checkout-start path).
|
|
283
|
+
// 2. No contract but onContractAccepted is wired → call it
|
|
284
|
+
// directly without an acceptance payload. The storefront uses
|
|
285
|
+
// this to drive the /book + /checkout/start handoff so card
|
|
286
|
+
// intents redirect to the PSP. Skipping the dialog when no
|
|
287
|
+
// template is configured is intentional — the dialog is an
|
|
288
|
+
// optional gate, not a required step.
|
|
289
|
+
// 3. Neither wired → in-process commit (the operator dashboard's
|
|
290
|
+
// legacy path).
|
|
291
|
+
if (contractConfig) {
|
|
292
|
+
setContractDialogOpen(true);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
await handleAccepted(null);
|
|
296
|
+
};
|
|
297
|
+
const onContractAccept = async (acceptance) => {
|
|
298
|
+
setContractDialogOpen(false);
|
|
299
|
+
await handleAccepted(acceptance);
|
|
300
|
+
};
|
|
301
|
+
// Bind the picked lead + departure into the billing-extras slot so the
|
|
302
|
+
// template can run lead-aware checks (e.g. duplicate-departure warning).
|
|
303
|
+
const billingExtrasSlot = props.renderBillingExtras
|
|
304
|
+
? () => props.renderBillingExtras?.({
|
|
305
|
+
buyerType: draft.billing.buyerType,
|
|
306
|
+
personId: draft.billing.contact.personId,
|
|
307
|
+
organizationId: draft.billing.organizationId,
|
|
308
|
+
productId: props.entityId,
|
|
309
|
+
departureSlotId: draft.configure.departureSlotId,
|
|
310
|
+
departureDate: draft.configure.departureDate,
|
|
311
|
+
})
|
|
312
|
+
: undefined;
|
|
313
|
+
// Renders one step's content. Shared by both layouts — the wizard shows
|
|
314
|
+
// exactly one at a time; the stacked page renders them all in sections.
|
|
315
|
+
const renderStep = (step) => {
|
|
316
|
+
switch (step) {
|
|
317
|
+
case "departure":
|
|
318
|
+
// First load: the descriptor arrives with the first quote. Show a
|
|
319
|
+
// skeleton rather than the generic fallback, which would flash and
|
|
320
|
+
// then shift into the real layout.
|
|
321
|
+
return !quote.data && quote.isQuoting ? (_jsx(ConfigureStepSkeleton, {})) : (_jsx(DepartureStep, { draft: draft, setDraft: setDraft, shape: shape, productId: props.entityId, renderDeparturePicker: props.renderDeparturePicker }));
|
|
322
|
+
case "options":
|
|
323
|
+
return (_jsx(OptionsStep, { draft: draft, setDraft: setDraft, shape: shape, productId: props.entityId, renderUnitsPicker: props.renderUnitsPicker }));
|
|
324
|
+
case "billing":
|
|
325
|
+
return (_jsx(BillingStep, { draft: draft, setDraft: setDraft, shape: shape, renderLeadContactPicker: props.renderLeadContactPicker, renderExtras: billingExtrasSlot, warnings: warningsForStep("billing", draft, shape, messages) }));
|
|
326
|
+
case "travelers":
|
|
327
|
+
return (_jsx(TravelersStep, { draft: draft, setDraft: setDraft, shape: shape, renderTravelerContactPicker: props.renderTravelerContactPicker, warnings: warningsForStep("travelers", draft, shape, messages) }));
|
|
328
|
+
case "accommodation":
|
|
329
|
+
return _jsx(AccommodationStep, { draft: draft, setDraft: setDraft, shape: shape });
|
|
330
|
+
case "addons":
|
|
331
|
+
return _jsx(AddonsStep, { draft: draft, setDraft: setDraft, shape: shape });
|
|
332
|
+
case "payment":
|
|
333
|
+
return (_jsx(PaymentStep, { draft: draft, setDraft: setDraft, shape: shape, capabilities: props.paymentCapabilities ?? {
|
|
334
|
+
acceptsCard: false,
|
|
335
|
+
acceptsHold: true,
|
|
336
|
+
acceptsTicketOnCredit: false,
|
|
337
|
+
}, renderProviderStep: props.renderPaymentProviderStep, surface: surface, pricing: quote.data?.pricing ?? null }));
|
|
338
|
+
case "documents":
|
|
339
|
+
return _jsx(DocumentsStep, { draft: draft, setDraft: setDraft });
|
|
340
|
+
case "review":
|
|
341
|
+
return (_jsx(ReviewStep, { draft: draft, setDraft: setDraft, isCommitting: commit.isPending || isHandlingCheckout, onConfirm: onConfirm,
|
|
342
|
+
// Stacked has no per-step gates, so the Confirm button enforces
|
|
343
|
+
// the whole-booking validity itself.
|
|
344
|
+
canConfirm: layout === "stacked" ? canCommit : undefined, renderExtras: props.renderReviewExtras, surface: surface, pricing: quote.data?.pricing ?? null, warnings: warningsForStep("review", draft, shape, messages) }));
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
if (layout === "stacked") {
|
|
348
|
+
return (_jsx(StackedJourney, { className: props.className, steps: stackedSteps, renderStep: renderStep, isStepComplete: (s) => stackedStepComplete(s, draft, shape, available), commitError: commit.error, onCancel: props.onCancelled, onConfirm: onConfirm, isCommitting: commit.isPending || isHandlingCheckout, canConfirm: canCommit, sidePanel: _jsx(PriceSidePanel, { pricing: quote.data?.pricing ?? null, isQuoting: quote.isQuoting, invalidReason: quote.data?.invalidReason, entitySummary: props.entitySummary, currentStep: firstIncomplete, steps: stackedSteps, shape: shape, draft: draft, className: props.sidePanelClassName,
|
|
349
|
+
// Price override + voucher live with the pricing, not in Payment.
|
|
350
|
+
pricingExtras: _jsx(FinalizeControls, { draft: draft, setDraft: setDraft, pricing: quote.data?.pricing ?? null, renderVoucherPicker: props.renderVoucherPicker }) }), contractDialog: contractConfig ? (_jsx(ContractPreviewDialog, { open: contractDialogOpen, onOpenChange: setContractDialogOpen, previewUrl: contractConfig.previewUrl, acceptLanguage: contractConfig.acceptLanguage, variables: contractVariables, marketingLabel: contractConfig.marketingLabel, termsLabel: contractConfig.termsLabel, onAccept: onContractAccept })) : null }));
|
|
351
|
+
}
|
|
352
|
+
return (_jsxs("div", { className: props.className, children: [_jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-8 md:items-start", children: [_jsxs("div", { className: "space-y-6 md:col-span-5", children: [_jsx(StepHeader, { current: currentStep, visited: [...visited], steps: steps, shape: shape, onJumpTo: jumpTo }), currentStep === "departure" ? (
|
|
353
|
+
// First load: the descriptor arrives with the first quote. Show a
|
|
354
|
+
// skeleton rather than the generic fallback, which would flash
|
|
355
|
+
// and then shift into the real layout.
|
|
356
|
+
!quote.data && quote.isQuoting ? (_jsx(ConfigureStepSkeleton, {})) : (_jsx(DepartureStep, { draft: draft, setDraft: setDraft, shape: shape, productId: props.entityId, renderDeparturePicker: props.renderDeparturePicker }))) : null, currentStep === "options" ? (_jsx(OptionsStep, { draft: draft, setDraft: setDraft, shape: shape, productId: props.entityId, renderUnitsPicker: props.renderUnitsPicker })) : null, currentStep === "billing" ? (_jsx(BillingStep, { draft: draft, setDraft: setDraft, shape: shape, renderLeadContactPicker: props.renderLeadContactPicker, renderExtras: billingExtrasSlot })) : null, currentStep === "travelers" ? (_jsx(TravelersStep, { draft: draft, setDraft: setDraft, shape: shape, renderTravelerContactPicker: props.renderTravelerContactPicker })) : null, currentStep === "accommodation" ? (_jsx(AccommodationStep, { draft: draft, setDraft: setDraft, shape: shape })) : null, currentStep === "addons" ? (_jsx(AddonsStep, { draft: draft, setDraft: setDraft, shape: shape })) : null, currentStep === "payment" ? (_jsx(PaymentStep, { draft: draft, setDraft: setDraft, shape: shape, capabilities: props.paymentCapabilities ?? {
|
|
357
|
+
acceptsCard: false,
|
|
358
|
+
acceptsHold: true,
|
|
359
|
+
acceptsTicketOnCredit: false,
|
|
360
|
+
}, renderProviderStep: props.renderPaymentProviderStep, surface: surface, pricing: quote.data?.pricing ?? null })) : null, currentStep === "review" ? (_jsx(ReviewStep, { draft: draft, setDraft: setDraft, isCommitting: commit.isPending || isHandlingCheckout, onConfirm: onConfirm, renderExtras: props.renderReviewExtras, surface: surface, pricing: quote.data?.pricing ?? null })) : null, warnings.length > 0 ? (_jsx("ul", { className: "space-y-1 rounded-md border border-amber-300 bg-amber-50 p-3 text-amber-900 text-sm dark:border-amber-700 dark:bg-amber-950 dark:text-amber-100", children: warnings.map((w) => (_jsxs("li", { children: ["\u26A0 ", w] }, w))) })) : null, _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { type: "button", variant: "outline", disabled: isAdvanceGuardPending, onClick: () => {
|
|
361
|
+
if (prev)
|
|
362
|
+
goBack();
|
|
363
|
+
else
|
|
364
|
+
props.onCancelled?.();
|
|
365
|
+
}, children: messages.bookingJourney.navigation.back }), next ? (_jsx(Button, { type: "button", onClick: () => void advance(), disabled: !canAdvance || isAdvanceGuardPending, className: "ml-auto", children: isAdvanceGuardPending
|
|
366
|
+
? messages.bookingJourney.navigation.checking
|
|
367
|
+
: messages.bookingJourney.navigation.next })) : null] }), advanceGuardError ? (_jsx("p", { className: "text-destructive text-sm", role: "alert", "aria-live": "polite", children: advanceGuardError })) : null, commit.error ? (_jsx("p", { className: "text-destructive text-sm", children: commit.error instanceof Error ? commit.error.message : String(commit.error) })) : null] }), _jsx("aside", { className: "md:sticky md:top-4 md:col-span-3", children: _jsx(PriceSidePanel, { pricing: quote.data?.pricing ?? null, isQuoting: quote.isQuoting, invalidReason: quote.data?.invalidReason, entitySummary: props.entitySummary, currentStep: currentStep, steps: steps, shape: shape, draft: draft, className: props.sidePanelClassName }) })] }), contractConfig ? (_jsx(ContractPreviewDialog, { open: contractDialogOpen, onOpenChange: setContractDialogOpen, previewUrl: contractConfig.previewUrl, acceptLanguage: contractConfig.acceptLanguage, variables: contractVariables, marketingLabel: contractConfig.marketingLabel, termsLabel: contractConfig.termsLabel, onAccept: onContractAccept })) : null] }));
|
|
368
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* First-load placeholder for the Configure step. Mirrors the real layout
|
|
4
|
+
* (departure, travelers, option) closely enough that swapping to the live
|
|
5
|
+
* descriptor causes minimal layout shift.
|
|
6
|
+
*/
|
|
7
|
+
export declare function ConfigureStepSkeleton(): React.ReactElement;
|
|
8
|
+
//# sourceMappingURL=configure-step-skeleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure-step-skeleton.d.ts","sourceRoot":"","sources":["../../../src/journey/components/configure-step-skeleton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AAEnC;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,KAAK,CAAC,YAAY,CA0B1D"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Card, CardContent, CardHeader } from "@voyant-travel/ui/components/card";
|
|
3
|
+
import { Skeleton } from "@voyant-travel/ui/components/skeleton";
|
|
4
|
+
/**
|
|
5
|
+
* First-load placeholder for the Configure step. Mirrors the real layout
|
|
6
|
+
* (departure, travelers, option) closely enough that swapping to the live
|
|
7
|
+
* descriptor causes minimal layout shift.
|
|
8
|
+
*/
|
|
9
|
+
export function ConfigureStepSkeleton() {
|
|
10
|
+
return (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(Skeleton, { className: "h-5 w-28" }) }), _jsxs(CardContent, { className: "space-y-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Skeleton, { className: "h-4 w-24" }), _jsx(Skeleton, { className: "h-10 w-full" })] }), _jsxs("div", { className: "space-y-3", children: [_jsx(Skeleton, { className: "h-4 w-20" }), _jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-3", children: [_jsx(Skeleton, { className: "h-16 w-full" }), _jsx(Skeleton, { className: "h-16 w-full" }), _jsx(Skeleton, { className: "h-16 w-full" })] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Skeleton, { className: "h-4 w-16" }), _jsx(Skeleton, { className: "h-12 w-full" })] })] })] }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Contract preview dialog. Renders a contract template with the
|
|
4
|
+
* draft variables prefilled and gates the journey on two
|
|
5
|
+
* checkboxes — terms acceptance and an optional marketing opt-in.
|
|
6
|
+
*
|
|
7
|
+
* The dialog is template-driven: the storefront wires a
|
|
8
|
+
* `templateSlug` plus a `resolveVariables(draft)` function that maps
|
|
9
|
+
* the booking draft to the template's variable schema. The dialog
|
|
10
|
+
* fetches the rendered HTML from
|
|
11
|
+
* `POST /v1/public/legal/contracts/templates/by-slug/:slug/preview`
|
|
12
|
+
* and renders it in an iframe (sandboxed — same-origin removed) so
|
|
13
|
+
* inline styles in the contract HTML don't leak into the page.
|
|
14
|
+
*/
|
|
15
|
+
export interface ContractPreviewDialogProps {
|
|
16
|
+
open: boolean;
|
|
17
|
+
onOpenChange: (open: boolean) => void;
|
|
18
|
+
/** Variables to interpolate into the template body. */
|
|
19
|
+
variables: Record<string, unknown>;
|
|
20
|
+
/**
|
|
21
|
+
* URL of the public render endpoint. The storefront wraps the
|
|
22
|
+
* journey and supplies an absolute URL so the dialog stays
|
|
23
|
+
* agnostic about where the API base lives.
|
|
24
|
+
*/
|
|
25
|
+
previewUrl: string;
|
|
26
|
+
/** Optional Accept-Language header for locale resolution. */
|
|
27
|
+
acceptLanguage?: string;
|
|
28
|
+
/** Fired when the user clicks Accept after ticking the gates. */
|
|
29
|
+
onAccept: (acceptance: ContractAcceptance) => void;
|
|
30
|
+
/** Optional marketing-opt-in label. When omitted, marketing
|
|
31
|
+
* consent isn't required to accept. */
|
|
32
|
+
marketingLabel?: string;
|
|
33
|
+
termsLabel?: React.ReactNode;
|
|
34
|
+
}
|
|
35
|
+
export interface ContractAcceptance {
|
|
36
|
+
templateId: string;
|
|
37
|
+
templateSlug: string;
|
|
38
|
+
templateName: string;
|
|
39
|
+
acceptedTerms: true;
|
|
40
|
+
acceptedMarketing: boolean;
|
|
41
|
+
acceptedAt: string;
|
|
42
|
+
/** The exact rendered HTML the user accepted — captured for the
|
|
43
|
+
* audit trail so we can reproduce what they saw. */
|
|
44
|
+
renderedHtml: string;
|
|
45
|
+
}
|
|
46
|
+
export declare function ContractPreviewDialog({ open, onOpenChange, variables, previewUrl, acceptLanguage, onAccept, marketingLabel, termsLabel, }: ContractPreviewDialogProps): React.ReactElement;
|
|
47
|
+
//# sourceMappingURL=contract-preview-dialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-preview-dialog.d.ts","sourceRoot":"","sources":["../../../src/journey/components/contract-preview-dialog.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAClC;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iEAAiE;IACjE,QAAQ,EAAE,CAAC,UAAU,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAClD;4CACwC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC7B;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,IAAI,CAAA;IACnB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB;yDACqD;IACrD,YAAY,EAAE,MAAM,CAAA;CACrB;AAgBD,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,UAAU,EACV,cAAc,EACd,QAAQ,EACR,cAAc,EACd,UAAU,GACX,EAAE,0BAA0B,GAAG,KAAK,CAAC,YAAY,CA2JjD"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { Button } from "@voyant-travel/ui/components/button";
|
|
4
|
+
import { Checkbox } from "@voyant-travel/ui/components/checkbox";
|
|
5
|
+
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, } from "@voyant-travel/ui/components/dialog";
|
|
6
|
+
import { Skeleton } from "@voyant-travel/ui/components/skeleton";
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import { formatMessage, useBookingsUiMessagesOrDefault } from "../../i18n/index.js";
|
|
9
|
+
export function ContractPreviewDialog({ open, onOpenChange, variables, previewUrl, acceptLanguage, onAccept, marketingLabel, termsLabel, }) {
|
|
10
|
+
const messages = useBookingsUiMessagesOrDefault();
|
|
11
|
+
const [loadState, setLoadState] = React.useState("idle");
|
|
12
|
+
const [errorMessage, setErrorMessage] = React.useState(null);
|
|
13
|
+
const [renderedHtml, setRenderedHtml] = React.useState("");
|
|
14
|
+
const [template, setTemplate] = React.useState(null);
|
|
15
|
+
const [acceptedTerms, setAcceptedTerms] = React.useState(false);
|
|
16
|
+
// Marketing consent defaults to opted-in; the customer can untick
|
|
17
|
+
// before accepting. Terms still require an explicit tick.
|
|
18
|
+
const [acceptedMarketing, setAcceptedMarketing] = React.useState(true);
|
|
19
|
+
// Stringify the variables once so the effect re-fetches only on
|
|
20
|
+
// meaningful changes — equivalent to a deep-equality check, but
|
|
21
|
+
// cheap enough to run every render.
|
|
22
|
+
const variablesKey = React.useMemo(() => JSON.stringify(variables), [variables]);
|
|
23
|
+
const variablesRef = React.useRef(variables);
|
|
24
|
+
variablesRef.current = variables;
|
|
25
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: variablesKey is the meaningful-change signal; the actual variables are read off variablesRef so the effect doesn't re-fire on every render -- owner: bookings-react; existing suppression is intentional pending typed cleanup.
|
|
26
|
+
React.useEffect(() => {
|
|
27
|
+
if (!open)
|
|
28
|
+
return;
|
|
29
|
+
let cancelled = false;
|
|
30
|
+
setLoadState("loading");
|
|
31
|
+
setErrorMessage(null);
|
|
32
|
+
setAcceptedTerms(false);
|
|
33
|
+
setAcceptedMarketing(true);
|
|
34
|
+
void fetch(previewUrl, {
|
|
35
|
+
method: "POST",
|
|
36
|
+
credentials: "include",
|
|
37
|
+
headers: {
|
|
38
|
+
"content-type": "application/json",
|
|
39
|
+
...(acceptLanguage ? { "accept-language": acceptLanguage } : {}),
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify({ variables: variablesRef.current }),
|
|
42
|
+
})
|
|
43
|
+
.then(async (res) => {
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
throw new Error(formatMessage(messages.bookingJourney.contract.previewRequestFailed, {
|
|
46
|
+
status: res.status,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
const json = (await res.json());
|
|
50
|
+
if (cancelled)
|
|
51
|
+
return;
|
|
52
|
+
const body = json.data?.rendered ?? "";
|
|
53
|
+
const tmpl = json.data?.template;
|
|
54
|
+
if (!body || !tmpl) {
|
|
55
|
+
throw new Error(messages.bookingJourney.contract.previewMissing);
|
|
56
|
+
}
|
|
57
|
+
setRenderedHtml(body);
|
|
58
|
+
setTemplate({ id: tmpl.id, slug: tmpl.slug, name: tmpl.name });
|
|
59
|
+
setLoadState("ready");
|
|
60
|
+
})
|
|
61
|
+
.catch((err) => {
|
|
62
|
+
if (cancelled)
|
|
63
|
+
return;
|
|
64
|
+
setErrorMessage(err instanceof Error ? err.message : String(err));
|
|
65
|
+
setLoadState("error");
|
|
66
|
+
});
|
|
67
|
+
return () => {
|
|
68
|
+
cancelled = true;
|
|
69
|
+
};
|
|
70
|
+
}, [open, previewUrl, acceptLanguage, variablesKey]);
|
|
71
|
+
const canAccept = loadState === "ready" && acceptedTerms && Boolean(template);
|
|
72
|
+
const handleAccept = () => {
|
|
73
|
+
if (!canAccept || !template)
|
|
74
|
+
return;
|
|
75
|
+
onAccept({
|
|
76
|
+
templateId: template.id,
|
|
77
|
+
templateSlug: template.slug,
|
|
78
|
+
templateName: template.name,
|
|
79
|
+
acceptedTerms: true,
|
|
80
|
+
acceptedMarketing,
|
|
81
|
+
acceptedAt: new Date().toISOString(),
|
|
82
|
+
renderedHtml,
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "flex h-[85vh] w-[95vw] max-w-4xl flex-col gap-0 p-0", children: [_jsxs(DialogHeader, { className: "border-b p-6 pb-4", children: [_jsx(DialogTitle, { children: template?.name ?? messages.bookingJourney.contract.defaultTitle }), _jsx("p", { className: "text-muted-foreground text-sm", children: messages.bookingJourney.contract.description })] }), _jsxs("div", { className: "flex-1 overflow-hidden bg-muted/30", children: [loadState === "loading" ? (_jsxs("div", { className: "space-y-3 p-6", children: [_jsx(Skeleton, { className: "h-6 w-1/2" }), _jsx(Skeleton, { className: "h-4 w-full" }), _jsx(Skeleton, { className: "h-4 w-5/6" }), _jsx(Skeleton, { className: "h-4 w-4/5" }), _jsx(Skeleton, { className: "h-4 w-full" })] })) : null, loadState === "error" ? (_jsx("div", { className: "p-6", children: _jsxs("p", { className: "text-destructive text-sm", children: [messages.bookingJourney.contract.errorPrefix, " ", errorMessage] }) })) : null, loadState === "ready" ? (_jsx("iframe", { title: formatMessage(messages.bookingJourney.contract.iframeTitle, {
|
|
86
|
+
name: template?.name ?? messages.bookingJourney.contract.defaultTitle,
|
|
87
|
+
}), srcDoc: wrapPreviewHtml(renderedHtml), sandbox: "", className: "h-full w-full border-0 bg-white" })) : null] }), _jsxs(DialogFooter, { className: "border-t p-6 sm:flex-col sm:items-stretch sm:gap-3", children: [_jsxs("div", { className: "space-y-2 text-sm", children: [_jsxs("label", { className: "flex items-start gap-2", children: [_jsx(Checkbox, { checked: acceptedTerms, onCheckedChange: (v) => setAcceptedTerms(v === true), className: "mt-0.5" }), _jsx("span", { children: termsLabel ?? _jsx(_Fragment, { children: messages.bookingJourney.contract.termsLabel }) })] }), _jsxs("label", { className: "flex items-start gap-2", children: [_jsx(Checkbox, { checked: acceptedMarketing, onCheckedChange: (v) => setAcceptedMarketing(v === true), className: "mt-0.5" }), _jsx("span", { children: marketingLabel ?? messages.bookingJourney.contract.marketingLabel })] })] }), _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), children: messages.bookingJourney.contract.cancel }), _jsx(Button, { type: "button", disabled: !canAccept, onClick: handleAccept, children: messages.bookingJourney.contract.acceptAndContinue })] })] })] }) }));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Wrap the rendered template body in a self-contained light-theme HTML
|
|
91
|
+
* document. Templates author their own typography but rarely set a
|
|
92
|
+
* background, so without this the iframe inherits the browser default
|
|
93
|
+
* (transparent) and we'd see whatever shows through — which on the
|
|
94
|
+
* storefront's dark dialog reads as black-on-black.
|
|
95
|
+
*/
|
|
96
|
+
function wrapPreviewHtml(body) {
|
|
97
|
+
return `<!DOCTYPE html>
|
|
98
|
+
<html lang="en">
|
|
99
|
+
<head>
|
|
100
|
+
<meta charset="utf-8" />
|
|
101
|
+
<style>
|
|
102
|
+
:root { color-scheme: light; }
|
|
103
|
+
html, body { margin: 0; background: #ffffff; color: #111827; }
|
|
104
|
+
body {
|
|
105
|
+
padding: 1.5rem 2rem;
|
|
106
|
+
font-family: ui-serif, Georgia, "Times New Roman", serif;
|
|
107
|
+
font-size: 15px;
|
|
108
|
+
line-height: 1.6;
|
|
109
|
+
}
|
|
110
|
+
h1, h2, h3 { font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; color: #0f172a; }
|
|
111
|
+
h1 { font-size: 1.5rem; margin: 0 0 1rem; }
|
|
112
|
+
h2 { font-size: 1.15rem; margin: 1.5rem 0 0.5rem; }
|
|
113
|
+
p { margin: 0.5rem 0; }
|
|
114
|
+
ul, ol { padding-left: 1.5rem; }
|
|
115
|
+
strong { color: #0f172a; }
|
|
116
|
+
a { color: #2563eb; }
|
|
117
|
+
table { border-collapse: collapse; width: 100%; margin: 0.75rem 0; }
|
|
118
|
+
th, td { border: 1px solid #e5e7eb; padding: 0.5rem 0.75rem; text-align: left; }
|
|
119
|
+
th { background: #f9fafb; }
|
|
120
|
+
</style>
|
|
121
|
+
</head>
|
|
122
|
+
<body>${body}</body>
|
|
123
|
+
</html>`;
|
|
124
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accommodation-step.d.ts","sourceRoot":"","sources":["../../../../src/journey/components/journey-steps/accommodation-step.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAMlD,wBAAgB,iBAAiB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,eAAe,GAAG,KAAK,CAAC,YAAY,CAgIjG"}
|