kupos-ui-components-lib 10.4.31 → 10.4.34

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 (71) hide show
  1. package/dist/KuposUIComponent.d.ts +1 -1
  2. package/dist/KuposUIComponent.js +3 -0
  3. package/dist/assets/images/discount/blue.png +0 -0
  4. package/dist/assets/images/discount/cash.png +0 -0
  5. package/dist/assets/images/discount/first.png +0 -0
  6. package/dist/assets/images/discount/green.png +0 -0
  7. package/dist/assets/images/discount/instant.png +0 -0
  8. package/dist/assets/images/discount/last.png +0 -0
  9. package/dist/assets/images/discount/promo.png +0 -0
  10. package/dist/assets/images/discount/round.png +0 -0
  11. package/dist/assets/images/discount/seat.png +0 -0
  12. package/dist/assets/images/discount/yellow.png +0 -0
  13. package/dist/assets/images/index.d.ts +12 -0
  14. package/dist/assets/images/index.js +12 -0
  15. package/dist/assets/images/index.ts +14 -0
  16. package/dist/components/DiscountBanners/DiscountBannerDesktop.d.ts +11 -0
  17. package/dist/components/DiscountBanners/DiscountBannerDesktop.js +133 -0
  18. package/dist/components/DiscountBanners/DiscountBannerMobile.d.ts +11 -0
  19. package/dist/components/DiscountBanners/DiscountBannerMobile.js +132 -0
  20. package/dist/components/DiscountBanners/ResponsiveDiscountBanner.d.ts +3 -0
  21. package/dist/components/DiscountBanners/ResponsiveDiscountBanner.js +10 -0
  22. package/dist/components/DiscountBanners/index.d.ts +5 -0
  23. package/dist/components/DiscountBanners/index.js +4 -0
  24. package/dist/components/DiscountBanners/types.d.ts +51 -0
  25. package/dist/components/DiscountBanners/types.js +1 -0
  26. package/dist/components/ServiceItem/ServiceItemDesktop.js +1 -1
  27. package/dist/components/ServiceItem/ServiceItemMobile.js +0 -1
  28. package/dist/index.d.ts +5 -2
  29. package/dist/index.js +6 -1
  30. package/dist/styles.css +89 -0
  31. package/dist/ui/DiscountBanners/DiscountBanners.d.ts +4 -0
  32. package/dist/ui/DiscountBanners/DiscountBanners.js +114 -0
  33. package/dist/ui/DiscountBanners/defaultBackgrounds.d.ts +12 -0
  34. package/dist/ui/DiscountBanners/defaultBackgrounds.js +38 -0
  35. package/dist/ui/DiscountBanners/discountUtils.d.ts +3 -0
  36. package/dist/ui/DiscountBanners/discountUtils.js +126 -0
  37. package/dist/ui/DiscountBanners/index.d.ts +5 -0
  38. package/dist/ui/DiscountBanners/index.js +3 -0
  39. package/dist/ui/DiscountBanners/types.d.ts +49 -0
  40. package/dist/ui/DiscountBanners/types.js +1 -0
  41. package/dist/ui/ServiceBadges/ServiceBadges.js +1 -1
  42. package/dist/ui/mobileweb/ServiceBadgesMobile.js +1 -1
  43. package/package.json +21 -6
  44. package/src/KuposUIComponent.tsx +13 -1
  45. package/src/assets/images/discount/blue.png +0 -0
  46. package/src/assets/images/discount/cash.png +0 -0
  47. package/src/assets/images/discount/first.png +0 -0
  48. package/src/assets/images/discount/green.png +0 -0
  49. package/src/assets/images/discount/instant.png +0 -0
  50. package/src/assets/images/discount/last.png +0 -0
  51. package/src/assets/images/discount/promo.png +0 -0
  52. package/src/assets/images/discount/round.png +0 -0
  53. package/src/assets/images/discount/seat.png +0 -0
  54. package/src/assets/images/discount/yellow.png +0 -0
  55. package/src/assets/images/index.ts +14 -0
  56. package/src/components/DiscountBanners/DiscountBannerDesktop.tsx +240 -0
  57. package/src/components/DiscountBanners/DiscountBannerMobile.tsx +234 -0
  58. package/src/components/DiscountBanners/ResponsiveDiscountBanner.tsx +16 -0
  59. package/src/components/DiscountBanners/index.ts +16 -0
  60. package/src/components/DiscountBanners/types.ts +55 -0
  61. package/src/components/ServiceItem/ServiceItemDesktop.tsx +1 -0
  62. package/src/components/ServiceItem/ServiceItemMobile.tsx +0 -1
  63. package/src/index.ts +34 -3
  64. package/src/types/images.d.ts +12 -0
  65. package/src/ui/DiscountBanners/DiscountBanners.tsx +215 -0
  66. package/src/ui/DiscountBanners/defaultBackgrounds.ts +42 -0
  67. package/src/ui/DiscountBanners/discountUtils.ts +166 -0
  68. package/src/ui/DiscountBanners/index.ts +14 -0
  69. package/src/ui/DiscountBanners/types.ts +53 -0
  70. package/src/ui/ServiceBadges/ServiceBadges.tsx +1 -1
  71. package/src/ui/mobileweb/ServiceBadgesMobile.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;
