kupos-ui-components-lib 9.0.6 → 9.0.8

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.
@@ -1,5 +1,4 @@
1
1
  import React from "react";
2
- import DateService from "../../utils/DateService";
3
2
  import CommonService from "../../utils/CommonService";
4
3
  import ModalEventManager from "../../utils/ModalEventManager";
5
4
  import InternationalServicePopupBody from "../InternationalServicePopupBody";
@@ -23,14 +22,15 @@ import opsitesPriorityStageAnimation from "../../assets/images/anims/service_lis
23
22
  import bombAnimation from "../../assets/images/anims/service_list/bomb.json";
24
23
  import RatingBlock from "../../ui/RatingBlock";
25
24
  import DurationBlock from "../../ui/DurationBlock";
25
+ import DirectoBlock from "../../ui/DirectoBlock";
26
26
  import PetBlock from "../../ui/PetBlock";
27
27
  import FlexibleBlock from "../../ui/FlexibleBlock";
28
28
  import AmenitiesBlock from "../../ui/AmenitiesBlock";
29
- import StageTooltip from "../../ui/StagesTooltip";
30
29
  import KuposButton from "../../ui/KuposButton/KuposButton";
31
30
  import TopAmenities from "../../ui/TopAmenities/TopAmenities";
32
31
  import BottomAmenities from "../../ui/BottomAmenities/BottomAmenities";
33
32
  import SeatSection from "../../ui/SeatSection/SeatSection";
33
+ import DateTimeSection from "../../ui/DateTimeSection/DateTimeSection";
34
34
  const SEAT_EXCEPTIONS = ["Asiento mascota"];
35
35
  const ANIMATION_MAP = {
36
36
  promoAnim: {
@@ -63,22 +63,7 @@ const ANIMATION_MAP = {
63
63
  kupos: bombAnimation,
64
64
  },
65
65
  };
66
- const convertTo24Hour = (depTime) => {
67
- const hasAM = depTime.includes("AM");
68
- const hasPM = depTime.includes("PM");
69
- const [timePart] = depTime.split(/AM|PM/).map((part) => part.trim());
70
- const [hour, minute] = timePart.split(":").map(Number);
71
- const pad = (n) => (n < 10 ? "0" + n : String(n));
72
- if (hasAM) {
73
- return `${pad(hour === 12 ? 0 : hour)}:${pad(minute)}`;
74
- }
75
- if (hasPM) {
76
- return `${hour === 12 ? hour : hour + 12}:${pad(minute)}`;
77
- }
78
- return timePart;
79
- };
80
66
  function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, children, busStage, serviceDetailsLoading, cityOrigin, cityDestination, translation, orignLabel, destinationLabel, currencySign, isCiva, showRating, showLastSeats, removeArrivalTime, removeDuplicateSeats, isPeruSites, showAvailableSeats, isSeatIcon, isLinatal, isPeru, t = (key) => key, siteType, isAllinBus, isExpand, setIsExpand, coachKey, }) {
81
- var _a, _b;
82
67
  const getAnimationIcon = (icon) => {
83
68
  var _a;
84
69
  const animation = ANIMATION_MAP[icon];
@@ -198,10 +183,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
198
183
  }
199
184
  onBookButtonPress();
200
185
  };
