@ticketboothapp/booking 1.2.93 → 1.2.94
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/package.json
CHANGED
|
@@ -44,6 +44,7 @@ import { CheckoutModal, type CheckoutModalLineItem } from './CheckoutModal';
|
|
|
44
44
|
import { CancellationPolicySelector } from './CancellationPolicySelector';
|
|
45
45
|
import { PriceSummary } from './PriceSummary';
|
|
46
46
|
import { TermsAcceptance } from './TermsAcceptance';
|
|
47
|
+
import { PromoCodeInput } from './PromoCodeInput';
|
|
47
48
|
import { ItineraryBuilder } from './ItineraryBuilder';
|
|
48
49
|
import { MealDrinkAddOnSelector, canUseMealDrinkSelector } from './MealDrinkAddOnSelector';
|
|
49
50
|
import { AdminPaymentChoiceModal } from './AdminPaymentChoiceModal';
|
|
@@ -261,6 +262,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
261
262
|
const [promoDiscountAmount, setPromoDiscountAmount] = useState(0);
|
|
262
263
|
const [isGiftCard, setIsGiftCard] = useState(false);
|
|
263
264
|
const [isVoucher, setIsVoucher] = useState(false);
|
|
265
|
+
const activePromoCode = isAdmin ? appliedPromoCode : null;
|
|
264
266
|
const [additionalHoursCount, setAdditionalHoursCount] = useState(
|
|
265
267
|
() => initialBooking?.additionalHoursCount ?? initialValues?.additionalHoursCount ?? 0
|
|
266
268
|
);
|
|
@@ -369,7 +371,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
369
371
|
const endDate = format(endOfDay(clampedEnd), 'yyyy-MM-dd');
|
|
370
372
|
const result = await getAvailabilities(product.productId, startDate, endDate, {
|
|
371
373
|
allOptions: true,
|
|
372
|
-
promoCode:
|
|
374
|
+
promoCode: activePromoCode || undefined,
|
|
373
375
|
...(pricingProfileIdForAvailabilities
|
|
374
376
|
? { pricingProfileId: pricingProfileIdForAvailabilities }
|
|
375
377
|
: {}),
|
|
@@ -417,7 +419,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
417
419
|
? buildAvailabilitiesCacheKey(
|
|
418
420
|
product.productId,
|
|
419
421
|
activeOptionIdsKey,
|
|
420
|
-
|
|
422
|
+
activePromoCode,
|
|
421
423
|
pricingProfileIdForAvailabilities,
|
|
422
424
|
)
|
|
423
425
|
: null;
|
|
@@ -438,7 +440,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
438
440
|
product.productId,
|
|
439
441
|
selectedDate,
|
|
440
442
|
companyTimezone,
|
|
441
|
-
|
|
443
|
+
activePromoCode,
|
|
442
444
|
pricingProfileIdForAvailabilities,
|
|
443
445
|
cancellationPolicyProfileIdForAvailabilities,
|
|
444
446
|
activeOptionIdsKey,
|
|
@@ -477,7 +479,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
477
479
|
useEffect(() => {
|
|
478
480
|
fetchedRangesRef.current = [];
|
|
479
481
|
}, [
|
|
480
|
-
|
|
482
|
+
activePromoCode,
|
|
481
483
|
pricingProfileIdForAvailabilities,
|
|
482
484
|
cancellationPolicyProfileIdForAvailabilities,
|
|
483
485
|
]);
|
|
@@ -527,7 +529,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
527
529
|
? buildAvailabilitiesCacheKey(
|
|
528
530
|
product.productId,
|
|
529
531
|
activeOptionIdsKey,
|
|
530
|
-
|
|
532
|
+
activePromoCode,
|
|
531
533
|
pricingProfileIdForAvailabilities,
|
|
532
534
|
)
|
|
533
535
|
: null;
|
|
@@ -583,7 +585,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
583
585
|
const endDate = format(endOfDay(clampedEnd), 'yyyy-MM-dd');
|
|
584
586
|
const result = await getAvailabilities(product.productId, startDate, endDate, {
|
|
585
587
|
allOptions: true,
|
|
586
|
-
promoCode:
|
|
588
|
+
promoCode: activePromoCode || undefined,
|
|
587
589
|
...(pricingProfileIdForAvailabilities
|
|
588
590
|
? { pricingProfileId: pricingProfileIdForAvailabilities }
|
|
589
591
|
: {}),
|
|
@@ -657,7 +659,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
657
659
|
activeOptionIdsKey,
|
|
658
660
|
selectedDate,
|
|
659
661
|
product.productId,
|
|
660
|
-
|
|
662
|
+
activePromoCode,
|
|
661
663
|
pricingProfileIdForAvailabilities,
|
|
662
664
|
cancellationPolicyProfileIdForAvailabilities,
|
|
663
665
|
needsFetch,
|
|
@@ -864,7 +866,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
864
866
|
|
|
865
867
|
useEffect(() => {
|
|
866
868
|
if (
|
|
867
|
-
!
|
|
869
|
+
!activePromoCode ||
|
|
868
870
|
!selectedOption ||
|
|
869
871
|
!selectedDate ||
|
|
870
872
|
!selectedStartTime ||
|
|
@@ -879,7 +881,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
879
881
|
if (!companyId) return;
|
|
880
882
|
let cancelled = false;
|
|
881
883
|
getPromoDiscount(
|
|
882
|
-
|
|
884
|
+
activePromoCode,
|
|
883
885
|
companyId,
|
|
884
886
|
product.productId,
|
|
885
887
|
selectedOption,
|
|
@@ -906,7 +908,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
906
908
|
cancelled = true;
|
|
907
909
|
};
|
|
908
910
|
}, [
|
|
909
|
-
|
|
911
|
+
activePromoCode,
|
|
910
912
|
selectedOption,
|
|
911
913
|
selectedDate,
|
|
912
914
|
selectedStartTime,
|
|
@@ -1086,6 +1088,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
1086
1088
|
|
|
1087
1089
|
const handleApplyPromo = useCallback(async () => {
|
|
1088
1090
|
const code = promoCodeInput.trim().toUpperCase();
|
|
1091
|
+
if (!isAdmin) return;
|
|
1089
1092
|
if (!code || appliedPromoCode === code) return;
|
|
1090
1093
|
if (!product.companyId) return;
|
|
1091
1094
|
lastValidatedInputRef.current = code;
|
|
@@ -1116,6 +1119,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
1116
1119
|
}, [
|
|
1117
1120
|
promoCodeInput,
|
|
1118
1121
|
appliedPromoCode,
|
|
1122
|
+
isAdmin,
|
|
1119
1123
|
product.companyId,
|
|
1120
1124
|
product.productId,
|
|
1121
1125
|
hasOngoingDiscount,
|
|
@@ -1125,6 +1129,29 @@ export function PrivateShuttleBookingFlow({
|
|
|
1125
1129
|
const handleApplyPromoRef = useRef(handleApplyPromo);
|
|
1126
1130
|
handleApplyPromoRef.current = handleApplyPromo;
|
|
1127
1131
|
|
|
1132
|
+
useEffect(() => {
|
|
1133
|
+
if (!isAdmin) return;
|
|
1134
|
+
const trimmed = promoCodeInput.trim().toUpperCase();
|
|
1135
|
+
if (!trimmed) return;
|
|
1136
|
+
if (!selectedOption || !selectedStartTime || resourceCount === 0) return;
|
|
1137
|
+
if (appliedPromoCode === trimmed) return;
|
|
1138
|
+
if (lastValidatedInputRef.current === trimmed && promoCodeError) return;
|
|
1139
|
+
|
|
1140
|
+
const timer = setTimeout(() => {
|
|
1141
|
+
handleApplyPromoRef.current();
|
|
1142
|
+
}, 600);
|
|
1143
|
+
|
|
1144
|
+
return () => clearTimeout(timer);
|
|
1145
|
+
}, [
|
|
1146
|
+
isAdmin,
|
|
1147
|
+
promoCodeInput,
|
|
1148
|
+
appliedPromoCode,
|
|
1149
|
+
promoCodeError,
|
|
1150
|
+
selectedOption,
|
|
1151
|
+
selectedStartTime,
|
|
1152
|
+
resourceCount,
|
|
1153
|
+
]);
|
|
1154
|
+
|
|
1128
1155
|
const itineraryDisplayItems = useMemo(() => {
|
|
1129
1156
|
if (!selectedOption || !selectedStartTime) return [];
|
|
1130
1157
|
const items: Array<{
|
|
@@ -1276,7 +1303,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
1276
1303
|
foodRestrictions: foodRestrictions.trim() || null,
|
|
1277
1304
|
addOnSelections: addOnSelections.length > 0 ? addOnSelections : null,
|
|
1278
1305
|
cancellationPolicyId: cancellationPolicyId ?? initialBooking?.cancellationPolicyId ?? null,
|
|
1279
|
-
promoCode:
|
|
1306
|
+
promoCode: activePromoCode ?? null,
|
|
1280
1307
|
newTotalAmount: totalPrice,
|
|
1281
1308
|
additionalHoursCount: isAdmin ? additionalHoursCount : null,
|
|
1282
1309
|
});
|
|
@@ -1310,7 +1337,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
1310
1337
|
requestedPassengerCount: isSpecialRequest ? passengerCount : undefined,
|
|
1311
1338
|
pickupLocationId: pickupLocationId || undefined,
|
|
1312
1339
|
cancellationPolicyId: cancellationPolicyId || undefined,
|
|
1313
|
-
promoCode:
|
|
1340
|
+
promoCode: activePromoCode || undefined,
|
|
1314
1341
|
travelerHotel: selectedPickupLocation?.name || customPickupAddress || undefined,
|
|
1315
1342
|
draftItinerary:
|
|
1316
1343
|
draftItineraryDestinations.length > 0 || planningNotes
|
|
@@ -1427,8 +1454,8 @@ export function PrivateShuttleBookingFlow({
|
|
|
1427
1454
|
? [
|
|
1428
1455
|
{
|
|
1429
1456
|
label:
|
|
1430
|
-
|
|
1431
|
-
? `Promo: ${
|
|
1457
|
+
activePromoCode
|
|
1458
|
+
? `Promo: ${activePromoCode}`
|
|
1432
1459
|
: (t('booking.discount') || 'Discount'),
|
|
1433
1460
|
amount: -effectivePromoDiscountAmount,
|
|
1434
1461
|
type: isGiftCard ? 'GIFT_CARD' : 'PROMO_CODE',
|
|
@@ -1502,7 +1529,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
1502
1529
|
itineraryDisplay: itineraryDisplayForStorage,
|
|
1503
1530
|
termsAcceptedAt: termsAcceptedAt ?? undefined,
|
|
1504
1531
|
cancellationPolicyId: cancellationPolicyId || undefined,
|
|
1505
|
-
promoCode:
|
|
1532
|
+
promoCode: activePromoCode || undefined,
|
|
1506
1533
|
checkoutBreakdown,
|
|
1507
1534
|
paymentPlanType: 'DEPOSIT',
|
|
1508
1535
|
depositAmount: depositInfo.depositAmount,
|
|
@@ -1559,7 +1586,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
1559
1586
|
isTaxIncludedInPrice,
|
|
1560
1587
|
taxRate,
|
|
1561
1588
|
promoDiscountAmount: effectivePromoDiscountAmount > 0 ? effectivePromoDiscountAmount : 0,
|
|
1562
|
-
discountLabel:
|
|
1589
|
+
discountLabel: activePromoCode ? `Promo: ${activePromoCode}` : undefined,
|
|
1563
1590
|
});
|
|
1564
1591
|
setShowAdminPaymentChoice(true);
|
|
1565
1592
|
setLoading(false);
|
|
@@ -1582,7 +1609,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
1582
1609
|
itineraryDisplay: itineraryDisplayForStorage,
|
|
1583
1610
|
termsAcceptedAt: termsAcceptedAt ?? undefined,
|
|
1584
1611
|
cancellationPolicyId: cancellationPolicyId || undefined,
|
|
1585
|
-
promoCode:
|
|
1612
|
+
promoCode: activePromoCode || undefined,
|
|
1586
1613
|
checkoutBreakdown,
|
|
1587
1614
|
...(depositInfo && {
|
|
1588
1615
|
paymentPlanType: 'DEPOSIT' as const,
|
|
@@ -1674,7 +1701,7 @@ export function PrivateShuttleBookingFlow({
|
|
|
1674
1701
|
cancellationPolicyFee,
|
|
1675
1702
|
cancellationPolicyLabel: selectedCancellationPolicy?.label,
|
|
1676
1703
|
promoDiscountAmount: effectivePromoDiscountAmount > 0 ? effectivePromoDiscountAmount : 0,
|
|
1677
|
-
discountLabel:
|
|
1704
|
+
discountLabel: activePromoCode ? `Promo: ${activePromoCode}` : undefined,
|
|
1678
1705
|
isDepositPayment: !!depositInfo,
|
|
1679
1706
|
balanceChargeDaysBefore: depositInfo ? (privateShuttleConfig?.balanceChargeDaysBefore ?? 7) : undefined,
|
|
1680
1707
|
});
|
|
@@ -2528,8 +2555,39 @@ export function PrivateShuttleBookingFlow({
|
|
|
2528
2555
|
total={depositInfo ? depositInfo.depositAmount : totalPrice}
|
|
2529
2556
|
currency={currency}
|
|
2530
2557
|
locale={locale as 'en' | 'fr'}
|
|
2531
|
-
taxAmount={
|
|
2558
|
+
taxAmount={effectiveTaxAmount}
|
|
2532
2559
|
taxRate={taxRate}
|
|
2560
|
+
discountAmount={effectivePromoDiscountAmount}
|
|
2561
|
+
discountLabel={activePromoCode ? `Promo: ${activePromoCode}` : undefined}
|
|
2562
|
+
extraBetweenTaxAndTotal={
|
|
2563
|
+
isAdmin ? (
|
|
2564
|
+
<PromoCodeInput
|
|
2565
|
+
promoCodeInput={promoCodeInput}
|
|
2566
|
+
appliedPromoCode={appliedPromoCode}
|
|
2567
|
+
promoCodeError={promoCodeError}
|
|
2568
|
+
promoCodeValidating={promoCodeValidating}
|
|
2569
|
+
promoDiscountAmount={promoDiscountAmount}
|
|
2570
|
+
currency={currency}
|
|
2571
|
+
locale={locale}
|
|
2572
|
+
t={t}
|
|
2573
|
+
onInputChange={(value) => {
|
|
2574
|
+
setPromoCodeInput(value);
|
|
2575
|
+
setPromoCodeError('');
|
|
2576
|
+
}}
|
|
2577
|
+
onApply={handleApplyPromo}
|
|
2578
|
+
onRemove={() => {
|
|
2579
|
+
lastValidatedInputRef.current = null;
|
|
2580
|
+
setAppliedPromoCode(null);
|
|
2581
|
+
setPromoCodeInput('');
|
|
2582
|
+
setPromoCodeError('');
|
|
2583
|
+
setPromoDiscountAmount(0);
|
|
2584
|
+
setIsGiftCard(false);
|
|
2585
|
+
setIsVoucher(false);
|
|
2586
|
+
fetchedRangesRef.current = [];
|
|
2587
|
+
}}
|
|
2588
|
+
/>
|
|
2589
|
+
) : null
|
|
2590
|
+
}
|
|
2533
2591
|
size="sm"
|
|
2534
2592
|
t={t}
|
|
2535
2593
|
depositMode={
|