@@ -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: ",
@@ -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,3 @@
1
+ import React from "react";
2
+ import { DiscountBannersProps } from "../DiscountBanners/types";
3
+ export default function ResponsiveDiscountBanner(props: DiscountBannersProps): React.JSX.Element;
@@ -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 {};
@@ -305,7 +305,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
305
305
  },
306
306
  ];
307
307
  const otherItems = items.filter((i) => i.key !== "pet" && i.key !== "flexible" && !!i.condition);
308
- return (React.createElement(React.Fragment, null, isPeruSites ? (React.createElement(PeruServiceItemDesktop, { serviceItem: serviceItem, onBookButtonPress: onBookButtonPress, colors: colors, metaData: metaData, children: children, busStage: busStage, serviceDetailsLoading: serviceDetailsLoading, cityOrigin: cityOrigin, cityDestination: cityDestination, translation: translation, orignLabel: orignLabel, destinationLabel: destinationLabel, currencySign: currencySign, isCiva: isCiva, showRating: showRating, showLastSeats: showLastSeats, removeArrivalTime: removeArrivalTime, removeDuplicateSeats: removeDuplicateSeats, isPeruSites: isPeruSites, t: (key) => t(key), showAvailableSeats: showAvailableSeats, isSeatIcon: isSeatIcon, isPeru: isPeru, siteType: siteType, isAllinBus: isAllinBus, viewersConfig: viewersConfig, isLoggedIn: isLoggedIn, showLoginModal: showLoginModal, isExpand: isExpand, setIsExpand: setIsExpand, coachKey: coachKey, isFlores: isFlores, isNewUiEnabled: isNewUiEnabledPeru, showLoginOption: showLoginOption })) : isNewUi && !isTrain ? (React.createElement(FeatureServiceUi, { serviceItem: serviceItem, showTopLabel: showTopLabel, getAnimationIcon: getAnimationIcon, cityOrigin: cityOrigin, cityDestination: cityDestination, renderIcon: renderIcon, viewersConfig: viewersConfig, isFeatureDropDownExpand: isFeatureDropDownExpand, ticketQuantity: ticketQuantity, onIncreaseTicketQuantity: onIncreaseTicketQuantity, onDecreaseTicketQuantity: onDecreaseTicketQuantity, onBookButtonPress: onRemateUiButtonClick, onToggleExpand: () => setIsFeatureDropDownExpand &&
308
+ return (React.createElement(React.Fragment, null, isPeruSites ? (React.createElement(PeruServiceItemDesktop, { serviceItem: serviceItem, onBookButtonPress: onBookButtonPress, colors: colors, metaData: metaData, children: children, busStage: busStage, serviceDetailsLoading: serviceDetailsLoading, cityOrigin: cityOrigin, cityDestination: cityDestination, translation: translation, orignLabel: orignLabel, destinationLabel: destinationLabel, currencySign: currencySign, isCiva: isCiva, showRating: showRating, showLastSeats: showLastSeats, removeArrivalTime: removeArrivalTime, removeDuplicateSeats: removeDuplicateSeats, isPeruSites: isPeruSites, t: (key) => t(key), showAvailableSeats: showAvailableSeats, isSeatIcon: isSeatIcon, isPeru: isPeru, siteType: siteType, isAllinBus: isAllinBus, viewersConfig: viewersConfig, isLoggedIn: isLoggedIn, showLoginModal: showLoginModal, isExpand: isExpand, setIsExpand: setIsExpand, coachKey: coachKey, isFlores: isFlores, isNewUiEnabled: isNewUiEnabledPeru, showLoginOption: showLoginOption, priority_stage_ids: priority_stage_ids })) : isNewUi && !isTrain ? (React.createElement(FeatureServiceUi, { serviceItem: serviceItem, showTopLabel: showTopLabel, getAnimationIcon: getAnimationIcon, cityOrigin: cityOrigin, cityDestination: cityDestination, renderIcon: renderIcon, viewersConfig: viewersConfig, isFeatureDropDownExpand: isFeatureDropDownExpand, ticketQuantity: ticketQuantity, onIncreaseTicketQuantity: onIncreaseTicketQuantity, onDecreaseTicketQuantity: onDecreaseTicketQuantity, onBookButtonPress: onRemateUiButtonClick, onToggleExpand: () => setIsFeatureDropDownExpand &&
309
309
  setIsFeatureDropDownExpand(isFeatureDropDownExpand === serviceItem.id ||
310
310
  isFeatureDropDownExpand === true
311
311
  ? null
@@ -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";