@ticketboothapp/booking 1.2.123 → 1.2.125

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/CHANGE_BOOKING_BE_HANDOFF.md +15 -4
  2. package/package.json +1 -1
  3. package/src/components/booking/AdminChangeBookingContent.tsx +276 -0
  4. package/src/components/booking/AdminChangeBookingFlow.tsx +651 -6202
  5. package/src/components/booking/AdminChangeCheckoutDialogs.tsx +105 -0
  6. package/src/components/booking/AdminChangeCheckoutPanel.tsx +307 -0
  7. package/src/components/booking/AdminChangePricingPanel.tsx +244 -0
  8. package/src/components/booking/AdminChangeProductSwitcher.tsx +50 -0
  9. package/src/components/booking/AdminChangeReceiptComparison.tsx +167 -0
  10. package/src/components/booking/ChangeBookingCalendarPanel.tsx +126 -0
  11. package/src/components/booking/ChangeBookingCheckoutPanel.tsx +204 -0
  12. package/src/components/booking/ChangeBookingFlow.tsx +576 -4648
  13. package/src/components/booking/ChangeBookingItineraryPanel.tsx +115 -0
  14. package/src/components/booking/ChangeBookingQuoteStatusPlaceholder.tsx +57 -0
  15. package/src/components/booking/ChangeBookingSelectionControlsPanel.tsx +157 -0
  16. package/src/components/booking/ChangeBookingTicketsAndAddOnsPanel.tsx +102 -0
  17. package/src/components/booking/CheckoutModal.tsx +68 -49
  18. package/src/components/booking/NewBookingFlow.tsx +485 -3505
  19. package/src/components/booking/PriceBreakdown.tsx +17 -3
  20. package/src/components/booking/PriceSummary.tsx +21 -3
  21. package/src/components/booking/PrivateShuttleAddOnsSection.tsx +102 -0
  22. package/src/components/booking/PrivateShuttleBookingFlow.tsx +407 -2788
  23. package/src/components/booking/PrivateShuttleCheckoutDialogs.tsx +106 -0
  24. package/src/components/booking/PrivateShuttleCheckoutSection.tsx +333 -0
  25. package/src/components/booking/PrivateShuttleItinerarySection.tsx +95 -0
  26. package/src/components/booking/PrivateShuttleMediaIntro.tsx +62 -0
  27. package/src/components/booking/PrivateShuttleOptionSection.tsx +81 -0
  28. package/src/components/booking/PrivateShuttlePassengerSection.tsx +148 -0
  29. package/src/components/booking/PrivateShuttlePickupSection.tsx +91 -0
  30. package/src/components/booking/PrivateShuttlePreferencesSection.tsx +75 -0
  31. package/src/components/booking/PrivateShuttleStartTimeSection.tsx +88 -0
  32. package/src/components/booking/StandardBookingCheckoutDialogs.tsx +106 -0
  33. package/src/components/booking/StandardBookingCheckoutSection.tsx +185 -0
  34. package/src/components/booking/StandardBookingItineraryPanel.tsx +125 -0
  35. package/src/components/booking/StandardBookingMediaIntro.tsx +69 -0
  36. package/src/components/booking/StandardBookingSelectionControlsPanel.tsx +236 -0
  37. package/src/components/booking/admin-change-customer-quote-runner.ts +119 -0
  38. package/src/components/booking/admin-change-flow-state-helpers.ts +124 -0
  39. package/src/components/booking/admin-change-payment-choice-runner.ts +172 -0
  40. package/src/components/booking/admin-change-provider-payload.ts +101 -0
  41. package/src/components/booking/change-booking-checkout-builders.ts +185 -0
  42. package/src/components/booking/change-booking-checkout-quote-runner.ts +207 -0
  43. package/src/components/booking/change-booking-flow-helpers.ts +706 -0
  44. package/src/components/booking/change-booking-payment-modal-builders.ts +151 -0
  45. package/src/components/booking/change-booking-quote-guards.ts +223 -0
  46. package/src/components/booking/change-booking-quote-state.ts +64 -0
  47. package/src/components/booking/pricing-v2-checkout-summary.ts +144 -0
  48. package/src/components/booking/private-shuttle-availability.ts +111 -0
  49. package/src/components/booking/private-shuttle-checkout-builders.ts +264 -0
  50. package/src/components/booking/private-shuttle-checkout-controller.ts +744 -0
  51. package/src/components/booking/private-shuttle-payment-choice-runner.ts +271 -0
  52. package/src/components/booking/private-shuttle-provider-change-runner.ts +73 -0
  53. package/src/components/booking/private-shuttle-reservation-runner.ts +260 -0
  54. package/src/components/booking/standard-booking-availability.ts +305 -0
  55. package/src/components/booking/standard-booking-checkout-builders.ts +289 -0
  56. package/src/components/booking/standard-booking-checkout-controller.ts +659 -0
  57. package/src/components/booking/standard-booking-payment-choice-runner.ts +274 -0
  58. package/src/components/booking/standard-booking-reservation-runner.ts +229 -0
  59. package/src/components/booking/use-private-shuttle-availability.ts +602 -0
  60. package/src/components/booking/use-standard-booking-availability.ts +806 -0
  61. package/src/components/booking/useActiveProductOptions.ts +26 -0
  62. package/src/components/booking/useAdminChangeCheckoutController.ts +806 -0
  63. package/src/components/booking/useAdminChangeOrderSummaryModel.ts +246 -0
  64. package/src/components/booking/useAdminChangePriceSummary.ts +416 -0
  65. package/src/components/booking/useAdminChangePricingDebugPanel.tsx +178 -0
  66. package/src/components/booking/useAdminChangeProductReset.ts +60 -0
  67. package/src/components/booking/useAdminChangeProducts.ts +102 -0
  68. package/src/components/booking/useAdminChangePromoDiscount.ts +235 -0
  69. package/src/components/booking/useAdminChangeProtectedPricing.ts +280 -0
  70. package/src/components/booking/useAdminChangeQuoteDisplayState.tsx +437 -0
  71. package/src/components/booking/useAdminChangeQuotePreview.ts +506 -0
  72. package/src/components/booking/useAdminChangeReceiptDerivation.ts +203 -0
  73. package/src/components/booking/useAdminCustomReceiptLines.ts +57 -0
  74. package/src/components/booking/useAdminProviderPricingAdjustments.ts +146 -0
  75. package/src/components/booking/useBookingAvailabilityAddOns.ts +54 -0
  76. package/src/components/booking/useBookingPromoAndQuantityController.ts +163 -0
  77. package/src/components/booking/useBookingQuantityCapTrim.ts +56 -0
  78. package/src/components/booking/useBookingViewItemAnalytics.ts +30 -0
  79. package/src/components/booking/useChangeBookingAddOnFloorController.ts +109 -0
  80. package/src/components/booking/useChangeBookingAutoSelections.ts +148 -0
  81. package/src/components/booking/useChangeBookingAvailabilities.ts +692 -0
  82. package/src/components/booking/useChangeBookingCheckoutController.ts +461 -0
  83. package/src/components/booking/useChangeBookingInitialHydration.ts +204 -0
  84. package/src/components/booking/useChangeBookingItineraryUiState.ts +133 -0
  85. package/src/components/booking/useChangeBookingPickupItinerary.ts +472 -0
  86. package/src/components/booking/useChangeBookingPriceSummary.ts +199 -0
  87. package/src/components/booking/useChangeBookingPromoDiscount.ts +218 -0
  88. package/src/components/booking/useChangeBookingProtectedPricing.ts +256 -0
  89. package/src/components/booking/useChangeBookingQuotePreview.ts +442 -0
  90. package/src/components/booking/useChangeBookingReceiptDerivation.ts +128 -0
  91. package/src/components/booking/useChangeBookingReceiptFloorController.ts +449 -0
  92. package/src/components/booking/useChangeBookingSelection.ts +362 -0
  93. package/src/components/booking/useChangeBookingSelectionDetails.ts +200 -0
  94. package/src/components/booking/useChangeBookingSummaryLines.ts +169 -0
  95. package/src/components/booking/usePrivateShuttlePriceSummary.ts +513 -0
  96. package/src/components/booking/usePrivateShuttlePromoController.ts +143 -0
  97. package/src/components/booking/usePrivateShuttlePromoDiscount.ts +124 -0
  98. package/src/components/booking/useSeedPromoCodeInput.ts +13 -0
  99. package/src/components/booking/useStandardBookingAutoSelections.ts +224 -0
  100. package/src/components/booking/useStandardBookingPickupItinerary.ts +473 -0
  101. package/src/components/booking/useStandardBookingPriceSummary.ts +438 -0
  102. package/src/components/booking/useStandardBookingPromoController.ts +258 -0
  103. package/src/components/booking/useStandardBookingPromoDiscount.ts +203 -0
  104. package/src/data/products-config.json +1 -1
  105. package/src/lib/booking/change-booking-server-preview.ts +134 -20
  106. package/src/lib/booking/change-flow-pricing.ts +31 -11
  107. package/src/lib/booking/checkout-breakdown.ts +66 -1
  108. package/src/lib/booking/pricing-config.ts +10 -0
  109. package/src/lib/booking/source-metadata.ts +58 -0
  110. package/src/lib/booking-api.ts +155 -3
  111. package/src/lib/pricing-v2-shadow.ts +272 -0
  112. package/test/change-booking-helpers.test.ts +206 -0
