@ticketboothapp/booking 1.2.122 → 1.2.124
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/CHANGE_BOOKING_BE_HANDOFF.md +15 -4
- package/package.json +1 -1
- package/src/components/booking/AdminChangeBookingContent.tsx +276 -0
- package/src/components/booking/AdminChangeBookingFlow.tsx +647 -6157
- package/src/components/booking/AdminChangeCheckoutDialogs.tsx +105 -0
- package/src/components/booking/AdminChangeCheckoutPanel.tsx +307 -0
- package/src/components/booking/AdminChangePricingPanel.tsx +244 -0
- package/src/components/booking/AdminChangeProductSwitcher.tsx +50 -0
- package/src/components/booking/AdminChangeReceiptComparison.tsx +167 -0
- package/src/components/booking/ChangeBookingCalendarPanel.tsx +126 -0
- package/src/components/booking/ChangeBookingCheckoutPanel.tsx +204 -0
- package/src/components/booking/ChangeBookingFlow.tsx +576 -4648
- package/src/components/booking/ChangeBookingItineraryPanel.tsx +115 -0
- package/src/components/booking/ChangeBookingQuoteStatusPlaceholder.tsx +57 -0
- package/src/components/booking/ChangeBookingSelectionControlsPanel.tsx +157 -0
- package/src/components/booking/ChangeBookingTicketsAndAddOnsPanel.tsx +102 -0
- package/src/components/booking/CheckoutModal.tsx +68 -49
- package/src/components/booking/NewBookingFlow.tsx +485 -3505
- package/src/components/booking/PriceBreakdown.tsx +17 -3
- package/src/components/booking/PriceSummary.tsx +21 -3
- package/src/components/booking/PrivateShuttleAddOnsSection.tsx +102 -0
- package/src/components/booking/PrivateShuttleBookingFlow.tsx +407 -2788
- package/src/components/booking/PrivateShuttleCheckoutDialogs.tsx +106 -0
- package/src/components/booking/PrivateShuttleCheckoutSection.tsx +333 -0
- package/src/components/booking/PrivateShuttleItinerarySection.tsx +95 -0
- package/src/components/booking/PrivateShuttleMediaIntro.tsx +62 -0
- package/src/components/booking/PrivateShuttleOptionSection.tsx +81 -0
- package/src/components/booking/PrivateShuttlePassengerSection.tsx +148 -0
- package/src/components/booking/PrivateShuttlePickupSection.tsx +91 -0
- package/src/components/booking/PrivateShuttlePreferencesSection.tsx +75 -0
- package/src/components/booking/PrivateShuttleStartTimeSection.tsx +88 -0
- package/src/components/booking/StandardBookingCheckoutDialogs.tsx +106 -0
- package/src/components/booking/StandardBookingCheckoutSection.tsx +185 -0
- package/src/components/booking/StandardBookingItineraryPanel.tsx +125 -0
- package/src/components/booking/StandardBookingMediaIntro.tsx +69 -0
- package/src/components/booking/StandardBookingSelectionControlsPanel.tsx +236 -0
- package/src/components/booking/admin-change-customer-quote-runner.ts +119 -0
- package/src/components/booking/admin-change-flow-state-helpers.ts +124 -0
- package/src/components/booking/admin-change-payment-choice-runner.ts +172 -0
- package/src/components/booking/admin-change-provider-payload.ts +101 -0
- package/src/components/booking/change-booking-checkout-builders.ts +185 -0
- package/src/components/booking/change-booking-checkout-quote-runner.ts +207 -0
- package/src/components/booking/change-booking-flow-helpers.ts +706 -0
- package/src/components/booking/change-booking-payment-modal-builders.ts +151 -0
- package/src/components/booking/change-booking-quote-guards.ts +223 -0
- package/src/components/booking/change-booking-quote-state.ts +64 -0
- package/src/components/booking/pricing-v2-checkout-summary.ts +144 -0
- package/src/components/booking/private-shuttle-availability.ts +111 -0
- package/src/components/booking/private-shuttle-checkout-builders.ts +264 -0
- package/src/components/booking/private-shuttle-checkout-controller.ts +744 -0
- package/src/components/booking/private-shuttle-payment-choice-runner.ts +271 -0
- package/src/components/booking/private-shuttle-provider-change-runner.ts +73 -0
- package/src/components/booking/private-shuttle-reservation-runner.ts +260 -0
- package/src/components/booking/standard-booking-availability.ts +305 -0
- package/src/components/booking/standard-booking-checkout-builders.ts +289 -0
- package/src/components/booking/standard-booking-checkout-controller.ts +659 -0
- package/src/components/booking/standard-booking-payment-choice-runner.ts +274 -0
- package/src/components/booking/standard-booking-reservation-runner.ts +229 -0
- package/src/components/booking/use-private-shuttle-availability.ts +602 -0
- package/src/components/booking/use-standard-booking-availability.ts +806 -0
- package/src/components/booking/useActiveProductOptions.ts +26 -0
- package/src/components/booking/useAdminChangeCheckoutController.ts +806 -0
- package/src/components/booking/useAdminChangeOrderSummaryModel.ts +246 -0
- package/src/components/booking/useAdminChangePriceSummary.ts +416 -0
- package/src/components/booking/useAdminChangePricingDebugPanel.tsx +178 -0
- package/src/components/booking/useAdminChangeProductReset.ts +60 -0
- package/src/components/booking/useAdminChangeProducts.ts +102 -0
- package/src/components/booking/useAdminChangePromoDiscount.ts +235 -0
- package/src/components/booking/useAdminChangeProtectedPricing.ts +280 -0
- package/src/components/booking/useAdminChangeQuoteDisplayState.tsx +437 -0
- package/src/components/booking/useAdminChangeQuotePreview.ts +506 -0
- package/src/components/booking/useAdminChangeReceiptDerivation.ts +203 -0
- package/src/components/booking/useAdminCustomReceiptLines.ts +57 -0
- package/src/components/booking/useAdminProviderPricingAdjustments.ts +146 -0
- package/src/components/booking/useBookingAvailabilityAddOns.ts +54 -0
- package/src/components/booking/useBookingPromoAndQuantityController.ts +163 -0
- package/src/components/booking/useBookingQuantityCapTrim.ts +56 -0
- package/src/components/booking/useBookingViewItemAnalytics.ts +30 -0
- package/src/components/booking/useChangeBookingAddOnFloorController.ts +109 -0
- package/src/components/booking/useChangeBookingAutoSelections.ts +148 -0
- package/src/components/booking/useChangeBookingAvailabilities.ts +692 -0
- package/src/components/booking/useChangeBookingCheckoutController.ts +461 -0
- package/src/components/booking/useChangeBookingInitialHydration.ts +204 -0
- package/src/components/booking/useChangeBookingItineraryUiState.ts +133 -0
- package/src/components/booking/useChangeBookingPickupItinerary.ts +472 -0
- package/src/components/booking/useChangeBookingPriceSummary.ts +199 -0
- package/src/components/booking/useChangeBookingPromoDiscount.ts +218 -0
- package/src/components/booking/useChangeBookingProtectedPricing.ts +256 -0
- package/src/components/booking/useChangeBookingQuotePreview.ts +442 -0
- package/src/components/booking/useChangeBookingReceiptDerivation.ts +128 -0
- package/src/components/booking/useChangeBookingReceiptFloorController.ts +449 -0
- package/src/components/booking/useChangeBookingSelection.ts +362 -0
- package/src/components/booking/useChangeBookingSelectionDetails.ts +200 -0
- package/src/components/booking/useChangeBookingSummaryLines.ts +169 -0
- package/src/components/booking/usePrivateShuttlePriceSummary.ts +513 -0
- package/src/components/booking/usePrivateShuttlePromoController.ts +143 -0
- package/src/components/booking/usePrivateShuttlePromoDiscount.ts +124 -0
- package/src/components/booking/useSeedPromoCodeInput.ts +13 -0
- package/src/components/booking/useStandardBookingAutoSelections.ts +224 -0
- package/src/components/booking/useStandardBookingPickupItinerary.ts +473 -0
- package/src/components/booking/useStandardBookingPriceSummary.ts +438 -0
- package/src/components/booking/useStandardBookingPromoController.ts +258 -0
- package/src/components/booking/useStandardBookingPromoDiscount.ts +203 -0
- package/src/data/products-config.json +1 -1
- package/src/lib/booking/change-booking-server-preview.ts +134 -20
- package/src/lib/booking/change-flow-pricing.ts +31 -11
- package/src/lib/booking/checkout-breakdown.ts +66 -1
- package/src/lib/booking/pricing-config.ts +10 -0
- package/src/lib/booking/source-metadata.ts +58 -0
- package/src/lib/booking-api.ts +154 -3
- package/src/lib/pricing-v2-shadow.ts +272 -0
- package/test/change-booking-helpers.test.ts +206 -0
|
@@ -130,8 +130,16 @@ export function PriceBreakdown({
|
|
|
130
130
|
);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
const editableHoverHandlers =
|
|
134
|
+
editable && canShowBreakdown
|
|
135
|
+
? {
|
|
136
|
+
onMouseEnter: () => setShowTooltip(true),
|
|
137
|
+
onMouseLeave: () => setShowTooltip(false),
|
|
138
|
+
}
|
|
139
|
+
: {};
|
|
140
|
+
|
|
133
141
|
return (
|
|
134
|
-
<div className="flex items-center justify-between gap-3 min-w-0">
|
|
142
|
+
<div className="flex items-center justify-between gap-3 min-w-0" {...editableHoverHandlers}>
|
|
135
143
|
{editable && onEditableLabelChange ? (
|
|
136
144
|
<input
|
|
137
145
|
type="text"
|
|
@@ -141,7 +149,13 @@ export function PriceBreakdown({
|
|
|
141
149
|
aria-label={`Edit ${category} label`}
|
|
142
150
|
/>
|
|
143
151
|
) : (
|
|
144
|
-
<span
|
|
152
|
+
<span
|
|
153
|
+
className={
|
|
154
|
+
editable && canShowBreakdown
|
|
155
|
+
? 'text-sm text-stone-600 min-w-0 truncate cursor-help underline decoration-dotted underline-offset-2'
|
|
156
|
+
: 'text-sm text-stone-600 min-w-0 truncate'
|
|
157
|
+
}
|
|
158
|
+
>
|
|
145
159
|
{category} {qty > 1 ? `× ${qty}` : ''}
|
|
146
160
|
</span>
|
|
147
161
|
)}
|
|
@@ -194,7 +208,7 @@ export function PriceBreakdown({
|
|
|
194
208
|
)}
|
|
195
209
|
</span>
|
|
196
210
|
)}
|
|
197
|
-
{
|
|
211
|
+
{canShowBreakdown && showTooltip && (
|
|
198
212
|
<div className="absolute right-0 top-full mt-2 w-72 p-3 bg-stone-900 text-white text-xs rounded-lg shadow-xl z-50">
|
|
199
213
|
<div className="font-semibold mb-2 pb-2 border-b border-stone-700">
|
|
200
214
|
Price Breakdown ({category})
|
|
@@ -86,7 +86,12 @@ export interface PriceSummaryProps {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
function getLineAmountClass(type: string | undefined, amount: number): string {
|
|
89
|
-
const isDiscount =
|
|
89
|
+
const isDiscount =
|
|
90
|
+
amount < 0 ||
|
|
91
|
+
type === 'PROMO_CODE' ||
|
|
92
|
+
type === 'DISCOUNT' ||
|
|
93
|
+
type === 'GIFT_CARD' ||
|
|
94
|
+
type === 'PAYMENT_CREDIT';
|
|
90
95
|
const isAddOn = (type === 'RETURN_OPTION' || type === 'return') && amount > 0;
|
|
91
96
|
if (isDiscount) return 'font-medium text-red-600';
|
|
92
97
|
if (isAddOn) return 'font-medium text-emerald-600';
|
|
@@ -106,6 +111,18 @@ function formatLineAmount(
|
|
|
106
111
|
return formatted;
|
|
107
112
|
}
|
|
108
113
|
|
|
114
|
+
function displaySummaryLineLabel(label: string, type: string | undefined): string {
|
|
115
|
+
const normalizedType = String(type ?? '').trim().toUpperCase();
|
|
116
|
+
const normalizedLabel = label.trim().toLowerCase();
|
|
117
|
+
if (
|
|
118
|
+
(normalizedType === 'GIFT_CARD' || normalizedType === 'PAYMENT_CREDIT') &&
|
|
119
|
+
(normalizedLabel === 'gift card' || normalizedLabel === 'payment credit')
|
|
120
|
+
) {
|
|
121
|
+
return 'Gift card comp';
|
|
122
|
+
}
|
|
123
|
+
return label;
|
|
124
|
+
}
|
|
125
|
+
|
|
109
126
|
function shouldAppendQuantitySuffix(type: string | undefined, label: string, quantity: number | null | undefined): boolean {
|
|
110
127
|
if (quantity == null || quantity <= 1) return false;
|
|
111
128
|
const normalizedType = String(type ?? '').trim().toUpperCase();
|
|
@@ -223,6 +240,7 @@ export function PriceSummary({
|
|
|
223
240
|
);
|
|
224
241
|
}
|
|
225
242
|
const { lineKey, label, amount, type, quantity, tooltip, editable } = row;
|
|
243
|
+
const shownLabel = displaySummaryLineLabel(label, type);
|
|
226
244
|
// Receipt mode: insert Subtotal row before first TAX line
|
|
227
245
|
const isTaxLine = type === 'TAX';
|
|
228
246
|
const showSubtotalBeforeTax = isTaxLine && subtotal != null && subtotal > 0 && !subtotalShown;
|
|
@@ -250,8 +268,8 @@ export function PriceSummary({
|
|
|
250
268
|
/>
|
|
251
269
|
) : (
|
|
252
270
|
<span className="min-w-0 truncate">
|
|
253
|
-
{
|
|
254
|
-
{shouldAppendQuantitySuffix(type,
|
|
271
|
+
{shownLabel}
|
|
272
|
+
{shouldAppendQuantitySuffix(type, shownLabel, quantity) ? ` (x${quantity})` : ''}
|
|
255
273
|
</span>
|
|
256
274
|
)}
|
|
257
275
|
{tooltip && <InfoTooltip text={tooltip} />}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { AddOn } from '../../lib/booking-api';
|
|
2
|
+
import { formatCurrencyAmount } from '../../lib/currency';
|
|
3
|
+
import type { Locale } from '../../lib/booking/i18n/config';
|
|
4
|
+
import type { Currency } from './CurrencySwitcher';
|
|
5
|
+
import { MealDrinkAddOnSelector, canUseMealDrinkSelector } from './MealDrinkAddOnSelector';
|
|
6
|
+
import styles from './PrivateShuttleBookingFlow.module.css';
|
|
7
|
+
|
|
8
|
+
export type PrivateShuttleAddOnSelection = {
|
|
9
|
+
addOnId: string;
|
|
10
|
+
variantId?: string;
|
|
11
|
+
quantity?: number;
|
|
12
|
+
};
|
|
13
|
+
type PrivateShuttleAddOnSelectionUpdate =
|
|
14
|
+
| PrivateShuttleAddOnSelection[]
|
|
15
|
+
| ((prev: PrivateShuttleAddOnSelection[]) => PrivateShuttleAddOnSelection[]);
|
|
16
|
+
|
|
17
|
+
export interface PrivateShuttleAddOnsSectionProps {
|
|
18
|
+
passengerCount: number;
|
|
19
|
+
addOns: AddOn[];
|
|
20
|
+
addOnSelections: PrivateShuttleAddOnSelection[];
|
|
21
|
+
selectedDestinationIds: string[];
|
|
22
|
+
currency: Currency;
|
|
23
|
+
locale: Locale;
|
|
24
|
+
onAddOnSelectionsChange: (update: PrivateShuttleAddOnSelectionUpdate) => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function PrivateShuttleAddOnsSection({
|
|
28
|
+
passengerCount,
|
|
29
|
+
addOns,
|
|
30
|
+
addOnSelections,
|
|
31
|
+
selectedDestinationIds,
|
|
32
|
+
currency,
|
|
33
|
+
locale,
|
|
34
|
+
onAddOnSelectionsChange,
|
|
35
|
+
}: PrivateShuttleAddOnsSectionProps) {
|
|
36
|
+
if (passengerCount <= 0 || addOns.length === 0) return null;
|
|
37
|
+
|
|
38
|
+
const animalsAddOn = addOns.find((addOn) => addOn.addOnId === 'addon_animals');
|
|
39
|
+
const isAnimalsSelected = addOnSelections.some((selection) => selection.addOnId === 'addon_animals');
|
|
40
|
+
const lunchAddOn = selectedDestinationIds.includes('emerald_lake')
|
|
41
|
+
? addOns.find((addOn) => addOn.addOnId === 'addon_el_lunch')
|
|
42
|
+
: null;
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div className={styles.section}>
|
|
46
|
+
{lunchAddOn && canUseMealDrinkSelector(lunchAddOn) ? (
|
|
47
|
+
<MealDrinkAddOnSelector
|
|
48
|
+
addOn={lunchAddOn}
|
|
49
|
+
selections={addOnSelections}
|
|
50
|
+
onSelectionsChange={(updater) =>
|
|
51
|
+
onAddOnSelectionsChange((prev) => updater(prev))
|
|
52
|
+
}
|
|
53
|
+
currency={currency}
|
|
54
|
+
locale={locale}
|
|
55
|
+
/>
|
|
56
|
+
) : null}
|
|
57
|
+
{animalsAddOn ? (
|
|
58
|
+
<div>
|
|
59
|
+
<label className={`${styles.sectionLabel} private-shuttle-section-label`}>
|
|
60
|
+
Traveling with animals?
|
|
61
|
+
</label>
|
|
62
|
+
<p className="text-sm text-stone-500 mb-2">
|
|
63
|
+
{animalsAddOn.description || 'Cleaning fee for traveling with animals'}
|
|
64
|
+
</p>
|
|
65
|
+
<div className="flex flex-wrap gap-2">
|
|
66
|
+
<button
|
|
67
|
+
type="button"
|
|
68
|
+
onClick={() =>
|
|
69
|
+
onAddOnSelectionsChange(
|
|
70
|
+
addOnSelections.filter((selection) => selection.addOnId !== 'addon_animals'),
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
className={`${styles.btnTime} private-shuttle-btn-time ${
|
|
74
|
+
!isAnimalsSelected ? styles.btnTimeSelected : styles.btnTimeDefault
|
|
75
|
+
}`}
|
|
76
|
+
>
|
|
77
|
+
No animals
|
|
78
|
+
</button>
|
|
79
|
+
<button
|
|
80
|
+
type="button"
|
|
81
|
+
onClick={() => {
|
|
82
|
+
if (isAnimalsSelected) return;
|
|
83
|
+
onAddOnSelectionsChange([
|
|
84
|
+
...addOnSelections,
|
|
85
|
+
{ addOnId: 'addon_animals', quantity: 1 },
|
|
86
|
+
]);
|
|
87
|
+
}}
|
|
88
|
+
className={`${styles.btnTime} private-shuttle-btn-time flex items-center gap-2 ${
|
|
89
|
+
isAnimalsSelected ? styles.btnTimeSelected : styles.btnTimeDefault
|
|
90
|
+
}`}
|
|
91
|
+
>
|
|
92
|
+
<span>Yes, traveling with animals</span>
|
|
93
|
+
<span className="text-sm font-semibold opacity-90">
|
|
94
|
+
+{formatCurrencyAmount(animalsAddOn.price || 0, currency, locale)}
|
|
95
|
+
</span>
|
|
96
|
+
</button>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
) : null}
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
}
|