201
- const depTime = serviceItem.dep_time || "";
202
- const hasAM = depTime.includes("AM");
203
- const hasPM = depTime.includes("PM");
204
- const cleanedDepTime = convertTo24Hour(depTime);
186
+ const countdownSeconds = 7830;
205
187
  const items = [
206
188
  {
207
189
  key: "amenities",
@@ -218,10 +200,8 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
218
200
  {
219
201
  key: "directo",
220
202
  width: "12%",
221
- condition: serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip,
222
- render: (React.createElement("div", { className: "flex items-center gap-[10px] text-[12.5px] z-10 mt-[6px]" },
223
- React.createElement(LottiePlayer, { animationData: getAnimationIcon("directoAnim"), width: "14px", height: "14px" }),
224
- React.createElement("div", null, translation === null || translation === void 0 ? void 0 : translation.directService))),
203
+ condition: !(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip),
204
+ render: (React.createElement(DirectoBlock, { translation: translation, getAnimationIcon: getAnimationIcon, colors: colors, isSoldOut: isSoldOut })),
225
205
  },
226
206
  {
227
207
  key: "pet",
@@ -239,16 +219,24 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
239
219
  ];
240
220
  const otherItems = items.filter((i) => i.key !== "pet" && i.key !== "flexible" && !!i.condition);
241
221
  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 })) : (React.createElement("div", { className: `relative ${serviceItem.offer_text ? "mb-[55px]" : "mb-[10px]"} mt-[14px]` },
242
- React.createElement(TopAmenities, { showPromo: showPromo, showTopLabel: showTopLabel, isSoldOut: isSoldOut, priceColor: colors.priceColor, buttonColor: colors.kuposButtonColor, boardingIcon: renderIcon("whiteBoardingIcon", "14px"), getAnimationIcon: getAnimationIcon }),
243
- React.createElement("div", { className: "bg-white mx-auto relative", style: {
244
- border: `1px solid ${colors.priceColor}`,
245
- // showPromo
246
- // ? `1px solid ${colors.priceColor}`
247
- // : "1px solid #ccc",
248
- borderRadius:
249
- // showPromo || showTopLabel ?
250
- "10px 0 10px 10px",
251
- // : "10px",
222
+ React.createElement(TopAmenities, { showPromo: showPromo, showTopLabel: showTopLabel, isSoldOut: isSoldOut, priceColor: colors.priceColor, buttonColor: colors.kuposButtonColor, boardingIcon: renderIcon("whiteBoardingIcon", "14px"), getAnimationIcon: getAnimationIcon, countdownSeconds: countdownSeconds, onCountdownEnd: () => {
223
+ const cardEl = document.getElementById(`service-card-${serviceItem.id}`);
224
+ if (!cardEl)
225
+ return;
226
+ cardEl.style.border = "1px solid #ccc";
227
+ if (!showTopLabel) {
228
+ cardEl.style.borderRadius = "10px";
229
+ }
230
+ } }),
231
+ React.createElement("div", { id: `service-card-${serviceItem.id}`, className: "bg-white mx-auto relative ", style: {
232
+ border: countdownSeconds > 0
233
+ ? `1px solid ${colors.priceColor}`
234
+ : "1px solid #ccc",
235
+ borderRadius: showTopLabel
236
+ ? "10px 0 10px 10px"
237
+ : countdownSeconds > 0
238
+ ? "10px 0 10px 10px"
239
+ : "10px",
252
240
  } },
253
241
  React.createElement("div", {
254
242
  // className="p-[15px] pt-[20px]"
@@ -271,39 +259,7 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
271
259
  React.createElement("img", { src: serviceItem.operator_details[0], alt: "service logo", className: `h-auto w-[150px] object-contain ${isSoldOut ? "grayscale" : ""}` }),
272
260
  isCiva ? (React.createElement("div", { className: "text-[13.33px] black-text ml-2" }, serviceItem.operator_details[2])) : null),
273
261
  React.createElement(RatingBlock, { showRating: showRating, serviceItem: serviceItem, isSoldOut: isSoldOut, colors: colors, t: t, translation: translation })),
274
- React.createElement("div", { className: `min-h-[2.5rem] grid grid-cols-[26px_auto_26%_1fr] gap-x-4 items-center text-[13.33px] ${isSoldOut ? "text-[#c0c0c0]" : ""}`, style: {
275
- gridTemplateRows: "1fr",
276
- } },
277
- React.createElement("div", { className: "flex flex-col gap-[6px]" },
278
- orignLabel ? (React.createElement("div", { className: "w-[60px] h-[20px] flex items-center" }, orignLabel)) : (React.createElement("div", { className: "h-[20px] flex items-center" },
279
- React.createElement("img", { src: (_a = serviceItem.icons) === null || _a === void 0 ? void 0 : _a.origin, alt: "origin", className: `w-[16px] h-auto mr-[8px] ${isSoldOut ? "grayscale" : ""}` }))),
280
- !isCiva &&
281
- (destinationLabel ? (React.createElement("div", { className: "w-[60px] h-[20px] flex items-center" }, destinationLabel)) : (React.createElement("div", { className: "h-[20px] flex items-center" },
282
- React.createElement("img", { src: (_b = serviceItem.icons) === null || _b === void 0 ? void 0 : _b.destination, className: `w-[16px] h-auto mr-[8px] ${isSoldOut ? "grayscale" : ""}`, style: { opacity: isSoldOut ? 0.5 : 1 } }))))),
283
- React.createElement("div", { className: "flex flex-col gap-[6px]" },
284
- React.createElement(StageTooltip, { stageData: serviceItem.boarding_stages, direction: 1, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
285
- React.createElement("span", { className: "cursor-pointer bold-text capitalize" }, DateService.getServiceItemDate(serviceItem.travel_date))),
286
- !isCiva && (React.createElement(StageTooltip, { stageData: serviceItem.boarding_stages, direction: 1, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
287
- React.createElement("span", { className: "cursor-pointer bold-text capitalize" }, DateService.getServiceItemDate(serviceItem.arrival_date))))),
288
- React.createElement("div", { className: "flex flex-col gap-[6px] items-center" },
289
- React.createElement("div", { className: "h-[20px] flex items-center justify-center" },
290
- React.createElement("div", null, "\u2022")),
291
- !isCiva && (React.createElement("div", { className: "h-[20px] flex items-center justify-center" }, removeArrivalTime ? null : serviceItem.arr_time ? (React.createElement("div", null, "\u2022")) : null))),
292
- React.createElement("div", { className: "flex flex-col gap-[6px]" },
293
- React.createElement(StageTooltip, { stageData: serviceItem.dropoff_stages, direction: 2, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
294
- React.createElement("div", { className: "font-[900] bold-text" }, isLinatal ? (React.createElement(React.Fragment, null,
295
- cleanedDepTime,
296
- " ",
297
- React.createElement("span", null, hasPM ? "PM" : hasAM ? "AM" : ""),
298
- !(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dep_time.includes("AM")) &&
299
- !(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dep_time.includes("PM")) &&
300
- DateService.ampmOnly(serviceItem.dep_time))) : (DateService.formatTime(serviceItem.dep_time)))),
301
- !isCiva && (React.createElement(StageTooltip, { stageData: serviceItem.dropoff_stages, direction: 2, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
302
- React.createElement("div", { className: "font-[900] bold-text" }, removeArrivalTime
303
- ? null
304
- : serviceItem.arr_time
305
- ? DateService.formatTime(serviceItem.arr_time)
306
- : null))))),
262
+ React.createElement(DateTimeSection, { serviceItem: serviceItem, isSoldOut: isSoldOut, isCiva: isCiva, isLinatal: isLinatal, removeArrivalTime: removeArrivalTime, orignLabel: orignLabel, destinationLabel: destinationLabel, busStage: busStage, metaData: metaData, colors: colors }),
307
263
  React.createElement("div", { style: {
308
264
  width: "1px",
309
265
  height: "2.5rem",
@@ -322,7 +278,14 @@ function ServiceItemPB({ serviceItem, onBookButtonPress, colors, metaData, child
322
278
  React.createElement(KuposButton, { isSoldOut: isSoldOut, isLoading: serviceDetailsLoading, buttonColor: colors.kuposButtonColor, buyLabel: translation === null || translation === void 0 ? void 0 : translation.buyButton, soldOutLabel: translation === null || translation === void 0 ? void 0 : translation.soldOutButton, soldOutIcon: renderIcon("soldOutIcon", "14px"), onClick: checkMidnight }))),
323
279
  React.createElement(BottomAmenities, { otherItems: otherItems, serviceItem: serviceItem, grayscaleClass: grayscaleClass, isSoldOut: isSoldOut, isItemExpanded: isItemExpanded, colors: colors, translation: translation, getAnimationIcon: getAnimationIcon, downArrowIcon: renderIcon("downArrow", "10px"), onToggleExpand: () => setIsExpand &&
324
280
  setIsExpand(isItemExpanded ? null : serviceItem.id) }))),
325
- isItemExpanded && (React.createElement(ExpandedDropdown, { serviceItem: serviceItem, showPromo: showPromo, colors: colors, grayscaleClass: grayscaleClass, translation: translation, getAnimationIcon: getAnimationIcon })),
281
+ React.createElement("div", { style: {
282
+ display: "grid",
283
+ gridTemplateRows: isItemExpanded ? "1fr" : "0fr",
284
+ opacity: isItemExpanded ? 1 : 0,
285
+ transition: "grid-template-rows 0.3s ease-in-out, opacity 0.25s ease-in-out",
286
+ } },
287
+ React.createElement("div", { style: { overflow: "hidden", minHeight: 0, marginTop: "-10px" } },
288
+ React.createElement(ExpandedDropdown, { serviceItem: serviceItem, showPromo: showPromo, colors: colors, grayscaleClass: grayscaleClass, translation: translation, getAnimationIcon: getAnimationIcon }))),
326
289
  children,
327
290
  (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.offer_text) && (React.createElement("div", { className: "text-white p-[10px_15px] text-left w-full flex items-center absolute -bottom-[36px] pt-[50px] -z-10 rounded-b-[14px] text-[14px]", style: {
328
291
  backgroundColor: colors === null || colors === void 0 ? void 0 : colors.bottomStripColor,
package/dist/styles.css CHANGED
@@ -135,12 +135,12 @@
135
135
  .mt-\[2px\] {
136
136
  margin-top: 2px;
137
137
  }
138
+ .mt-\[3px\] {
139
+ margin-top: 3px;
140
+ }
138
141
  .mt-\[5px\] {
139
142
  margin-top: 5px;
140
143
  }
141
- .mt-\[6px\] {
142
- margin-top: 6px;
143
- }
144
144
  .mt-\[10px\] {
145
145
  margin-top: 10px;
146
146
  }
@@ -294,6 +294,9 @@
294
294
  .max-h-\[66vh\] {
295
295
  max-height: 66vh;
296
296
  }
297
+ .min-h-\[2\.2rem\] {
298
+ min-height: 2.2rem;
299
+ }
297
300
  .min-h-\[2\.5rem\] {
298
301
  min-height: 2.5rem;
299
302
  }
@@ -366,6 +369,10 @@
366
369
  .w-auto {
367
370
  width: auto;
368
371
  }
372
+ .w-fit {
373
+ width: -moz-fit-content;
374
+ width: fit-content;
375
+ }
369
376
  .w-full {
370
377
  width: 100%;
371
378
  }
@@ -465,6 +472,9 @@
465
472
  .gap-\[6px\] {
466
473
  gap: 6px;
467
474
  }
475
+ .gap-\[8px\] {
476
+ gap: 8px;
477
+ }
468
478
  .gap-\[10px\] {
469
479
  gap: 10px;
470
480
  }
@@ -10,13 +10,14 @@ function BottomAmenities({ otherItems, serviceItem, grayscaleClass, isSoldOut, i
10
10
  Object.keys(serviceItem.pet_seat_info).length > 0);
11
11
  return (React.createElement("div", { className: "flex items-center mt-[15px] border-t border-[#eee] pt-[6px]" },
12
12
  React.createElement("div", { className: "grid items-center gap-[2%] flex-1 ", style: {
13
- gridTemplateColumns: "18% 18% 23% 23%",
13
+ // gridTemplateColumns: " 28% 21% 23% 23%",
14
+ gridTemplateColumns: "28% 17% 23% 23%",
14
15
  } }, otherItems.map((item) => (React.createElement("div", { key: item.key, className: "flex items-center" }, item.render)))),
15
16
  React.createElement("div", { className: "flex items-center justify-end shrink-0 ml-[5px] w-[150px]" },
16
17
  (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_tracking_enabled) && (React.createElement("div", { className: grayscaleClass + " mr-[10px]" },
17
18
  React.createElement(LottiePlayer, { animationData: getAnimationIcon("locationAnim"), width: "20px", height: "20px" }))),
18
19
  serviceItem.is_change_ticket && (React.createElement(FlexibleBlock, { translation: translation, getAnimationIcon: getAnimationIcon, colors: colors, serviceItem: serviceItem, isSoldOut: isSoldOut })),
19
20
  hasPetInfo && (React.createElement(PetBlock, { translation: translation, getAnimationIcon: getAnimationIcon, colors: colors, isSoldOut: isSoldOut })),
20
- showDownArrow ? (React.createElement("div", { className: "flex items-center cursor-pointer ml-[4px] transition-transform duration-300 w-[14px] h-[14px]", onClick: onToggleExpand }, downArrowIcon)) : null)));
21
+ showDownArrow ? (React.createElement("div", { className: `flex items-center cursor-pointer ml-[4px] transition-transform duration-300 w-[14px] h-[14px] ${isItemExpanded ? "rotate-180" : ""}`, onClick: onToggleExpand }, downArrowIcon)) : null)));
21
22
  }
22
23
  export default BottomAmenities;
@@ -0,0 +1,28 @@
1
+ import React from "react";
2
+ interface DateTimeSectionProps {
3
+ serviceItem: {
4
+ icons?: {
5
+ origin?: string;
6
+ destination?: string;
7
+ [key: string]: any;
8
+ };
9
+ boarding_stages?: string;
10
+ dropoff_stages?: string;
11
+ travel_date: string;
12
+ arrival_date: string;
13
+ dep_time: string;
14
+ arr_time: string;
15
+ [key: string]: any;
16
+ };
17
+ isSoldOut: boolean;
18
+ isCiva?: boolean;
19
+ isLinatal?: boolean;
20
+ removeArrivalTime?: boolean;
21
+ orignLabel?: string;
22
+ destinationLabel?: string;
23
+ busStage?: Record<string, string>;
24
+ metaData?: any;
25
+ colors: Record<string, any>;
26
+ }
27
+ declare function DateTimeSection({ serviceItem, isSoldOut, isCiva, isLinatal, removeArrivalTime, orignLabel, destinationLabel, busStage, metaData, colors, }: DateTimeSectionProps): React.ReactElement;
28
+ export default DateTimeSection;
@@ -0,0 +1,58 @@
1
+ import React from "react";
2
+ import DateService from "../../utils/DateService";
3
+ import StageTooltip from "../StagesTooltip";
4
+ function DateTimeSection({ serviceItem, isSoldOut, isCiva, isLinatal, removeArrivalTime, orignLabel, destinationLabel, busStage, metaData, colors, }) {
5
+ var _a, _b;
6
+ const depTime = serviceItem.dep_time || "";
7
+ const hasAM = depTime.includes("AM");
8
+ const hasPM = depTime.includes("PM");
9
+ const convertTo24Hour = (depTime) => {
10
+ const hasAM = depTime.includes("AM");
11
+ const hasPM = depTime.includes("PM");
12
+ const [timePart] = depTime.split(/AM|PM/).map((part) => part.trim());
13
+ const [hour, minute] = timePart.split(":").map(Number);
14
+ const pad = (n) => (n < 10 ? "0" + n : String(n));
15
+ if (hasAM) {
16
+ return `${pad(hour === 12 ? 0 : hour)}:${pad(minute)}`;
17
+ }
18
+ if (hasPM) {
19
+ return `${hour === 12 ? hour : hour + 12}:${pad(minute)}`;
20
+ }
21
+ return timePart;
22
+ };
23
+ const cleanedDepTime = convertTo24Hour(depTime);
24
+ return (React.createElement("div", { className: `min-h-[2.2rem] grid grid-cols-[26px_auto_26%_1fr] gap-x-4 items-center text-[13.33px] ${isSoldOut ? "text-[#c0c0c0]" : ""}`, style: {
25
+ gridTemplateRows: "1fr",
26
+ } },
27
+ React.createElement("div", { className: "flex flex-col gap-[6px]" },
28
+ orignLabel ? (React.createElement("div", { className: "w-[60px] h-[20px] flex items-center" }, orignLabel)) : (React.createElement("div", { className: "h-[20px] flex items-center" },
29
+ React.createElement("img", { src: (_a = serviceItem.icons) === null || _a === void 0 ? void 0 : _a.origin, alt: "origin", className: `w-[16px] h-auto mr-[8px] ${isSoldOut ? "grayscale" : ""}` }))),
30
+ !isCiva &&
31
+ (destinationLabel ? (React.createElement("div", { className: "w-[60px] h-[20px] flex items-center" }, destinationLabel)) : (React.createElement("div", { className: "h-[20px] flex items-center" },
32
+ React.createElement("img", { src: (_b = serviceItem.icons) === null || _b === void 0 ? void 0 : _b.destination, className: `w-[16px] h-auto mr-[8px] ${isSoldOut ? "grayscale" : ""}`, style: { opacity: isSoldOut ? 0.5 : 1 } }))))),
33
+ React.createElement("div", { className: "flex flex-col gap-[6px]" },
34
+ React.createElement(StageTooltip, { stageData: serviceItem.boarding_stages, direction: 1, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
35
+ React.createElement("span", { className: "cursor-pointer bold-text capitalize" }, DateService.getServiceItemDate(serviceItem.travel_date))),
36
+ !isCiva && (React.createElement(StageTooltip, { stageData: serviceItem.boarding_stages, direction: 1, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
37
+ React.createElement("span", { className: "cursor-pointer bold-text capitalize" }, DateService.getServiceItemDate(serviceItem.arrival_date))))),
38
+ React.createElement("div", { className: "flex flex-col gap-[6px] items-center" },
39
+ React.createElement("div", { className: "h-[20px] flex items-center justify-center" },
40
+ React.createElement("div", null, "\u2022")),
41
+ !isCiva && (React.createElement("div", { className: "h-[20px] flex items-center justify-center" }, removeArrivalTime ? null : serviceItem.arr_time ? (React.createElement("div", null, "\u2022")) : null))),
42
+ React.createElement("div", { className: "flex flex-col gap-[6px]" },
43
+ React.createElement(StageTooltip, { stageData: serviceItem.dropoff_stages, direction: 2, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
44
+ React.createElement("div", { className: "font-[900] bold-text" }, isLinatal ? (React.createElement(React.Fragment, null,
45
+ cleanedDepTime,
46
+ " ",
47
+ React.createElement("span", null, hasPM ? "PM" : hasAM ? "AM" : ""),
48
+ !(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dep_time.includes("AM")) &&
49
+ !(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.dep_time.includes("PM")) &&
50
+ DateService.ampmOnly(serviceItem.dep_time))) : (DateService.formatTime(serviceItem.dep_time)))),
51
+ !isCiva && (React.createElement(StageTooltip, { stageData: serviceItem.dropoff_stages, direction: 2, terminals: busStage, serviceItem: serviceItem, metaData: metaData, colors: colors },
52
+ React.createElement("div", { className: "font-[900] bold-text" }, removeArrivalTime
53
+ ? null
54
+ : serviceItem.arr_time
55
+ ? DateService.formatTime(serviceItem.arr_time)
56
+ : null))))));
57
+ }
58
+ export default DateTimeSection;
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ declare const DirectoBlock: ({ translation, isSoldOut, colors, getAnimationIcon }: {
3
+ translation: any;
4
+ isSoldOut: any;
5
+ colors: any;
6
+ getAnimationIcon: any;
7
+ }) => React.JSX.Element;
8
+ export default DirectoBlock;
@@ -0,0 +1,11 @@
1
+ import React from "react";
2
+ import LottiePlayer from "../assets/LottiePlayer";
3
+ const DirectoBlock = ({ translation, isSoldOut, colors, getAnimationIcon }) => (React.createElement("div", { className: "flex items-center relative whitespace-nowrap mt-[3px]" },
4
+ React.createElement("div", { className: `w-[18px] mr-[4px] ${isSoldOut ? "grayscale" : ""}` },
5
+ React.createElement(LottiePlayer, { animationData: getAnimationIcon("directoAnim"), width: "14px", height: "14px" })),
6
+ React.createElement("div", { className: "group text-[13.33px] cursor-pointer" }, translation === null || translation === void 0 ? void 0 :
7
+ translation.directService,
8
+ React.createElement("div", { className: "hidden group-hover:block absolute top-[24px] left-1/2 -translate-x-1/2 text-white p-3 rounded-[14px] whitespace-nowrap w-fit z-10 mt-2.5 text-center shadow-service text-[12px]", style: { backgroundColor: colors.tooltipColor } },
9
+ React.createElement("div", { className: "tooltip-arrow absolute -top-[7px] left-1/2 -translate-x-1/2 w-0 h-0 border-l-8 border-r-8 border-b-8 border-l-transparent border-r-transparent", style: { borderBottomColor: colors.tooltipColor } }), translation === null || translation === void 0 ? void 0 :
10
+ translation.directServiceText))));
11
+ export default DirectoBlock;
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  interface ExpandedDropdownProps {
3
3
  serviceItem: {
4
+ change_ticket_hours?: number;
4
5
  pet_seat_info?: Record<string, any>;
5
6
  is_change_ticket?: boolean;
6
7
  is_tracking_enabled?: boolean;
@@ -1,27 +1,37 @@
1
1
  import React from "react";
2
- import LottiePlayer from "../../assets/LottiePlayer";
3
2
  function ExpandedDropdown({ serviceItem, showPromo, colors, grayscaleClass, translation, getAnimationIcon, }) {
3
+ var _a, _b;
4
4
  const hasPetInfo = serviceItem.pet_seat_info &&
5
5
  Object.keys(serviceItem.pet_seat_info).length > 0;
6
- return (React.createElement("div", { className: "px-[15px] pt-[26px] pb-[14px] -mt-[16px] pt-[20px] relative -z-9", style: {
7
- backgroundColor: "#f5f5f5",
6
+ return (React.createElement("div", { className: "px-[15px] pt-[26px] pb-[14px] -mt-[16px] pt-[35px] relative -z-9", style: {
7
+ backgroundColor: "#ffefef",
8
8
  borderRadius: "0 0 10px 10px",
9
9
  // border: showPromo ? `1px solid ${colors.priceColor}` : "1px solid #ccc",
10
- border: `1px solid ${colors.priceColor}`,
11
- borderTop: "none",
10
+ // border: `1px solid ${colors.priceColor}`,
11
+ // borderTop: "none",
12
12
  } },
13
- React.createElement("div", { className: "flex flex-col gap-[12px] text-[13px] text-[#464647]" },
14
- hasPetInfo && (React.createElement("div", { className: "flex items-center gap-[10px]" },
15
- React.createElement(LottiePlayer, { animationData: getAnimationIcon("petFriendlyAnim"), width: "20px", height: "20px" }),
16
- React.createElement("div", { className: "h-auto mr-[4px] text-[13px] text-[#464647] bold-text" },
17
- React.createElement("span", null, translation === null || translation === void 0 ? void 0 : translation.petFriendly)))),
18
- serviceItem.is_change_ticket && (React.createElement("div", { className: "flex items-center gap-[10px]" },
19
- React.createElement(LottiePlayer, { animationData: getAnimationIcon("flexibleIcon"), width: "20px", height: "20px" }),
20
- React.createElement("div", { className: "h-auto mr-[4px] text-[13px] text-[#464647] bold-text" },
21
- React.createElement("span", null, translation === null || translation === void 0 ? void 0 : translation.flexible)))),
22
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_tracking_enabled) && (React.createElement("div", { className: `${grayscaleClass} flex items-center gap-[10px]` },
23
- React.createElement(LottiePlayer, { animationData: getAnimationIcon("locationAnim"), width: "20px", height: "20px" }),
24
- React.createElement("div", { className: "h-auto mr-[4px] text-[13px] text-[#464647] bold-text" },
25
- React.createElement("span", null, "GPS Tracker")))))));
13
+ React.createElement("div", { className: "flex flex-col gap-[10px] text-[13px] text-[#464647]", style: { lineHeight: 1.6 } },
14
+ React.createElement("div", { className: "flex gap-[8px] text-[13.33px]" },
15
+ React.createElement("span", { style: { marginTop: "2px" } }, "\u2022"),
16
+ React.createElement("span", null,
17
+ React.createElement("span", { className: "bold-text" }, "Pol\u00EDticas de anulaci\u00F3n:"),
18
+ " Tu pasaje puede ser anulado de forma online",
19
+ " ",
20
+ React.createElement("span", { className: "bold-text" },
21
+ "hasta ", (_a = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.change_ticket_hours) !== null && _a !== void 0 ? _a : 6,
22
+ " horas antes"),
23
+ " ",
24
+ "de la salida del bus. Al anular tu pasaje recibir\u00E1s una devoluci\u00F3n del 85% del monto de tu compra.")),
25
+ React.createElement("div", { className: "flex gap-[8px]" },
26
+ React.createElement("span", { style: { marginTop: "2px" } }, "\u2022"),
27
+ React.createElement("span", null,
28
+ React.createElement("span", { className: "bold-text" }, "Pol\u00EDticas de cambios:"),
29
+ " Tu pasaje puede ser cambiado de manera online",
30
+ " ",
31
+ React.createElement("span", { className: "bold-text" },
32
+ "hasta ", (_b = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.change_ticket_hours) !== null && _b !== void 0 ? _b : 6,
33
+ " horas antes"),
34
+ " ",
35
+ "de la salida del bus. El monto ser\u00E1 reembolsado a tu billetera kupospay.")))));
26
36
  }
27
37
  export default ExpandedDropdown;
@@ -75,7 +75,7 @@ function SeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, currenc
75
75
  const strikethroughStyle = Object.assign({ color: "#ccc", display: "flex", textAlign: "end", textDecoration: "line-through" }, (isPeru
76
76
  ? { position: "relative", top: 0 }
77
77
  : { position: "absolute", top: isCentered ? "-10px" : "-18px" }));
78
- return (React.createElement("div", { className: "relative flex gap-[10px] text-[13.33px] justify-between min-h-[2.5rem]", style: isCentered ? { alignItems: "center" } : {} },
78
+ return (React.createElement("div", { className: "relative flex gap-[10px] text-[13.33px] justify-between min-h-[2.2rem]", style: isCentered ? { alignItems: "center" } : {} },
79
79
  React.createElement("div", { className: "flex flex-col justify-between", style: { gap: "10px" } }, renderLabels()),
80
80
  React.createElement("div", { className: "flex flex-col justify-between absolute inset-y-0 right-0 left-1/2 h-full", style: {
81
81
  color: isSoldOut ? "#c0c0c0" : priceColor,
@@ -0,0 +1,18 @@
1
+ import React from "react";
2
+ interface PromoCountdownProps {
3
+ countdownSeconds: number;
4
+ }
5
+ interface PromoCountdownState {
6
+ remaining: number;
7
+ }
8
+ declare class PromoCountdown extends React.Component<PromoCountdownProps, PromoCountdownState> {
9
+ private timer;
10
+ constructor(props: PromoCountdownProps);
11
+ componentDidMount(): void;
12
+ componentDidUpdate(prevProps: PromoCountdownProps): void;
13
+ componentWillUnmount(): void;
14
+ private clearTimer;
15
+ private startTimer;
16
+ render(): React.JSX.Element;
17
+ }
18
+ export default PromoCountdown;
@@ -0,0 +1,55 @@
1
+ import React from "react";
2
+ class PromoCountdown extends React.Component {
3
+ constructor(props) {
4
+ super(props);
5
+ this.timer = null;
6
+ this.state = { remaining: props.countdownSeconds };
7
+ }
8
+ componentDidMount() {
9
+ this.startTimer();
10
+ }
11
+ componentDidUpdate(prevProps) {
12
+ if (prevProps.countdownSeconds !== this.props.countdownSeconds) {
13
+ this.setState({ remaining: this.props.countdownSeconds }, () => {
14
+ this.startTimer();
15
+ });
16
+ }
17
+ }
18
+ componentWillUnmount() {
19
+ this.clearTimer();
20
+ }
21
+ clearTimer() {
22
+ if (this.timer) {
23
+ clearInterval(this.timer);
24
+ this.timer = null;
25
+ }
26
+ }
27
+ startTimer() {
28
+ this.clearTimer();
29
+ if (this.state.remaining <= 0)
30
+ return;
31
+ this.timer = setInterval(() => {
32
+ this.setState((prev) => {
33
+ if (prev.remaining <= 1) {
34
+ this.clearTimer();
35
+ return { remaining: 0 };
36
+ }
37
+ return { remaining: prev.remaining - 1 };
38
+ });
39
+ }, 1000);
40
+ }
41
+ render() {
42
+ const { remaining } = this.state;
43
+ const hrs = Math.floor(remaining / 3600);
44
+ const mins = Math.floor((remaining % 3600) / 60);
45
+ const secs = remaining % 60;
46
+ const pad = (n) => String(n).padStart(2, "0");
47
+ return (React.createElement("span", { className: "bold-text" },
48
+ pad(hrs),
49
+ ":",
50
+ pad(mins),
51
+ ":",
52
+ pad(secs)));
53
+ }
54
+ }
55
+ export default PromoCountdown;
@@ -7,6 +7,9 @@ interface TopAmenitiesProps {
7
7
  buttonColor?: string;
8
8
  boardingIcon?: React.ReactNode;
9
9
  getAnimationIcon: (icon: string) => any;
10
+ countdownSeconds?: number;
11
+ promoText?: string;
12
+ onCountdownEnd?: () => void;
10
13
  }
11
- declare function TopAmenities({ showPromo, showTopLabel, isSoldOut, priceColor, buttonColor, boardingIcon, getAnimationIcon, }: TopAmenitiesProps): React.ReactElement;
14
+ declare function TopAmenities({ showPromo, showTopLabel, isSoldOut, priceColor, buttonColor, boardingIcon, getAnimationIcon, countdownSeconds, onCountdownEnd, }: TopAmenitiesProps): React.ReactElement;
12
15
  export default TopAmenities;
@@ -1,13 +1,40 @@
1
1
  import React from "react";
2
2
  import LottiePlayer from "../../assets/LottiePlayer";
3
- function TopAmenities({ showPromo, showTopLabel, isSoldOut, priceColor, buttonColor, boardingIcon, getAnimationIcon, }) {
3
+ function TopAmenities({ showPromo, showTopLabel, isSoldOut, priceColor, buttonColor, boardingIcon, getAnimationIcon, countdownSeconds = 0, onCountdownEnd, }) {
4
+ const pad = (n) => String(n).padStart(2, "0");
5
+ const startCountdown = (el) => {
6
+ if (!el || el.dataset.timerStarted)
7
+ return;
8
+ el.dataset.timerStarted = "true";
9
+ let remaining = countdownSeconds;
10
+ const update = () => {
11
+ const hrs = Math.floor(remaining / 3600);
12
+ const mins = Math.floor((remaining % 3600) / 60);
13
+ const secs = remaining % 60;
14
+ el.textContent = `${pad(hrs)}:${pad(mins)}:${pad(secs)}`;
15
+ };
16
+ update();
17
+ const timer = setInterval(() => {
18
+ if (remaining <= 0) {
19
+ clearInterval(timer);
20
+ const promoBar = el.closest("[data-promo-bar]");
21
+ if (promoBar)
22
+ promoBar.style.display = "none";
23
+ if (onCountdownEnd)
24
+ onCountdownEnd();
25
+ return;
26
+ }
27
+ remaining--;
28
+ update();
29
+ }, 1000);
30
+ };
4
31
  return (React.createElement("div", { style: {
5
32
  display: "flex",
6
33
  justifyContent: "flex-end",
7
34
  position: "relative",
8
35
  zIndex: "-1",
9
36
  } },
10
- React.createElement("div", { style: {
37
+ React.createElement("div", { "data-promo-bar": true, style: {
11
38
  backgroundColor: priceColor,
12
39
  position: "relative",
13
40
  right: showTopLabel ? "-21px" : "",
@@ -16,11 +43,11 @@ function TopAmenities({ showPromo, showTopLabel, isSoldOut, priceColor, buttonCo
16
43
  borderTopLeftRadius: "10px",
17
44
  } },
18
45
  React.createElement("div", { style: { display: "flex", alignItems: "center" } },
19
- React.createElement(LottiePlayer, { animationData: getAnimationIcon("bombAnimation"), width: "14px", height: "14px" }),
46
+ React.createElement(LottiePlayer, { animationData: getAnimationIcon("bombAnimation"), width: "16px", height: "16px" }),
20
47
  React.createElement("span", { className: "flex items-center py-[10px] pl-[6px] text-white text-[13.33px] z-20", style: { paddingRight: showTopLabel ? "18px" : "" } },
21
48
  React.createElement("span", { className: "bold-text" }, "kuponazo 20%\u00A0"),
22
49
  " | Termina en\u00A0",
23
- React.createElement("span", { className: "bold-text" }, "02:10:30")))),
50
+ React.createElement("span", { className: "bold-text", ref: startCountdown })))),
24
51
  showTopLabel && (React.createElement("div", { className: "flex items-center py-[10px] px-[14px] text-[13.33px] z-20", style: {
25
52
  backgroundColor: isSoldOut ? "#ddd" : buttonColor,
26
53
  borderTopRightRadius: "10px",
@@ -1,7 +1,7 @@
1
1
  declare const commonService: {
2
2
  currency(amount: number, currencySign?: string): string;
3
3
  copyObject: (ob: any) => any;
4
- getServiceTypeLabelForFilters: (service_type: any) => "" | "Tipo de servicio" | "Punto de embarque" | "Tipo de asiento" | "SERVICIOS";
4
+ getServiceTypeLabelForFilters: (service_type: any) => "Tipo de servicio" | "Punto de embarque" | "Tipo de asiento" | "SERVICIOS" | "";
5
5
  truncateSeatLabel: (label: string | number) => string;
6
6
  getAmenitiesImage: (name: string, serviceItem: any) => string;
7
7
  getAmenityName: (rawAmenity: string) => string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kupos-ui-components-lib",
3
- "version": "9.0.6",
3
+ "version": "9.0.8",
4
4
  "description": "A reusable UI components package",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -30,6 +30,7 @@
30
30
  "author": "Zahid Dar",
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
+ "kupos-ui-components-lib": "^9.0.7",
33
34
  "lottie-react": "^2.4.1",
34
35
  "lottie-web": "^5.13.0",
35
36
  "moment": "^2.30.1",