kupos-ui-components-lib 9.3.1 → 9.3.3
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/assets/images/anims/service_list/60_percent_anim.json +1 -0
- package/dist/assets/images/anims/service_list/dot_animation.json +1 -0
- package/dist/assets/images/anims/service_list/thunder_icon.json +1 -0
- package/dist/components/ServiceItem/ServiceItemDesktop.js +50 -121
- package/dist/components/ServiceItem/ServiceItemMobile.js +44 -105
- package/dist/components/ServiceItem/mobileTypes.d.ts +3 -0
- package/dist/components/ServiceItem/types.d.ts +2 -0
- package/dist/styles.css +125 -23
- package/dist/types.d.ts +2 -0
- package/dist/ui/ExpendedDropDown/ExpandedDropdown.js +16 -19
- package/dist/ui/FeatureServiceUI/FeatureServiceUi.d.ts +12 -0
- package/dist/ui/FeatureServiceUI/FeatureServiceUi.js +101 -0
- package/dist/ui/SeatSection/SeatSection.d.ts +2 -1
- package/dist/ui/SeatSection/SeatSection.js +41 -10
- package/dist/ui/ServiceBadges/ServiceBadges.d.ts +17 -0
- package/dist/ui/ServiceBadges/ServiceBadges.js +33 -0
- package/dist/ui/mobileweb/DateTimeSectionMobile.d.ts +2 -1
- package/dist/ui/mobileweb/DateTimeSectionMobile.js +2 -2
- package/dist/ui/mobileweb/ExpandedDropdownMobile.js +18 -18
- package/dist/ui/mobileweb/SeatSectionMobile.d.ts +2 -1
- package/dist/ui/mobileweb/SeatSectionMobile.js +28 -16
- package/dist/ui/mobileweb/ServiceBadgesMobile.d.ts +17 -0
- package/dist/ui/mobileweb/ServiceBadgesMobile.js +35 -0
- package/dist/utils/CommonService.d.ts +7 -0
- package/dist/utils/CommonService.js +61 -0
- package/package.json +1 -1
- package/src/assets/images/anims/service_list/dot_animation.json +1 -0
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +93 -235
- package/src/components/ServiceItem/ServiceItemMobile.tsx +118 -166
- package/src/components/ServiceItem/mobileTypes.ts +3 -0
- package/src/components/ServiceItem/types.ts +2 -0
- package/src/styles.css +10 -0
- package/src/types.ts +2 -0
- package/src/ui/ExpendedDropDown/ExpandedDropdown.tsx +26 -67
- package/src/ui/SeatSection/SeatSection.tsx +87 -32
- package/src/ui/ServiceBadges/ServiceBadges.tsx +92 -0
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +3 -0
- package/src/ui/mobileweb/ExpandedDropdownMobile.tsx +24 -24
- package/src/ui/mobileweb/SeatSectionMobile.tsx +77 -32
- package/src/ui/mobileweb/ServiceBadgesMobile.tsx +92 -0
- package/src/utils/CommonService.ts +86 -0
|
@@ -31,7 +31,7 @@ const TimeRow = ({ label, icon, alt, date, timeContent, isSoldOut, }) => (React.
|
|
|
31
31
|
React.createElement("span", { className: "cursor-pointer black-text" }, DateService.getServiceItemDate(date)),
|
|
32
32
|
React.createElement("div", { className: "absolute left-[50%]" }, "\u2022"),
|
|
33
33
|
React.createElement("div", { className: "font-[900] relative black-text" }, timeContent)))));
|
|
34
|
-
function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal, isPeru, orignLabel, destinationLabel, originIcon, destinationIcon, travelDate, arrivalDate, depTime, arrTime, seatTypes, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, }) {
|
|
34
|
+
function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal, isPeru, orignLabel, destinationLabel, originIcon, destinationIcon, travelDate, arrivalDate, depTime, arrTime, seatTypes, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, }) {
|
|
35
35
|
const { cleaned: cleanedDepTime, hasAM, hasPM } = getCleanedDepTime(depTime);
|
|
36
36
|
const depTimeContent = isLinatal ? (React.createElement("div", null,
|
|
37
37
|
React.createElement("span", null,
|
|
@@ -52,6 +52,6 @@ function DateTimeSectionMobile({ onBookButtonPress, isCiva, isSoldOut, isLinatal
|
|
|
52
52
|
backgroundColor: "#ccc",
|
|
53
53
|
margin: "auto",
|
|
54
54
|
} })),
|
|
55
|
-
React.createElement(SeatSectionMobile, { seatTypes: seatTypes, isSoldOut: isSoldOut, isPeru: isPeru, seatPriceColor: seatPriceColor, currencySign: currencySign, availableSeats: availableSeats, removeDuplicateSeats: removeDuplicateSeats, serviceItem: serviceItem })));
|
|
55
|
+
React.createElement(SeatSectionMobile, { seatTypes: seatTypes, isSoldOut: isSoldOut, isPeru: isPeru, seatPriceColor: seatPriceColor, currencySign: currencySign, availableSeats: availableSeats, removeDuplicateSeats: removeDuplicateSeats, serviceItem: serviceItem, tooltipBgColor: tooltipBgColor })));
|
|
56
56
|
}
|
|
57
57
|
export default DateTimeSectionMobile;
|
|
@@ -7,6 +7,23 @@ function ExpandedDropdownMobile({ serviceItem, isPeru, petSeatInfo, petFriendlyA
|
|
|
7
7
|
opacity: isSoldOut ? 0.5 : 1,
|
|
8
8
|
} },
|
|
9
9
|
React.createElement("div", { className: "flex flex-col gap-[8px] text-[11px] min-[420px]:text-[12px] text-[#464647]", style: { lineHeight: 1.6 } },
|
|
10
|
+
isPeru ? null : isChangeTicket ? (React.createElement("div", { className: "flex gap-[6px]" },
|
|
11
|
+
React.createElement("span", { style: { marginTop: "2px" } }, "\u2022"),
|
|
12
|
+
React.createElement("span", null,
|
|
13
|
+
React.createElement("span", { className: "bold-text" }, "Pasaje flexible:"),
|
|
14
|
+
" Tu pasaje puede ser cambiado de manera online",
|
|
15
|
+
" ",
|
|
16
|
+
React.createElement("span", { className: "bold-text" },
|
|
17
|
+
"hasta ",
|
|
18
|
+
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.change_ticket_hours) || 6,
|
|
19
|
+
" horas antes"),
|
|
20
|
+
" ",
|
|
21
|
+
"de la salida del bus. El monto ser\u00E1 reembolsado a tu billetera kupospay."))) : (React.createElement("div", { className: "flex gap-[8px] " },
|
|
22
|
+
React.createElement("span", { style: { marginTop: "2px" } }, "\u2022"),
|
|
23
|
+
React.createElement("span", null,
|
|
24
|
+
React.createElement("span", null,
|
|
25
|
+
React.createElement("span", { className: "bold-text" }, "Pasaje flexible:"),
|
|
26
|
+
" Esta empresa no permite cambios de pasajes")))),
|
|
10
27
|
petSeatInfo && Object.keys(petSeatInfo).length > 0 ? (React.createElement("div", { className: "flex items-center" },
|
|
11
28
|
React.createElement("div", { className: `relative group cursor-default ` },
|
|
12
29
|
React.createElement("div", { className: "flex items-center" },
|
|
@@ -24,23 +41,6 @@ function ExpandedDropdownMobile({ serviceItem, isPeru, petSeatInfo, petFriendlyA
|
|
|
24
41
|
React.createElement("span", { className: "bold-text" }, "Pol\u00EDticas de anulaci\u00F3n:"),
|
|
25
42
|
" Tu pasaje puede ser anulado de forma online",
|
|
26
43
|
React.createElement("span", { className: "bold-text" }, " hasta 4 horas antes"),
|
|
27
|
-
" antes de la salida del bus."))
|
|
28
|
-
isPeru ? null : isChangeTicket ? (React.createElement("div", { className: "flex gap-[6px]" },
|
|
29
|
-
React.createElement("span", { style: { marginTop: "2px" } }, "\u2022"),
|
|
30
|
-
React.createElement("span", null,
|
|
31
|
-
React.createElement("span", { className: "bold-text" }, "Pol\u00EDticas de cambios:"),
|
|
32
|
-
" Tu pasaje puede ser cambiado de manera online",
|
|
33
|
-
" ",
|
|
34
|
-
React.createElement("span", { className: "bold-text" },
|
|
35
|
-
"hasta ",
|
|
36
|
-
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.change_ticket_hours) || 6,
|
|
37
|
-
" horas antes"),
|
|
38
|
-
" ",
|
|
39
|
-
"de la salida del bus. El monto ser\u00E1 reembolsado a tu billetera kupospay."))) : (React.createElement("div", { className: "flex gap-[8px] " },
|
|
40
|
-
React.createElement("span", { style: { marginTop: "2px" } }, "\u2022"),
|
|
41
|
-
React.createElement("span", null,
|
|
42
|
-
React.createElement("span", null,
|
|
43
|
-
React.createElement("span", { className: "bold-text" }, "Pol\u00EDtica de cambios:"),
|
|
44
|
-
" Esta empresa no permite cambios de pasajes")))))));
|
|
44
|
+
" antes de la salida del bus.")))));
|
|
45
45
|
}
|
|
46
46
|
export default ExpandedDropdownMobile;
|
|
@@ -13,6 +13,7 @@ interface SeatSectionMobileProps {
|
|
|
13
13
|
availableSeats: number;
|
|
14
14
|
removeDuplicateSeats?: boolean;
|
|
15
15
|
serviceItem?: any;
|
|
16
|
+
tooltipBgColor?: string;
|
|
16
17
|
}
|
|
17
|
-
declare function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, }: SeatSectionMobileProps): React.ReactElement;
|
|
18
|
+
declare function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, }: SeatSectionMobileProps): React.ReactElement;
|
|
18
19
|
export default SeatSectionMobile;
|
|
@@ -42,8 +42,8 @@ const getUniqueSeats = (data, limit) => {
|
|
|
42
42
|
.sort((a, b) => a.fare - b.fare)
|
|
43
43
|
.slice(0, limit);
|
|
44
44
|
};
|
|
45
|
-
function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, }) {
|
|
46
|
-
var _a, _b, _c;
|
|
45
|
+
function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPriceColor, currencySign, availableSeats, removeDuplicateSeats, serviceItem, tooltipBgColor, }) {
|
|
46
|
+
var _a, _b, _c, _d, _e;
|
|
47
47
|
const hasMultipleTypes = ((_a = seatTypesData === null || seatTypesData === void 0 ? void 0 : seatTypesData.length) !== null && _a !== void 0 ? _a : 0) > 2;
|
|
48
48
|
const getFare = (fare) => {
|
|
49
49
|
if (removeDuplicateSeats && availableSeats <= 0 && !isPeru) {
|
|
@@ -59,10 +59,6 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
59
59
|
return null;
|
|
60
60
|
return filtered.reduce((min, item) => (item.fare < min ? item.fare : min), filtered[0].fare);
|
|
61
61
|
};
|
|
62
|
-
const getHighestFare = () => {
|
|
63
|
-
var _a;
|
|
64
|
-
return (((_a = seatTypesData === null || seatTypesData === void 0 ? void 0 : seatTypesData.filter((item) => !EXCEPTIONS.includes(item.label))) === null || _a === void 0 ? void 0 : _a.reduce((max, item) => (item.fare > max ? item.fare : max), 0)) || 0);
|
|
65
|
-
};
|
|
66
62
|
const renderPeruSeats = () => {
|
|
67
63
|
const lowestFare = getLowestFare();
|
|
68
64
|
if (lowestFare === null)
|
|
@@ -92,17 +88,33 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
|
|
|
92
88
|
? getUniqueSeats(seatTypesData, 3)
|
|
93
89
|
: (_c = (_b = seatTypesData === null || seatTypesData === void 0 ? void 0 : seatTypesData.filter((item) => getFilteredSeats(item.label))) === null || _b === void 0 ? void 0 : _b.sort((a, b) => a.fare - b.fare)) === null || _c === void 0 ? void 0 : _c.slice(0, 2);
|
|
94
90
|
const discountedSeats = seats === null || seats === void 0 ? void 0 : seats.map((seat) => (Object.assign(Object.assign({}, seat), commonService.calculateDiscountedPrice(seat.fare, serviceItem))));
|
|
95
|
-
const highestOriginalPrice = Math.max(...((discountedSeats === null || discountedSeats === void 0 ? void 0 : discountedSeats.map((s) => s.originalPrice)) || [0]));
|
|
96
91
|
const hasDiscount = discountedSeats === null || discountedSeats === void 0 ? void 0 : discountedSeats.some((s) => s.originalPrice !== s.discountedPrice);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
92
|
+
const discountSeat = (_d = discountedSeats === null || discountedSeats === void 0 ? void 0 : discountedSeats.filter((seat) => !EXCEPTIONS.includes(seat.label))) === null || _d === void 0 ? void 0 : _d.sort((a, b) => a.discountedPrice - b.discountedPrice)[0];
|
|
93
|
+
const discountValue = (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discount_type) === "percentage" &&
|
|
94
|
+
typeof (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discount_value) === "number"
|
|
95
|
+
? Math.round(serviceItem.discount_value)
|
|
96
|
+
: null;
|
|
97
|
+
return (React.createElement("div", { className: "content-center relative", style: { width: "40%" } }, hasDiscount && discountSeat ? (React.createElement("div", { className: "relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] " },
|
|
98
|
+
discountValue != null && (React.createElement("div", { className: "absolute -top-[18px] right-[0px]", style: {
|
|
99
|
+
animation: "pulse-zoom 2s ease-in-out infinite",
|
|
103
100
|
} },
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
React.createElement("span", { className: "rounded-[100px] px-[8px] text-[12px] bold-text leading-[20px] text-[#fff]", style: {
|
|
102
|
+
backgroundColor: tooltipBgColor,
|
|
103
|
+
} },
|
|
104
|
+
discountValue,
|
|
105
|
+
"% OFF"))),
|
|
106
|
+
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-[#c2c2c2]" }, "Antes"),
|
|
107
|
+
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-[#9f9f9f] line-through text-right" }, commonService.currency(discountSeat.originalPrice, currencySign)),
|
|
108
|
+
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[24px]", style: { color: isSoldOut ? "#bbb" : "#464647" } }, "Desde"),
|
|
109
|
+
React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: { color: isSoldOut ? "#bbb" : "#ff5964" } },
|
|
110
|
+
((_e = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.icons) === null || _e === void 0 ? void 0 : _e.fireIcon) ? (React.createElement("img", { src: serviceItem.icons.fireIcon, alt: "discount", className: "h-[16px] w-[16px] object-contain", style: { filter: isSoldOut ? "grayscale" : "" } })) : null,
|
|
111
|
+
commonService.currency(discountSeat.discountedPrice, currencySign)),
|
|
112
|
+
isSoldOut ? (React.createElement("span", { className: "col-span-2 min-[420]:text-[13px] text-right text-[12px] text-[#ccc]" }, "Agotado")) : null)) : (React.createElement("div", { className: "flex flex-col justify-between h-[2.5rem] ", style: {
|
|
113
|
+
gap: isSoldOut ? "0px" : "5px",
|
|
114
|
+
justifyContent: hasMultipleTypes ? "space-between" : "center",
|
|
115
|
+
} },
|
|
116
|
+
renderSeats(),
|
|
117
|
+
isSoldOut ? (React.createElement("div", { className: "flex justify-end" },
|
|
118
|
+
React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] text-[#ccc]" }, "Agotado"))) : null))));
|
|
107
119
|
}
|
|
108
120
|
export default SeatSectionMobile;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
interface ServiceBadgesMobileProps {
|
|
3
|
+
showTopLabel?: string;
|
|
4
|
+
isSoldOut: boolean;
|
|
5
|
+
colors: any;
|
|
6
|
+
renderIcon: (iconKey: string, size?: string) => React.ReactNode;
|
|
7
|
+
translation?: {
|
|
8
|
+
directService?: string;
|
|
9
|
+
};
|
|
10
|
+
serviceItem: {
|
|
11
|
+
is_direct_trip?: boolean;
|
|
12
|
+
train_type_label?: string;
|
|
13
|
+
};
|
|
14
|
+
isConexion?: boolean;
|
|
15
|
+
}
|
|
16
|
+
declare const ServiceBadgesMobile: React.FC<ServiceBadgesMobileProps>;
|
|
17
|
+
export default ServiceBadgesMobile;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
const ServiceBadgesMobile = ({ showTopLabel, isSoldOut, colors, renderIcon, serviceItem, isConexion, }) => {
|
|
3
|
+
return (React.createElement("div", { className: "absolute -top-[9px] left-0 w-full flex items-center justify-end gap-[12px] pr-[20px] z-10" },
|
|
4
|
+
showTopLabel && (React.createElement("div", { className: `flex items-center gap-[2px] py-[4px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20`, style: {
|
|
5
|
+
backgroundColor: "#fff",
|
|
6
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
7
|
+
color: colors.topLabelColor,
|
|
8
|
+
} },
|
|
9
|
+
React.createElement("div", { className: isSoldOut ? "grayscale" : "" }, renderIcon("specialDeparture", "12px")),
|
|
10
|
+
React.createElement("div", { style: {
|
|
11
|
+
color: colors.topLabelColor,
|
|
12
|
+
} }, showTopLabel))),
|
|
13
|
+
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.is_direct_trip) && (React.createElement("div", { className: `flex items-center gap-[2px] py-[5px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20`, style: {
|
|
14
|
+
backgroundColor: "#fff",
|
|
15
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
16
|
+
color: colors.topLabelColor,
|
|
17
|
+
} },
|
|
18
|
+
renderIcon("directo", "12px"),
|
|
19
|
+
React.createElement("div", { className: "ml-[5px]" }, "Directo"))),
|
|
20
|
+
isConexion && (React.createElement("div", { className: `flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[11px] z-20`, style: {
|
|
21
|
+
backgroundColor: "#fff",
|
|
22
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
23
|
+
color: colors.topLabelColor,
|
|
24
|
+
} },
|
|
25
|
+
renderIcon("airportIcon", "14px"),
|
|
26
|
+
React.createElement("div", null, "Conexi\u00F3n"))),
|
|
27
|
+
(serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.train_type_label) === "Tren Express (Nuevo)" && (React.createElement("div", { className: `flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20`, style: {
|
|
28
|
+
backgroundColor: "#fff",
|
|
29
|
+
border: `1px solid ${colors.topLabelColor}`,
|
|
30
|
+
color: colors.topLabelColor,
|
|
31
|
+
} },
|
|
32
|
+
renderIcon("directo", "12px"),
|
|
33
|
+
React.createElement("div", null, "Tren Express")))));
|
|
34
|
+
};
|
|
35
|
+
export default ServiceBadgesMobile;
|
|
@@ -17,5 +17,12 @@ declare const commonService: {
|
|
|
17
17
|
originalPrice: number;
|
|
18
18
|
discountedPrice: number;
|
|
19
19
|
};
|
|
20
|
+
startViewerCount: (node: HTMLSpanElement | null, viewersConfig?: {
|
|
21
|
+
min: number;
|
|
22
|
+
max: number;
|
|
23
|
+
interval?: number;
|
|
24
|
+
}) => void;
|
|
25
|
+
startCountdown: (node: HTMLSpanElement | null, countdownSeconds?: number) => void;
|
|
26
|
+
startComprandoCount: (node: HTMLSpanElement | null, min?: number, max?: number) => void;
|
|
20
27
|
};
|
|
21
28
|
export default commonService;
|
|
@@ -284,5 +284,66 @@ const commonService = {
|
|
|
284
284
|
const discountedPrice = Math.max(0, price - finalDiscount);
|
|
285
285
|
return { originalPrice: price, discountedPrice };
|
|
286
286
|
},
|
|
287
|
+
startViewerCount: (node, viewersConfig) => {
|
|
288
|
+
if (!node || !viewersConfig)
|
|
289
|
+
return;
|
|
290
|
+
const prevId = node.dataset.viewerId;
|
|
291
|
+
if (prevId)
|
|
292
|
+
clearInterval(Number(prevId));
|
|
293
|
+
const { min, max, interval = 5000 } = viewersConfig;
|
|
294
|
+
const clamp = (v) => Math.min(max, Math.max(min, v));
|
|
295
|
+
const initialValue = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
296
|
+
node.textContent = String(initialValue);
|
|
297
|
+
const id = setInterval(() => {
|
|
298
|
+
const current = Number(node.textContent) || initialValue;
|
|
299
|
+
const delta = Math.ceil(current * 0.2);
|
|
300
|
+
const next = current + Math.floor(Math.random() * (2 * delta + 1)) - delta;
|
|
301
|
+
node.textContent = String(clamp(Math.round(next)));
|
|
302
|
+
}, interval);
|
|
303
|
+
node.dataset.viewerId = String(id);
|
|
304
|
+
},
|
|
305
|
+
startCountdown: (node, countdownSeconds = 599) => {
|
|
306
|
+
if (!node)
|
|
307
|
+
return;
|
|
308
|
+
const prevId = node.dataset.countdownId;
|
|
309
|
+
if (prevId)
|
|
310
|
+
clearInterval(Number(prevId));
|
|
311
|
+
let remaining = countdownSeconds * 1000; // Convert to milliseconds
|
|
312
|
+
const formatTime = (totalMs) => {
|
|
313
|
+
const m = Math.floor(totalMs / 60000);
|
|
314
|
+
const s = Math.floor((totalMs % 60000) / 1000);
|
|
315
|
+
const ms = Math.floor((totalMs % 1000) / 10); // Show 2 digits for milliseconds
|
|
316
|
+
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}:${String(ms).padStart(2, "0")}`;
|
|
317
|
+
};
|
|
318
|
+
node.textContent = formatTime(remaining);
|
|
319
|
+
const id = setInterval(() => {
|
|
320
|
+
remaining -= 100; // Decrease by 100ms
|
|
321
|
+
if (remaining <= 0) {
|
|
322
|
+
remaining = countdownSeconds * 1000;
|
|
323
|
+
}
|
|
324
|
+
node.textContent = formatTime(remaining);
|
|
325
|
+
}, 100); // Update every 100ms
|
|
326
|
+
node.dataset.countdownId = String(id);
|
|
327
|
+
},
|
|
328
|
+
startComprandoCount: (node, min = 4, max = 16) => {
|
|
329
|
+
if (!node)
|
|
330
|
+
return;
|
|
331
|
+
const prevId = node.dataset.comprandoId;
|
|
332
|
+
if (prevId)
|
|
333
|
+
clearInterval(Number(prevId));
|
|
334
|
+
const initialValue = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
335
|
+
node.textContent = String(initialValue);
|
|
336
|
+
const id = setInterval(() => {
|
|
337
|
+
const current = Number(node.textContent) || initialValue;
|
|
338
|
+
const changePercent = 0.05; // 5% change
|
|
339
|
+
const change = Math.ceil(current * changePercent);
|
|
340
|
+
const direction = Math.random() > 0.5 ? 1 : -1;
|
|
341
|
+
let next = current + (change * direction);
|
|
342
|
+
// Clamp within min and max
|
|
343
|
+
next = Math.min(max, Math.max(min, next));
|
|
344
|
+
node.textContent = String(next);
|
|
345
|
+
}, 5000); // Update every 5 seconds
|
|
346
|
+
node.dataset.comprandoId = String(id);
|
|
347
|
+
},
|
|
287
348
|
};
|
|
288
349
|
export default commonService;
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"nm":"Main Scene","h":260.03,"w":256,"meta":{"g":"@lottiefiles/creator@1.89.0"},"layers":[{"ty":4,"nm":"circle 3","sr":1,"st":12,"op":91,"ip":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[-96.841,-18.544,0]},"s":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[1000,1000],"t":2},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[600,600],"t":28},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[400,400],"t":40},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[600,600],"t":53},{"s":[1000,1000],"t":78}]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[128,130.015]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[100],"t":2},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[70],"t":28},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[20],"t":40},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[70],"t":53},{"s":[100],"t":78}]}},"shapes":[{"ty":"gr","nm":"Ellipse 1","it":[{"ty":"el","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0]},"s":{"a":0,"k":[23.352,23.352]}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[-96.841,-18.544]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":1}],"v":"5.7.0","fr":29.97,"op":84,"ip":0,"assets":[]}
|