@@ -0,0 +1,264 @@
1
+ import type {
2
+ AddOn,
3
+ CheckoutBreakdown,
4
+ PricingV2QuoteSnapshot,
5
+ ProductOption,
6
+ } from '../../lib/booking-api';
7
+ import type { CheckoutLineInput } from '../../lib/booking/checkout-breakdown';
8
+ import {
9
+ buildCheckoutBreakdown,
10
+ buildCheckoutBreakdownFromPricingV2Quote,
11
+ round2,
12
+ } from '../../lib/booking/checkout-breakdown';
13
+ import type { OrderSummaryFeeLine } from '../../lib/booking/pricing';
14
+ import type { CheckoutModalLineItem, CheckoutModalSummaryOverride } from './CheckoutModal';
15
+ import { buildCheckoutModalSummaryFromPricingV2Quote } from './pricing-v2-checkout-summary';
16
+
17
+ type PrivateShuttleConfig = NonNullable<ProductOption['privateShuttleConfig']>;
18
+ type PrivateShuttleDepositConfig = NonNullable<PrivateShuttleConfig['depositConfig']>;
19
+
20
+ export type PrivateShuttleAddOnSelection = {
21
+ addOnId: string;
22
+ variantId?: string;
23
+ quantity?: number;
24
+ };
25
+
26
+ export type PrivateShuttleDepositInfo = {
27
+ depositAmount: number;
28
+ balanceAmount: number;
29
+ totalPrice: number;
30
+ };
31
+
32
+ export interface BuildPrivateShuttleCheckoutArtifactsParams {
33
+ resourceCount: number;
34
+ resourcePrice: number;
35
+ basePrice: number;
36
+ addOnSelections: PrivateShuttleAddOnSelection[];
37
+ addOns: AddOn[];
38
+ additionalHoursAmount: number;
39
+ additionalHoursCount: number;
40
+ perBookingFeeLineItems: OrderSummaryFeeLine[];
41
+ cancellationPolicyFee: number;
42
+ cancellationPolicyLabel?: string;
43
+ effectiveTaxAmount: number;
44
+ taxLabel: string;
45
+ effectivePromoDiscountAmount: number;
46
+ activePromoCode?: string | null;
47
+ discountLabel: string;
48
+ promoLineType: 'GIFT_CARD' | 'PROMO_CODE';
49
+ depositInfo: PrivateShuttleDepositInfo | null;
50
+ depositConfig?: PrivateShuttleDepositConfig;
51
+ totalPrice: number;
52
+ currency: string;
53
+ pricingV2Quote?: PricingV2QuoteSnapshot | null;
54
+ roundingLabel: string;
55
+ }
56
+
57
+ export interface PrivateShuttleCheckoutArtifacts {
58
+ checkoutBreakdown: CheckoutBreakdown;
59
+ pricingV2SummaryOverride?: CheckoutModalSummaryOverride;
60
+ receiptTotal: number;
61
+ checkoutDepositInfo: PrivateShuttleDepositInfo | null;
62
+ ticketLinesForModal: CheckoutModalLineItem[];
63
+ feeLineItemsForModal: OrderSummaryFeeLine[];
64
+ }
65
+
66
+ function buildPrivateShuttleAddOnLineItems(
67
+ addOnSelections: PrivateShuttleAddOnSelection[],
68
+ addOns: AddOn[]
69
+ ): {
70
+ checkoutLines: CheckoutLineInput[];
71
+ modalFeeLineItems: OrderSummaryFeeLine[];
72
+ } {
73
+ const checkoutLines: CheckoutLineInput[] = [];
74
+ const modalFeeLineItems: OrderSummaryFeeLine[] = [];
75
+
76
+ for (const selection of addOnSelections) {
77
+ const addOn = addOns.find((candidate) => candidate.addOnId === selection.addOnId);
78
+ if (!addOn) continue;
79
+
80
+ const hasVariant =
81
+ (addOn.variantType === 'single_choice' || addOn.variantType === 'multi_quantity') &&
82
+ selection.variantId;
83
+ const variant = hasVariant
84
+ ? addOn.variants?.find((candidate) => candidate.id === selection.variantId)
85
+ : null;
86
+ const quantity = selection.quantity ?? 1;
87
+ const amount = ((addOn.price ?? 0) + (variant?.priceAdjustment ?? 0)) * quantity;
88
+ const checkoutLabel = variant?.label
89
+ ? `${addOn.name} (${variant.label})${quantity > 1 ? ` \u00d7 ${quantity}` : ''}`
90
+ : addOn.name;
91
+
92
+ checkoutLines.push({
93
+ label: checkoutLabel,
94
+ amount,
95
+ type: 'FEE',
96
+ });
97
+ modalFeeLineItems.push({
98
+ name: addOn.name,
99
+ totalAmount: amount,
100
+ });
101
+ }
102
+
103
+ return { checkoutLines, modalFeeLineItems };
104
+ }
105
+
106
+ function buildPrivateShuttleCheckoutDepositInfo({
107
+ originalDepositInfo,
108
+ depositConfig,
109
+ receiptTotal,
110
+ }: {
111
+ originalDepositInfo: PrivateShuttleDepositInfo | null;
112
+ depositConfig?: PrivateShuttleDepositConfig;
113
+ receiptTotal: number;
114
+ }): PrivateShuttleDepositInfo | null {
115
+ if (!originalDepositInfo) return null;
116
+ if (!depositConfig || receiptTotal <= 0) return originalDepositInfo;
117
+
118
+ let depositAmount = 0;
119
+ if (depositConfig.percentage != null) {
120
+ const pct = depositConfig.percentage;
121
+ depositAmount = pct <= 1 ? receiptTotal * pct : (receiptTotal * pct) / 100;
122
+ } else if (depositConfig.fixedAmount != null) {
123
+ depositAmount = depositConfig.fixedAmount;
124
+ }
125
+
126
+ depositAmount = round2(Math.min(Math.max(depositAmount, 0), receiptTotal));
127
+ if (depositAmount <= 0) return null;
128
+
129
+ return {
130
+ depositAmount,
131
+ balanceAmount: round2(receiptTotal - depositAmount),
132
+ totalPrice: receiptTotal,
133
+ };
134
+ }
135
+
136
+ export function buildPrivateShuttleCheckoutArtifacts(
137
+ params: BuildPrivateShuttleCheckoutArtifactsParams
138
+ ): PrivateShuttleCheckoutArtifacts {
139
+ const {
140
+ resourceCount,
141
+ resourcePrice,
142
+ basePrice,
143
+ addOnSelections,
144
+ addOns,
145
+ additionalHoursAmount,
146
+ additionalHoursCount,
147
+ perBookingFeeLineItems,
148
+ cancellationPolicyFee,
149
+ cancellationPolicyLabel,
150
+ effectiveTaxAmount,
151
+ taxLabel,
152
+ effectivePromoDiscountAmount,
153
+ activePromoCode,
154
+ discountLabel,
155
+ promoLineType,
156
+ depositInfo,
157
+ depositConfig,
158
+ totalPrice,
159
+ currency,
160
+ pricingV2Quote,
161
+ roundingLabel,
162
+ } = params;
163
+
164
+ const { checkoutLines: addOnCheckoutLines, modalFeeLineItems: addOnFeeLineItemsForModal } =
165
+ buildPrivateShuttleAddOnLineItems(addOnSelections, addOns);
166
+
167
+ const lines: CheckoutLineInput[] = [
168
+ {
169
+ label: resourceCount > 1 ? 'Shuttles' : 'Shuttle',
170
+ amount: basePrice,
171
+ type: 'TICKET',
172
+ quantity: resourceCount,
173
+ },
174
+ ...addOnCheckoutLines,
175
+ ...(additionalHoursAmount > 0
176
+ ? [
177
+ {
178
+ label:
179
+ additionalHoursCount === 1
180
+ ? 'Additional hour'
181
+ : `Additional hours (${additionalHoursCount})`,
182
+ amount: additionalHoursAmount,
183
+ type: 'ADDITIONAL_HOURS',
184
+ },
185
+ ]
186
+ : []),
187
+ ...perBookingFeeLineItems.map((fee) => ({
188
+ label: fee.name,
189
+ amount: fee.totalAmount,
190
+ type: 'FEE',
191
+ })),
192
+ ...(cancellationPolicyFee > 0 && cancellationPolicyLabel
193
+ ? [
194
+ {
195
+ label: cancellationPolicyLabel,
196
+ amount: cancellationPolicyFee,
197
+ type: 'CANCELLATION_UPGRADE',
198
+ },
199
+ ]
200
+ : []),
201
+ ...(effectiveTaxAmount > 0
202
+ ? [
203
+ {
204
+ label: taxLabel,
205
+ amount: effectiveTaxAmount,
206
+ type: 'TAX',
207
+ },
208
+ ]
209
+ : []),
210
+ ];
211
+ const legacyReceiptTotal = depositInfo ? depositInfo.totalPrice : totalPrice;
212
+ const linesWithPromo: CheckoutLineInput[] = [
213
+ ...lines,
214
+ ...(effectivePromoDiscountAmount > 0
215
+ ? [
216
+ {
217
+ label: activePromoCode ? `Promo: ${activePromoCode}` : discountLabel,
218
+ amount: -effectivePromoDiscountAmount,
219
+ type: promoLineType,
220
+ },
221
+ ]
222
+ : []),
223
+ ];
224
+ const legacyCheckoutBreakdown = buildCheckoutBreakdown({
225
+ lines: linesWithPromo,
226
+ totalAmount: legacyReceiptTotal,
227
+ currency,
228
+ roundingLabel,
229
+ });
230
+ const checkoutBreakdown =
231
+ buildCheckoutBreakdownFromPricingV2Quote(pricingV2Quote, roundingLabel) ??
232
+ legacyCheckoutBreakdown;
233
+ const pricingV2SummaryOverride = buildCheckoutModalSummaryFromPricingV2Quote(
234
+ pricingV2Quote,
235
+ roundingLabel
236
+ );
237
+ const receiptTotal = checkoutBreakdown.totalAmount;
238
+ const checkoutDepositInfo = buildPrivateShuttleCheckoutDepositInfo({
239
+ originalDepositInfo: depositInfo,
240
+ depositConfig,
241
+ receiptTotal,
242
+ });
243
+ const ticketLinesForModal: CheckoutModalLineItem[] = [
244
+ {
245
+ line: {
246
+ category: 'Shuttle',
247
+ qty: resourceCount,
248
+ pricePerUnit: resourcePrice,
249
+ itemTotal: basePrice,
250
+ },
251
+ breakdown: null,
252
+ },
253
+ ];
254
+ const feeLineItemsForModal = [...addOnFeeLineItemsForModal, ...perBookingFeeLineItems];
255
+
256
+ return {
257
+ checkoutBreakdown,
258
+ pricingV2SummaryOverride,
259
+ receiptTotal,
260
+ checkoutDepositInfo,
261
+ ticketLinesForModal,
262
+ feeLineItemsForModal,
263
+ };
264
+ }