kupos-ui-components-lib 10.4.30 → 10.4.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/KuposUIComponent.d.ts +1 -1
- package/dist/KuposUIComponent.js +3 -0
- package/dist/assets/images/discount/blue.png +0 -0
- package/dist/assets/images/discount/cash.png +0 -0
- package/dist/assets/images/discount/first.png +0 -0
- package/dist/assets/images/discount/green.png +0 -0
- package/dist/assets/images/discount/instant.png +0 -0
- package/dist/assets/images/discount/last.png +0 -0
- package/dist/assets/images/discount/promo.png +0 -0
- package/dist/assets/images/discount/round.png +0 -0
- package/dist/assets/images/discount/seat.png +0 -0
- package/dist/assets/images/discount/yellow.png +0 -0
- package/dist/assets/images/index.d.ts +12 -0
- package/dist/assets/images/index.js +12 -0
- package/dist/assets/images/index.ts +14 -0
- package/dist/components/DiscountBanners/DiscountBannerDesktop.d.ts +11 -0
- package/dist/components/DiscountBanners/DiscountBannerDesktop.js +133 -0
- package/dist/components/DiscountBanners/DiscountBannerMobile.d.ts +11 -0
- package/dist/components/DiscountBanners/DiscountBannerMobile.js +132 -0
- package/dist/components/DiscountBanners/ResponsiveDiscountBanner.d.ts +3 -0
- package/dist/components/DiscountBanners/ResponsiveDiscountBanner.js +10 -0
- package/dist/components/DiscountBanners/index.d.ts +5 -0
- package/dist/components/DiscountBanners/index.js +4 -0
- package/dist/components/DiscountBanners/types.d.ts +51 -0
- package/dist/components/DiscountBanners/types.js +1 -0
- package/dist/components/ServiceItem/ServiceItemMobile.js +0 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +6 -1
- package/dist/styles.css +89 -0
- package/dist/ui/DiscountBanners/DiscountBanners.d.ts +4 -0
- package/dist/ui/DiscountBanners/DiscountBanners.js +114 -0
- package/dist/ui/DiscountBanners/defaultBackgrounds.d.ts +12 -0
- package/dist/ui/DiscountBanners/defaultBackgrounds.js +38 -0
- package/dist/ui/DiscountBanners/discountUtils.d.ts +3 -0
- package/dist/ui/DiscountBanners/discountUtils.js +126 -0
- package/dist/ui/DiscountBanners/index.d.ts +5 -0
- package/dist/ui/DiscountBanners/index.js +3 -0
- package/dist/ui/DiscountBanners/types.d.ts +49 -0
- package/dist/ui/DiscountBanners/types.js +1 -0
- package/dist/ui/OfferBanner.js +1 -1
- package/package.json +21 -6
- package/src/KuposUIComponent.tsx +13 -1
- package/src/assets/images/discount/blue.png +0 -0
- package/src/assets/images/discount/cash.png +0 -0
- package/src/assets/images/discount/first.png +0 -0
- package/src/assets/images/discount/green.png +0 -0
- package/src/assets/images/discount/instant.png +0 -0
- package/src/assets/images/discount/last.png +0 -0
- package/src/assets/images/discount/promo.png +0 -0
- package/src/assets/images/discount/round.png +0 -0
- package/src/assets/images/discount/seat.png +0 -0
- package/src/assets/images/discount/yellow.png +0 -0
- package/src/assets/images/index.ts +14 -0
- package/src/components/DiscountBanners/DiscountBannerDesktop.tsx +240 -0
- package/src/components/DiscountBanners/DiscountBannerMobile.tsx +234 -0
- package/src/components/DiscountBanners/ResponsiveDiscountBanner.tsx +16 -0
- package/src/components/DiscountBanners/index.ts +16 -0
- package/src/components/DiscountBanners/types.ts +55 -0
- package/src/components/ServiceItem/ServiceItemMobile.tsx +0 -1
- package/src/index.ts +34 -3
- package/src/types/images.d.ts +12 -0
- package/src/ui/DiscountBanners/DiscountBanners.tsx +215 -0
- package/src/ui/DiscountBanners/defaultBackgrounds.ts +42 -0
- package/src/ui/DiscountBanners/discountUtils.ts +166 -0
- package/src/ui/DiscountBanners/index.ts +14 -0
- package/src/ui/DiscountBanners/types.ts +53 -0
- package/src/ui/OfferBanner.tsx +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
interface KuposUIComponentProps {
|
|
3
|
-
typeOfComponent: "serviceitem" | "paymentsidebar" | "servicelist" | "filterbar" | "survey" | "cuponerafilterbar";
|
|
3
|
+
typeOfComponent: "serviceitem" | "paymentsidebar" | "servicelist" | "filterbar" | "survey" | "cuponerafilterbar" | "discountbanners";
|
|
4
4
|
variant?: "mobile" | "desktop";
|
|
5
5
|
serviceItem?: any;
|
|
6
6
|
onBookButtonPress?: () => void;
|
package/dist/KuposUIComponent.js
CHANGED
|
@@ -16,6 +16,7 @@ import { ResponsiveServiceList } from "./components/ServiceList";
|
|
|
16
16
|
import { ResponsiveFilterBar } from "./components/FilterBar";
|
|
17
17
|
import ResponsiveCuponeraFilterBar from "./components/CuponeraFilterBar/ResponsiveCuponeraFilterBar";
|
|
18
18
|
import { ResponsiveSurvey } from "./components/Survey";
|
|
19
|
+
import { ResponsiveDiscountBanner, } from "./components/DiscountBanners";
|
|
19
20
|
// Using imported ResponsivePaymentSideBar component instead
|
|
20
21
|
export default function KuposUIComponent(props) {
|
|
21
22
|
const { typeOfComponent } = props, restProps = __rest(props, ["typeOfComponent"]);
|
|
@@ -32,6 +33,8 @@ export default function KuposUIComponent(props) {
|
|
|
32
33
|
return (React.createElement(ResponsiveCuponeraFilterBar, Object.assign({}, restProps)));
|
|
33
34
|
case "survey":
|
|
34
35
|
return React.createElement(ResponsiveSurvey, Object.assign({}, restProps));
|
|
36
|
+
case "discountbanners":
|
|
37
|
+
return (React.createElement(ResponsiveDiscountBanner, Object.assign({}, restProps)));
|
|
35
38
|
default:
|
|
36
39
|
return (React.createElement("div", { className: "error-message" },
|
|
37
40
|
"Invalid component type: ",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -30,3 +30,15 @@ export declare const amenities: {
|
|
|
30
30
|
"wifi-white": any;
|
|
31
31
|
"amenity-cortina": any;
|
|
32
32
|
};
|
|
33
|
+
export declare const backgroundImages: {
|
|
34
|
+
"discount-banner-1": any;
|
|
35
|
+
"discount-banner-2": any;
|
|
36
|
+
"discount-banner-3": any;
|
|
37
|
+
"discount-last-minute": any;
|
|
38
|
+
"discount-first-time": any;
|
|
39
|
+
"discount-cashback": any;
|
|
40
|
+
"discount-round-trip": any;
|
|
41
|
+
"discount-promo-code": any;
|
|
42
|
+
"discount-seat-level": any;
|
|
43
|
+
"discount-instant": any;
|
|
44
|
+
};
|
|
@@ -33,3 +33,15 @@ export const amenities = {
|
|
|
33
33
|
// PNG
|
|
34
34
|
"amenity-cortina": require("./amenities/amenity-cortina.png"),
|
|
35
35
|
};
|
|
36
|
+
export const backgroundImages = {
|
|
37
|
+
"discount-banner-1": require("./discount/green.png"),
|
|
38
|
+
"discount-banner-2": require("./discount/yellow.png"),
|
|
39
|
+
"discount-banner-3": require("./discount/blue.png"),
|
|
40
|
+
"discount-last-minute": require("./discount/last.png"),
|
|
41
|
+
"discount-first-time": require("./discount/first.png"),
|
|
42
|
+
"discount-cashback": require("./discount/cash.png"),
|
|
43
|
+
"discount-round-trip": require("./discount/round.png"),
|
|
44
|
+
"discount-promo-code": require("./discount/promo.png"),
|
|
45
|
+
"discount-seat-level": require("./discount/seat.png"),
|
|
46
|
+
"discount-instant": require("./discount/instant.png"),
|
|
47
|
+
};
|
|
@@ -33,3 +33,17 @@ export const amenities = {
|
|
|
33
33
|
// PNG
|
|
34
34
|
"amenity-cortina": require("./amenities/amenity-cortina.png"),
|
|
35
35
|
};
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
export const backgroundImages = {
|
|
39
|
+
"discount-banner-1": require("./discount/green.png"),
|
|
40
|
+
"discount-banner-2": require("./discount/yellow.png"),
|
|
41
|
+
"discount-banner-3": require("./discount/blue.png"),
|
|
42
|
+
"discount-last-minute": require("./discount/last.png"),
|
|
43
|
+
"discount-first-time": require("./discount/first.png"),
|
|
44
|
+
"discount-cashback": require("./discount/cash.png"),
|
|
45
|
+
"discount-round-trip": require("./discount/round.png"),
|
|
46
|
+
"discount-promo-code": require("./discount/promo.png"),
|
|
47
|
+
"discount-seat-level": require("./discount/seat.png"),
|
|
48
|
+
"discount-instant": require("./discount/instant.png"),
|
|
49
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { DiscountBannerCard, DiscountBannersProps } from "./types";
|
|
3
|
+
interface DiscountBannersDesktopState {
|
|
4
|
+
internalSelectedKey: string | null;
|
|
5
|
+
}
|
|
6
|
+
declare class DiscountBannersDesktop extends React.Component<DiscountBannersProps, DiscountBannersDesktopState> {
|
|
7
|
+
constructor(props: DiscountBannersProps);
|
|
8
|
+
handleCardClick(card: DiscountBannerCard): void;
|
|
9
|
+
render(): React.JSX.Element;
|
|
10
|
+
}
|
|
11
|
+
export default DiscountBannersDesktop;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { CAMPAIGN_ART, DEFAULT_BACKGROUND_IMAGES, toImageUrl, } from "../../ui/DiscountBanners/defaultBackgrounds";
|
|
4
|
+
import { deriveDiscountCards } from "../../ui/DiscountBanners";
|
|
5
|
+
const DEFAULT_LABEL = "Oferta especial";
|
|
6
|
+
const DEFAULT_ACCENT_PALETTE = [
|
|
7
|
+
"#107E23",
|
|
8
|
+
"#FFC000",
|
|
9
|
+
"#0069D1", // blue (descuentos especiales)
|
|
10
|
+
];
|
|
11
|
+
const SIZE_CLASSES = {
|
|
12
|
+
default: {
|
|
13
|
+
card: "w-[200px] h-[80px] pt-[8px] pb-0 pl-[10px] pr-[8px]",
|
|
14
|
+
chip: "w-[81px] h-[17px] text-[9px] leading-[17px]",
|
|
15
|
+
column: "max-w-[116px] mt-[3px]",
|
|
16
|
+
discount: "text-[15px] leading-[17px]",
|
|
17
|
+
subtitle: "text-[12px] leading-[14px] mt-[1px]",
|
|
18
|
+
flameBadge: "text-[18px] leading-[16px]",
|
|
19
|
+
flamePercent: "text-[10px]",
|
|
20
|
+
},
|
|
21
|
+
compact: {
|
|
22
|
+
card: "w-[170px] h-[68px] pt-[7px] pb-0 pl-[8px] pr-[7px]",
|
|
23
|
+
chip: "w-[69px] h-[15px] text-[8px] leading-[15px]",
|
|
24
|
+
column: "max-w-[99px] mt-[2px]",
|
|
25
|
+
discount: "text-[13px] leading-[15px]",
|
|
26
|
+
subtitle: "text-[10.5px] leading-[12px] mt-[1px]",
|
|
27
|
+
flameBadge: "text-[13.5px] leading-[13.5px]",
|
|
28
|
+
flamePercent: "text-[8px]",
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
const FLAME_CENTER = { left: "76.8%", top: "56.4%" };
|
|
32
|
+
const REMATE_KEY = "remate";
|
|
33
|
+
function isRemateCard(card) {
|
|
34
|
+
return card.isWowDeal || card.key === REMATE_KEY;
|
|
35
|
+
}
|
|
36
|
+
const FALLBACK_ART = [
|
|
37
|
+
{ image: DEFAULT_BACKGROUND_IMAGES[1], accent: "#FFC000" },
|
|
38
|
+
{ image: DEFAULT_BACKGROUND_IMAGES[2], accent: "#0069D1" },
|
|
39
|
+
];
|
|
40
|
+
const REMATE_ART = {
|
|
41
|
+
image: DEFAULT_BACKGROUND_IMAGES[0],
|
|
42
|
+
accent: "#107E23",
|
|
43
|
+
};
|
|
44
|
+
function resolveArt(cards) {
|
|
45
|
+
let ordinal = 0;
|
|
46
|
+
return cards.map((card) => {
|
|
47
|
+
if (isRemateCard(card))
|
|
48
|
+
return REMATE_ART;
|
|
49
|
+
const campaignArt = card.campaignType
|
|
50
|
+
? CAMPAIGN_ART[card.campaignType]
|
|
51
|
+
: undefined;
|
|
52
|
+
if (campaignArt)
|
|
53
|
+
return campaignArt;
|
|
54
|
+
const art = FALLBACK_ART[ordinal % FALLBACK_ART.length];
|
|
55
|
+
ordinal += 1;
|
|
56
|
+
return art;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
class DiscountBannersDesktop extends React.Component {
|
|
60
|
+
constructor(props) {
|
|
61
|
+
var _a;
|
|
62
|
+
super(props);
|
|
63
|
+
this.state = {
|
|
64
|
+
internalSelectedKey: (_a = props.defaultSelectedKey) !== null && _a !== void 0 ? _a : null,
|
|
65
|
+
};
|
|
66
|
+
this.handleCardClick = this.handleCardClick.bind(this);
|
|
67
|
+
}
|
|
68
|
+
handleCardClick(card) {
|
|
69
|
+
var _a, _b, _c, _d;
|
|
70
|
+
const { selectedKey, onDiscountSelect } = this.props;
|
|
71
|
+
const isControlled = selectedKey !== undefined;
|
|
72
|
+
const activeKey = isControlled
|
|
73
|
+
? selectedKey
|
|
74
|
+
: this.state.internalSelectedKey;
|
|
75
|
+
const nextKey = activeKey === card.key ? null : card.key;
|
|
76
|
+
if (!isControlled) {
|
|
77
|
+
this.setState({ internalSelectedKey: nextKey });
|
|
78
|
+
}
|
|
79
|
+
const cards = deriveDiscountCards((_a = this.props.services) !== null && _a !== void 0 ? _a : [], this.props.wowDealData, (_b = this.props.currencySign) !== null && _b !== void 0 ? _b : "$");
|
|
80
|
+
const selectedCard = nextKey
|
|
81
|
+
? ((_c = cards.find((c) => c.key === nextKey)) !== null && _c !== void 0 ? _c : null)
|
|
82
|
+
: null;
|
|
83
|
+
onDiscountSelect === null || onDiscountSelect === void 0 ? void 0 : onDiscountSelect(selectedCard, (_d = selectedCard === null || selectedCard === void 0 ? void 0 : selectedCard.matchedServices) !== null && _d !== void 0 ? _d : []);
|
|
84
|
+
}
|
|
85
|
+
render() {
|
|
86
|
+
const { services = [], wowDealData, backgroundImages = [], artIncludesChipPill, accentColors = [], label = DEFAULT_LABEL, currencySign = "$", size = "default", selectedKey, className = "", style, } = this.props;
|
|
87
|
+
// Compute cards directly — no useMemo
|
|
88
|
+
const cards = deriveDiscountCards(services, wowDealData, currencySign);
|
|
89
|
+
if (!cards.length)
|
|
90
|
+
return null;
|
|
91
|
+
const isControlled = selectedKey !== undefined;
|
|
92
|
+
const activeKey = isControlled
|
|
93
|
+
? selectedKey
|
|
94
|
+
: this.state.internalSelectedKey;
|
|
95
|
+
const usingDefaultArt = !backgroundImages.length;
|
|
96
|
+
const defaultArt = resolveArt(cards);
|
|
97
|
+
const chipPillInArt = artIncludesChipPill !== null && artIncludesChipPill !== void 0 ? artIncludesChipPill : usingDefaultArt;
|
|
98
|
+
const sizeClasses = SIZE_CLASSES[size !== null && size !== void 0 ? size : "default"];
|
|
99
|
+
return (React.createElement("div", { className: `kupos-discount-banners flex items-stretch gap-[10px] overflow-x-auto [scrollbar-width:none] ${className}`, style: style }, cards.map((card, index) => {
|
|
100
|
+
const isActive = activeKey === card.key;
|
|
101
|
+
const isDimmed = activeKey != null && !isActive;
|
|
102
|
+
const backgroundImage = usingDefaultArt
|
|
103
|
+
? defaultArt[index].image
|
|
104
|
+
: toImageUrl(backgroundImages[index % backgroundImages.length]);
|
|
105
|
+
const accentColor = accentColors.length
|
|
106
|
+
? accentColors[index % accentColors.length]
|
|
107
|
+
: usingDefaultArt
|
|
108
|
+
? defaultArt[index].accent
|
|
109
|
+
: DEFAULT_ACCENT_PALETTE[index % DEFAULT_ACCENT_PALETTE.length];
|
|
110
|
+
const isFlameArt = backgroundImage === DEFAULT_BACKGROUND_IMAGES[0];
|
|
111
|
+
const showFlamePercent = isRemateCard(card) &&
|
|
112
|
+
isFlameArt &&
|
|
113
|
+
card.discountType === "percentage" &&
|
|
114
|
+
card.amount > 0;
|
|
115
|
+
return (React.createElement("button", { key: card.key, type: "button", "aria-pressed": isActive, onClick: () => this.handleCardClick(card), className: `relative flex-shrink-0 flex flex-col items-start text-left border-none bg-transparent cursor-pointer bg-no-repeat transition-opacity duration-200 ease-in-out ${sizeClasses.card} ${isDimmed ? "opacity-[0.65]" : "opacity-100"}`, style: {
|
|
116
|
+
backgroundImage: backgroundImage
|
|
117
|
+
? `url(${backgroundImage})`
|
|
118
|
+
: undefined,
|
|
119
|
+
backgroundSize: "100% 100%",
|
|
120
|
+
} },
|
|
121
|
+
React.createElement("span", { className: `bold-text flex-shrink-0 rounded-full text-center text-[#464647] overflow-hidden whitespace-nowrap ${sizeClasses.chip}`, style: chipPillInArt
|
|
122
|
+
? undefined
|
|
123
|
+
: { backgroundColor: "rgba(255,255,255,0.55)" } }, label),
|
|
124
|
+
showFlamePercent && (React.createElement("span", { className: `bold-text absolute text-[#ffffff] text-center pointer-events-none ${sizeClasses.flameBadge}`, style: Object.assign(Object.assign({}, FLAME_CENTER), { transform: "translate(-50%, -50%)", textShadow: "0 1px 2px rgba(0,0,0,0.28)", fontWeight: 900, whiteSpace: "nowrap" }) },
|
|
125
|
+
card.amount,
|
|
126
|
+
React.createElement("span", { className: sizeClasses.flamePercent, style: { fontWeight: 700 } }, "%"))),
|
|
127
|
+
React.createElement("span", { className: `flex flex-col ${sizeClasses.column}` },
|
|
128
|
+
React.createElement("span", { className: `bold-text text-[#464647] ${sizeClasses.discount}` }, card.discountLabel),
|
|
129
|
+
React.createElement("span", { className: `bold-text ${sizeClasses.subtitle}`, style: { color: accentColor } }, card.subtitle))));
|
|
130
|
+
})));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
export default DiscountBannersDesktop;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { DiscountBannerCard, DiscountBannersProps } from "./types";
|
|
3
|
+
interface DiscountBannersMobileState {
|
|
4
|
+
internalSelectedKey: string | null;
|
|
5
|
+
}
|
|
6
|
+
declare class DiscountBannersMobile extends React.Component<DiscountBannersProps, DiscountBannersMobileState> {
|
|
7
|
+
constructor(props: DiscountBannersProps);
|
|
8
|
+
handleCardClick(card: DiscountBannerCard): void;
|
|
9
|
+
render(): React.JSX.Element;
|
|
10
|
+
}
|
|
11
|
+
export default DiscountBannersMobile;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { CAMPAIGN_ART, DEFAULT_BACKGROUND_IMAGES, toImageUrl, } from "../../ui/DiscountBanners/defaultBackgrounds";
|
|
4
|
+
import { deriveDiscountCards } from "../../ui/DiscountBanners";
|
|
5
|
+
const DEFAULT_LABEL = "Oferta especial";
|
|
6
|
+
const DEFAULT_ACCENT_PALETTE = [
|
|
7
|
+
"#107E23",
|
|
8
|
+
"#FFC000",
|
|
9
|
+
"#0069D1", // blue (descuentos especiales)
|
|
10
|
+
];
|
|
11
|
+
const SIZE_CLASSES = {
|
|
12
|
+
default: {
|
|
13
|
+
card: "w-[200px] h-[80px] pt-[8px] pb-0 pl-[10px] pr-[8px]",
|
|
14
|
+
chip: "w-[81px] h-[17px] text-[9px] leading-[17px]",
|
|
15
|
+
column: "max-w-[116px] mt-[3px]",
|
|
16
|
+
discount: "text-[15px] leading-[17px]",
|
|
17
|
+
subtitle: "text-[12px] leading-[14px] mt-[1px]",
|
|
18
|
+
flameBadge: "text-[18px] leading-[16px]",
|
|
19
|
+
flamePercent: "text-[10px]",
|
|
20
|
+
},
|
|
21
|
+
compact: {
|
|
22
|
+
card: "w-[170px] h-[68px] pt-[7px] pb-0 pl-[8px] pr-[7px]",
|
|
23
|
+
chip: "w-[69px] h-[15px] text-[8px] leading-[15px]",
|
|
24
|
+
column: "max-w-[99px] mt-[2px]",
|
|
25
|
+
discount: "text-[13px] leading-[15px]",
|
|
26
|
+
subtitle: "text-[10.5px] leading-[12px] mt-[1px]",
|
|
27
|
+
flameBadge: "text-[13.5px] leading-[13.5px]",
|
|
28
|
+
flamePercent: "text-[8px]",
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
const FLAME_CENTER = { left: "76.8%", top: "56.4%" };
|
|
32
|
+
const REMATE_KEY = "remate";
|
|
33
|
+
function isRemateCard(card) {
|
|
34
|
+
return card.isWowDeal || card.key === REMATE_KEY;
|
|
35
|
+
}
|
|
36
|
+
const FALLBACK_ART = [
|
|
37
|
+
{ image: DEFAULT_BACKGROUND_IMAGES[1], accent: "#FFC000" },
|
|
38
|
+
{ image: DEFAULT_BACKGROUND_IMAGES[2], accent: "#0069D1" },
|
|
39
|
+
];
|
|
40
|
+
const REMATE_ART = {
|
|
41
|
+
image: DEFAULT_BACKGROUND_IMAGES[0],
|
|
42
|
+
accent: "#107E23",
|
|
43
|
+
};
|
|
44
|
+
function resolveArt(cards) {
|
|
45
|
+
let ordinal = 0;
|
|
46
|
+
return cards.map((card) => {
|
|
47
|
+
if (isRemateCard(card))
|
|
48
|
+
return REMATE_ART;
|
|
49
|
+
const campaignArt = card.campaignType
|
|
50
|
+
? CAMPAIGN_ART[card.campaignType]
|
|
51
|
+
: undefined;
|
|
52
|
+
if (campaignArt)
|
|
53
|
+
return campaignArt;
|
|
54
|
+
const art = FALLBACK_ART[ordinal % FALLBACK_ART.length];
|
|
55
|
+
ordinal += 1;
|
|
56
|
+
return art;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
class DiscountBannersMobile extends React.Component {
|
|
60
|
+
constructor(props) {
|
|
61
|
+
var _a;
|
|
62
|
+
super(props);
|
|
63
|
+
this.state = {
|
|
64
|
+
internalSelectedKey: (_a = props.defaultSelectedKey) !== null && _a !== void 0 ? _a : null,
|
|
65
|
+
};
|
|
66
|
+
this.handleCardClick = this.handleCardClick.bind(this);
|
|
67
|
+
}
|
|
68
|
+
handleCardClick(card) {
|
|
69
|
+
var _a, _b, _c, _d;
|
|
70
|
+
const { selectedKey, onDiscountSelect } = this.props;
|
|
71
|
+
const isControlled = selectedKey !== undefined;
|
|
72
|
+
const activeKey = isControlled
|
|
73
|
+
? selectedKey
|
|
74
|
+
: this.state.internalSelectedKey;
|
|
75
|
+
const nextKey = activeKey === card.key ? null : card.key;
|
|
76
|
+
if (!isControlled) {
|
|
77
|
+
this.setState({ internalSelectedKey: nextKey });
|
|
78
|
+
}
|
|
79
|
+
const cards = deriveDiscountCards((_a = this.props.services) !== null && _a !== void 0 ? _a : [], this.props.wowDealData, (_b = this.props.currencySign) !== null && _b !== void 0 ? _b : "$");
|
|
80
|
+
const selectedCard = nextKey
|
|
81
|
+
? ((_c = cards.find((c) => c.key === nextKey)) !== null && _c !== void 0 ? _c : null)
|
|
82
|
+
: null;
|
|
83
|
+
onDiscountSelect === null || onDiscountSelect === void 0 ? void 0 : onDiscountSelect(selectedCard, (_d = selectedCard === null || selectedCard === void 0 ? void 0 : selectedCard.matchedServices) !== null && _d !== void 0 ? _d : []);
|
|
84
|
+
}
|
|
85
|
+
render() {
|
|
86
|
+
const { services = [], wowDealData, backgroundImages = [], artIncludesChipPill, accentColors = [], label = DEFAULT_LABEL, currencySign = "$", size = "default", selectedKey, className = "", style, } = this.props;
|
|
87
|
+
const cards = deriveDiscountCards(services, wowDealData, currencySign);
|
|
88
|
+
if (!cards.length)
|
|
89
|
+
return null;
|
|
90
|
+
const isControlled = selectedKey !== undefined;
|
|
91
|
+
const activeKey = isControlled
|
|
92
|
+
? selectedKey
|
|
93
|
+
: this.state.internalSelectedKey;
|
|
94
|
+
const usingDefaultArt = !backgroundImages.length;
|
|
95
|
+
const defaultArt = resolveArt(cards);
|
|
96
|
+
const chipPillInArt = artIncludesChipPill !== null && artIncludesChipPill !== void 0 ? artIncludesChipPill : usingDefaultArt;
|
|
97
|
+
const sizeClasses = SIZE_CLASSES[size !== null && size !== void 0 ? size : "default"];
|
|
98
|
+
return (React.createElement("div", { className: `kupos-discount-banners flex items-stretch gap-[10px] overflow-x-auto [scrollbar-width:none] ${className}`, style: style }, cards.map((card, index) => {
|
|
99
|
+
const isActive = activeKey === card.key;
|
|
100
|
+
const isDimmed = activeKey != null && !isActive;
|
|
101
|
+
const backgroundImage = usingDefaultArt
|
|
102
|
+
? defaultArt[index].image
|
|
103
|
+
: toImageUrl(backgroundImages[index % backgroundImages.length]);
|
|
104
|
+
const accentColor = accentColors.length
|
|
105
|
+
? accentColors[index % accentColors.length]
|
|
106
|
+
: usingDefaultArt
|
|
107
|
+
? defaultArt[index].accent
|
|
108
|
+
: DEFAULT_ACCENT_PALETTE[index % DEFAULT_ACCENT_PALETTE.length];
|
|
109
|
+
const isFlameArt = backgroundImage === DEFAULT_BACKGROUND_IMAGES[0];
|
|
110
|
+
const showFlamePercent = isRemateCard(card) &&
|
|
111
|
+
isFlameArt &&
|
|
112
|
+
card.discountType === "percentage" &&
|
|
113
|
+
card.amount > 0;
|
|
114
|
+
return (React.createElement("button", { key: card.key, type: "button", "aria-pressed": isActive, onClick: () => this.handleCardClick(card), className: `relative flex-shrink-0 flex flex-col items-start text-left border-none bg-transparent cursor-pointer bg-no-repeat transition-opacity duration-200 ease-in-out ${sizeClasses.card} ${isDimmed ? "opacity-[0.65]" : "opacity-100"}`, style: {
|
|
115
|
+
backgroundImage: backgroundImage
|
|
116
|
+
? `url(${backgroundImage})`
|
|
117
|
+
: undefined,
|
|
118
|
+
backgroundSize: "100% 100%",
|
|
119
|
+
} },
|
|
120
|
+
React.createElement("span", { className: `bold-text flex-shrink-0 rounded-full text-center text-[#464647] overflow-hidden whitespace-nowrap ${sizeClasses.chip}`, style: chipPillInArt
|
|
121
|
+
? undefined
|
|
122
|
+
: { backgroundColor: "rgba(255,255,255,0.55)" } }, label),
|
|
123
|
+
showFlamePercent && (React.createElement("span", { className: `bold-text absolute text-[#ffffff] text-center pointer-events-none ${sizeClasses.flameBadge}`, style: Object.assign(Object.assign({}, FLAME_CENTER), { transform: "translate(-50%, -50%)", textShadow: "0 1px 2px rgba(0,0,0,0.28)", fontWeight: 900, whiteSpace: "nowrap" }) },
|
|
124
|
+
card.amount,
|
|
125
|
+
React.createElement("span", { className: sizeClasses.flamePercent, style: { fontWeight: 700 } }, "%"))),
|
|
126
|
+
React.createElement("span", { className: `flex flex-col ${sizeClasses.column}` },
|
|
127
|
+
React.createElement("span", { className: `bold-text text-[#464647] ${sizeClasses.discount}` }, card.discountLabel),
|
|
128
|
+
React.createElement("span", { className: `bold-text ${sizeClasses.subtitle}`, style: { color: accentColor } }, card.subtitle))));
|
|
129
|
+
})));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export default DiscountBannersMobile;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import DiscountBannersMobile from "./DiscountBannerMobile";
|
|
3
|
+
import DiscountBannersDesktop from "./DiscountBannerDesktop";
|
|
4
|
+
export default function ResponsiveDiscountBanner(props) {
|
|
5
|
+
const { variant } = props;
|
|
6
|
+
if (variant === "mobile") {
|
|
7
|
+
return (React.createElement(DiscountBannersMobile, Object.assign({}, props)));
|
|
8
|
+
}
|
|
9
|
+
return React.createElement(DiscountBannersDesktop, Object.assign({}, props));
|
|
10
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import DiscountBannerDesktop from "./DiscountBannerDesktop";
|
|
2
|
+
import DiscountBannerMobile from "./DiscountBannerMobile";
|
|
3
|
+
import ResponsiveDiscountBanner from "./ResponsiveDiscountBanner";
|
|
4
|
+
export { DiscountBannerDesktop, DiscountBannerMobile, ResponsiveDiscountBanner, };
|
|
5
|
+
export type { DiscountBannerCard, DiscountBannerServiceItem, DiscountBannersProps, WowDealData, } from "./types";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import DiscountBannerDesktop from "./DiscountBannerDesktop";
|
|
2
|
+
import DiscountBannerMobile from "./DiscountBannerMobile";
|
|
3
|
+
import ResponsiveDiscountBanner from "./ResponsiveDiscountBanner";
|
|
4
|
+
export { DiscountBannerDesktop, DiscountBannerMobile, ResponsiveDiscountBanner, };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
import { ImageRef } from "../../ui/DiscountBanners";
|
|
3
|
+
export interface DiscountBannerServiceItem {
|
|
4
|
+
id?: string | number;
|
|
5
|
+
offer_text?: string;
|
|
6
|
+
is_dp_enabled?: boolean;
|
|
7
|
+
dp_discount_percents?: Record<string, number>;
|
|
8
|
+
dp_discounted_seats?: string[];
|
|
9
|
+
discount_type?: string;
|
|
10
|
+
discount_value?: number;
|
|
11
|
+
max_discount?: number;
|
|
12
|
+
discounts?: Array<{
|
|
13
|
+
new_ui_enabled?: boolean;
|
|
14
|
+
campaign_type?: string;
|
|
15
|
+
}>;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
}
|
|
18
|
+
export interface WowDealData {
|
|
19
|
+
savings_percent?: number;
|
|
20
|
+
services?: any[];
|
|
21
|
+
final_price?: number;
|
|
22
|
+
original_price?: number;
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
}
|
|
25
|
+
export interface DiscountBannerCard {
|
|
26
|
+
key: string;
|
|
27
|
+
subtitle: string;
|
|
28
|
+
campaignType?: string;
|
|
29
|
+
discountType: "percentage" | "fixed";
|
|
30
|
+
amount: number;
|
|
31
|
+
discountLabel: string;
|
|
32
|
+
matchedServices: DiscountBannerServiceItem[];
|
|
33
|
+
isWowDeal: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface DiscountBannersProps {
|
|
36
|
+
services?: DiscountBannerServiceItem[];
|
|
37
|
+
wowDealData?: WowDealData;
|
|
38
|
+
backgroundImages?: ImageRef[];
|
|
39
|
+
artIncludesChipPill?: boolean;
|
|
40
|
+
accentColors?: string[];
|
|
41
|
+
label?: string;
|
|
42
|
+
currencySign?: string;
|
|
43
|
+
size?: "default" | "compact";
|
|
44
|
+
selectedKey?: string | null;
|
|
45
|
+
defaultSelectedKey?: string | null;
|
|
46
|
+
onDiscountSelect?: (card: DiscountBannerCard | null, filteredServices: DiscountBannerServiceItem[]) => void;
|
|
47
|
+
className?: string;
|
|
48
|
+
style?: CSSProperties;
|
|
49
|
+
variant?: "mobile" | "desktop";
|
|
50
|
+
typeOfComponent?: string;
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -21,7 +21,6 @@ const exceptions = [
|
|
|
21
21
|
];
|
|
22
22
|
function ServiceItemMobile({ serviceItem, onBookButtonPress, colors, busStage, orignLabel, destinationLabel, amenitiesData, setShowDropdown, showDropdown, isExpanded, setIsExpanded, setAmenetiesAtomValue, isCiva, currencySign, isPeru, showRating, showLastSeats, removeDuplicateSeats, isLinatal, viewersConfig, operatorLabel, isTrain, isFeatureDropDownExpand, setIsFeatureDropDownExpand, ticketQuantity, onIncreaseTicketQuantity, onDecreaseTicketQuantity, cityOrigin, cityDestination, isNewUi, onRemateUiButtonClick, selectedTimeSlot, onTimeSlotChange, isTimeDropdownOpen, onTimeDropdownToggle, wowDealData, isFlores, isAllinBus, isPeruSite, priority_stage_ids, }) {
|
|
23
23
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
24
|
-
console.log("🚀 ~ ServiceItemMobile ~ serviceItem:", serviceItem);
|
|
25
24
|
const isItemExpanded = serviceItem.id === isExpanded;
|
|
26
25
|
const isPetSeat = (Object.keys(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.pet_seat_info) || []).length > 0;
|
|
27
26
|
const isNewUiEnabled = ((_b = (_a = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discounts) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.new_ui_enabled) === true;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,10 +6,11 @@ import KuposUIComponent from "./KuposUIComponent";
|
|
|
6
6
|
import { PaymentSideBarDesktop, PaymentSideBarMobile, ResponsivePaymentSideBar } from "./components/PaymentSideBar";
|
|
7
7
|
import { ServiceListDesktop, ServiceListMobile, ResponsiveServiceList } from "./components/ServiceList";
|
|
8
8
|
import { FilterBarDesktop, FilterBarMobile, ResponsiveFilterBar } from "./components/FilterBar";
|
|
9
|
+
import { DiscountBannerDesktop, DiscountBannerMobile, ResponsiveDiscountBanner } from "./components/DiscountBanners";
|
|
9
10
|
import { FilterSortBarMobile } from "./components/FilterSortBar";
|
|
10
11
|
import { SurveyDesktop, SurveyMobile, ResponsiveSurvey } from "./components/Survey";
|
|
11
12
|
import { Modal, ModalHeader } from "./ui/Modal";
|
|
12
|
-
export { ServiceItemDesktop, ServiceItemMobile, ResponsiveServiceItem, ServiceItemPBMobile, KuposUIComponent, PaymentSideBarDesktop, PaymentSideBarMobile, ResponsivePaymentSideBar, ServiceListDesktop, ServiceListMobile, ResponsiveServiceList, FilterBarDesktop, FilterBarMobile, ResponsiveFilterBar, FilterSortBarMobile, SurveyDesktop, SurveyMobile, ResponsiveSurvey, Modal, ModalHeader, };
|
|
13
|
+
export { ServiceItemDesktop, ServiceItemMobile, ResponsiveServiceItem, ServiceItemPBMobile, KuposUIComponent, PaymentSideBarDesktop, PaymentSideBarMobile, ResponsivePaymentSideBar, ServiceListDesktop, ServiceListMobile, ResponsiveServiceList, FilterBarDesktop, FilterBarMobile, ResponsiveFilterBar, FilterSortBarMobile, SurveyDesktop, SurveyMobile, ResponsiveSurvey, Modal, ModalHeader, DiscountBannerMobile, DiscountBannerDesktop, ResponsiveDiscountBanner, };
|
|
13
14
|
export type { ServiceItemProps } from "./types";
|
|
14
15
|
export type { MobileServiceItemProps } from "./components/ServiceItem/mobileTypes";
|
|
15
16
|
export type { PaymentSideBarProps } from "./components/PaymentSideBar/types";
|
|
@@ -18,4 +19,6 @@ export type { FilterBarProps } from "./components/FilterBar/tyoes";
|
|
|
18
19
|
export type { FilterCategory, FilterCategoryKey, FilterCategoryKind, FilterOptionItem, PriceRangeValue, FilterSortBarColors, FilterSortBarIcons, FilterSortBarMobileProps, TimeOfDayVariant, SortDirection, SortOption, } from "./components/FilterSortBar";
|
|
19
20
|
export { DEFAULT_CATEGORY_LABELS } from "./components/FilterSortBar";
|
|
20
21
|
export type { SurveyProps } from "./components/Survey/types";
|
|
21
|
-
export type { ModalProps, ModalVariant, ModalSize, ModalHeaderProps } from "./ui/Modal";
|
|
22
|
+
export type { ModalProps, ModalVariant, ModalSize, ModalHeaderProps, } from "./ui/Modal";
|
|
23
|
+
export { deriveDiscountCards, CAMPAIGN_TYPE_LABELS, CAMPAIGN_ART, DEFAULT_BACKGROUND_IMAGES, toImageUrl, } from "./ui/DiscountBanners";
|
|
24
|
+
export type { DiscountBannerCard, DiscountBannerServiceItem, DiscountBannersProps, WowDealData, } from "./components/DiscountBanners";
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,8 @@ import { PaymentSideBarDesktop, PaymentSideBarMobile, ResponsivePaymentSideBar,
|
|
|
9
9
|
import { ServiceListDesktop, ServiceListMobile, ResponsiveServiceList, } from "./components/ServiceList";
|
|
10
10
|
// Import FilterBar components
|
|
11
11
|
import { FilterBarDesktop, FilterBarMobile, ResponsiveFilterBar, } from "./components/FilterBar";
|
|
12
|
+
//Import Discount Banner's
|
|
13
|
+
import { DiscountBannerDesktop, DiscountBannerMobile, ResponsiveDiscountBanner, } from "./components/DiscountBanners";
|
|
12
14
|
// Import FilterSortBar components
|
|
13
15
|
import { FilterSortBarMobile } from "./components/FilterSortBar";
|
|
14
16
|
// Import Survey components
|
|
@@ -27,5 +29,8 @@ FilterSortBarMobile,
|
|
|
27
29
|
//Survey components
|
|
28
30
|
SurveyDesktop, SurveyMobile, ResponsiveSurvey,
|
|
29
31
|
// Modal components
|
|
30
|
-
Modal, ModalHeader,
|
|
32
|
+
Modal, ModalHeader,
|
|
33
|
+
// DiscountBanners components
|
|
34
|
+
DiscountBannerMobile, DiscountBannerDesktop, ResponsiveDiscountBanner, };
|
|
31
35
|
export { DEFAULT_CATEGORY_LABELS } from "./components/FilterSortBar";
|
|
36
|
+
export { deriveDiscountCards, CAMPAIGN_TYPE_LABELS, CAMPAIGN_ART, DEFAULT_BACKGROUND_IMAGES, toImageUrl, } from "./ui/DiscountBanners";
|