kupos-ui-components-lib 9.0.4 → 9.0.6
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/README copy.md +223 -67
- package/dist/assets/images/anims/service_list/bomb.json +1 -0
- package/dist/assets/images/anims/service_list/directo.json +1 -1
- package/dist/assets/images/anims/service_list/priority_stage.json +1 -1
- package/dist/components/ServiceItem/ExpandedDropdown.d.ts +19 -0
- package/dist/components/ServiceItem/ExpandedDropdown.js +28 -0
- package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemDesktop.js +125 -262
- package/dist/components/ServiceItem/ServiceItemMobile.js +44 -291
- package/dist/components/ServiceItem/mobileTypes.d.ts +3 -0
- package/dist/components/ServiceItem/types.d.ts +7 -0
- package/dist/styles.css +67 -12
- package/dist/ui/AmenitiesBlock.js +60 -66
- package/dist/ui/BottomAmenities/BottomAmenities.d.ts +26 -0
- package/dist/ui/BottomAmenities/BottomAmenities.js +22 -0
- package/dist/ui/DurationBlock.js +2 -2
- package/dist/ui/ExpendedDropDown/ExpandedDropdown.d.ts +19 -0
- package/dist/ui/ExpendedDropDown/ExpandedDropdown.js +27 -0
- package/dist/ui/FlexibleBlock.js +2 -4
- package/dist/ui/KuposButton/KuposButton.d.ts +12 -0
- package/dist/ui/KuposButton/KuposButton.js +12 -0
- package/dist/ui/PetBlock.js +1 -3
- package/dist/ui/RatingBlock.js +6 -2
- package/dist/ui/SeatSection/SeatSection.d.ts +17 -0
- package/dist/ui/SeatSection/SeatSection.js +92 -0
- package/dist/ui/TopAmenities/TopAmenities.d.ts +12 -0
- package/dist/ui/TopAmenities/TopAmenities.js +32 -0
- package/dist/ui/mobileweb/BottomAmenitiesMobile.d.ts +23 -0
- package/dist/ui/mobileweb/BottomAmenitiesMobile.js +37 -0
- package/dist/ui/mobileweb/DateTimeSectionMobile.d.ts +23 -0
- package/dist/ui/mobileweb/DateTimeSectionMobile.js +57 -0
- package/dist/ui/mobileweb/SeatSectionMobile.d.ts +17 -0
- package/dist/ui/mobileweb/SeatSectionMobile.js +100 -0
- package/dist/ui/mobileweb/TopAmenitieMobile.d.ts +10 -0
- package/dist/ui/mobileweb/TopAmenitieMobile.js +35 -0
- package/package.json +1 -1
- package/src/assets/images/anims/service_list/bomb.json +1 -0
- package/src/assets/images/anims/service_list/directo.json +1 -1
- package/src/assets/images/anims/service_list/priority_stage.json +1 -1
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +222 -465
- package/src/components/ServiceItem/ServiceItemMobile.tsx +120 -501
- package/src/components/ServiceItem/mobileTypes.ts +3 -0
- package/src/components/ServiceItem/types.ts +7 -0
- package/src/ui/AmenitiesBlock.tsx +115 -97
- package/src/ui/BottomAmenities/BottomAmenities.tsx +109 -0
- package/src/ui/DurationBlock.tsx +2 -2
- package/src/ui/ExpendedDropDown/ExpandedDropdown.tsx +85 -0
- package/src/ui/FlexibleBlock.tsx +3 -3
- package/src/ui/KuposButton/KuposButton.tsx +48 -0
- package/src/ui/PetBlock.tsx +2 -2
- package/src/ui/RatingBlock.tsx +16 -4
- package/src/ui/SeatSection/SeatSection.tsx +187 -0
- package/src/ui/TopAmenities/TopAmenities.tsx +82 -0
- package/src/ui/mobileweb/BottomAmenitiesMobile.tsx +168 -0
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +192 -0
- package/src/ui/mobileweb/SeatSectionMobile.tsx +256 -0
- package/src/ui/mobileweb/TopAmenitieMobile.tsx +82 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from "react";
|
|
2
2
|
import { ServiceItemProps } from "./types";
|
|
3
3
|
import DateService from "../../utils/DateService";
|
|
4
4
|
import CommonService from "../../utils/CommonService";
|
|
5
|
-
import RatingHover from "./RatingHover";
|
|
6
5
|
import ModalEventManager from "../../utils/ModalEventManager";
|
|
7
6
|
import InternationalServicePopupBody from "../InternationalServicePopupBody";
|
|
8
7
|
import LottiePlayer from "../../assets/LottiePlayer";
|
|
9
8
|
import PeruServiceItemDesktop from "./PeruServiceItemDesktop";
|
|
9
|
+
import ExpandedDropdown from "../../ui/ExpendedDropDown/ExpandedDropdown";
|
|
10
10
|
import promoAnimation from "../../assets/images/anims/service_list/promocion.json";
|
|
11
11
|
import flexibleAnimation from "../../assets/images/anims/service_list/flexible.json";
|
|
12
12
|
import locationAnimation from "../../assets/images/anims/service_list/location.json";
|
|
@@ -18,22 +18,13 @@ import pullmanFlexibleAnimation from "../../assets/images/anims/service_list/pul
|
|
|
18
18
|
import pullmanPetFriendlyAnimation from "../../assets/images/anims/service_list/pullmanPetFriendly.json";
|
|
19
19
|
import pullmanLocationAnimation from "../../assets/images/anims/service_list/pullmanLocation.json";
|
|
20
20
|
import pullmanPriorityStageAnimation from "../../assets/images/anims/service_list/pullmanPriorityStage.json";
|
|
21
|
-
import pullmanPromoAnimation from "../../assets/images/anims/service_list/promocion.json";
|
|
22
|
-
import pullmanDirectoAnimation from "../../assets/images/anims/service_list/directo.json";
|
|
23
21
|
|
|
24
22
|
import opsitesFlexibleAnimation from "../../assets/images/anims/service_list/opsitesFlexible.json";
|
|
25
23
|
import opsitesPetFriendlyAnimation from "../../assets/images/anims/service_list/opsitesPetFriendly.json";
|
|
26
24
|
import opsitesLocationAnimation from "../../assets/images/anims/service_list/opsitesLocation.json";
|
|
27
25
|
import opsitesPriorityStageAnimation from "../../assets/images/anims/service_list/opsitesPriorityStage.json";
|
|
28
|
-
import opsitesPromoAnimation from "../../assets/images/anims/service_list/promocion.json";
|
|
29
|
-
import opsitesDirectoAnimation from "../../assets/images/anims/service_list/directo.json";
|
|
30
26
|
|
|
31
|
-
import
|
|
32
|
-
import linatalPromoAnimation from "../../assets/images/anims/service_list/promocion.json";
|
|
33
|
-
import linatalDirectoAnimation from "../../assets/images/anims/service_list/directo.json";
|
|
34
|
-
import linatalPriorityStageAnimation from "../../assets/images/anims/service_list/priority_stage.json";
|
|
35
|
-
import linatalPetFriendlyAnimation from "../../assets/images/anims/service_list/pet_friendly.json";
|
|
36
|
-
import linatalLocationAnimation from "../../assets/images/anims/service_list/location.json";
|
|
27
|
+
import bombAnimation from "../../assets/images/anims/service_list/bomb.json";
|
|
37
28
|
|
|
38
29
|
import RatingBlock from "../../ui/RatingBlock";
|
|
39
30
|
import DurationBlock from "../../ui/DurationBlock";
|
|
@@ -41,9 +32,61 @@ import PetBlock from "../../ui/PetBlock";
|
|
|
41
32
|
import FlexibleBlock from "../../ui/FlexibleBlock";
|
|
42
33
|
import AmenitiesBlock from "../../ui/AmenitiesBlock";
|
|
43
34
|
import StageTooltip from "../../ui/StagesTooltip";
|
|
35
|
+
import KuposButton from "../../ui/KuposButton/KuposButton";
|
|
36
|
+
import TopAmenities from "../../ui/TopAmenities/TopAmenities";
|
|
37
|
+
import BottomAmenities from "../../ui/BottomAmenities/BottomAmenities";
|
|
38
|
+
import SeatSection from "../../ui/SeatSection/SeatSection";
|
|
44
39
|
|
|
45
40
|
const SEAT_EXCEPTIONS = ["Asiento mascota"];
|
|
46
41
|
|
|
42
|
+
const ANIMATION_MAP: Record<string, Record<string, any>> = {
|
|
43
|
+
promoAnim: {
|
|
44
|
+
kupos: promoAnimation,
|
|
45
|
+
},
|
|
46
|
+
locationAnim: {
|
|
47
|
+
kupos: locationAnimation,
|
|
48
|
+
pullman: pullmanLocationAnimation,
|
|
49
|
+
opsites: opsitesLocationAnimation,
|
|
50
|
+
},
|
|
51
|
+
directoAnim: {
|
|
52
|
+
kupos: directoAnimation,
|
|
53
|
+
},
|
|
54
|
+
petFriendlyAnim: {
|
|
55
|
+
kupos: petFriendlyAnimation,
|
|
56
|
+
pullman: pullmanPetFriendlyAnimation,
|
|
57
|
+
opsites: opsitesPetFriendlyAnimation,
|
|
58
|
+
},
|
|
59
|
+
priorityStageAnim: {
|
|
60
|
+
kupos: priorityStageAnimation,
|
|
61
|
+
pullman: pullmanPriorityStageAnimation,
|
|
62
|
+
opsites: opsitesPriorityStageAnimation,
|
|
63
|
+
},
|
|
64
|
+
flexibleIcon: {
|
|
65
|
+
kupos: flexibleAnimation,
|
|
66
|
+
pullman: pullmanFlexibleAnimation,
|
|
67
|
+
opsites: opsitesFlexibleAnimation,
|
|
68
|
+
},
|
|
69
|
+
bombAnimation: {
|
|
70
|
+
kupos: bombAnimation,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const convertTo24Hour = (depTime: string): string => {
|
|
75
|
+
const hasAM = depTime.includes("AM");
|
|
76
|
+
const hasPM = depTime.includes("PM");
|
|
77
|
+
const [timePart] = depTime.split(/AM|PM/).map((part) => part.trim());
|
|
78
|
+
const [hour, minute] = timePart.split(":").map(Number);
|
|
79
|
+
const pad = (n: number) => (n < 10 ? "0" + n : String(n));
|
|
80
|
+
|
|
81
|
+
if (hasAM) {
|
|
82
|
+
return `${pad(hour === 12 ? 0 : hour)}:${pad(minute)}`;
|
|
83
|
+
}
|
|
84
|
+
if (hasPM) {
|
|
85
|
+
return `${hour === 12 ? hour : hour + 12}:${pad(minute)}`;
|
|
86
|
+
}
|
|
87
|
+
return timePart;
|
|
88
|
+
};
|
|
89
|
+
|
|
47
90
|
function ServiceItemPB({
|
|
48
91
|
serviceItem,
|
|
49
92
|
onBookButtonPress,
|
|
@@ -71,48 +114,12 @@ function ServiceItemPB({
|
|
|
71
114
|
t = (key: string) => key,
|
|
72
115
|
siteType,
|
|
73
116
|
isAllinBus,
|
|
117
|
+
isExpand,
|
|
118
|
+
setIsExpand,
|
|
119
|
+
coachKey,
|
|
74
120
|
}: ServiceItemProps & { currencySign?: string }): React.ReactElement {
|
|
75
|
-
const animationMap: Record<string, Record<string, any>> = {
|
|
76
|
-
promoAnim: {
|
|
77
|
-
kupos: promoAnimation,
|
|
78
|
-
pullman: pullmanPromoAnimation,
|
|
79
|
-
opsites: opsitesPromoAnimation,
|
|
80
|
-
linatal: linatalPromoAnimation,
|
|
81
|
-
},
|
|
82
|
-
locationAnim: {
|
|
83
|
-
kupos: locationAnimation,
|
|
84
|
-
pullman: pullmanLocationAnimation,
|
|
85
|
-
opsites: opsitesLocationAnimation,
|
|
86
|
-
linatal: linatalLocationAnimation,
|
|
87
|
-
},
|
|
88
|
-
directoAnim: {
|
|
89
|
-
kupos: directoAnimation,
|
|
90
|
-
pullman: pullmanDirectoAnimation,
|
|
91
|
-
opsites: opsitesDirectoAnimation,
|
|
92
|
-
linatal: linatalDirectoAnimation,
|
|
93
|
-
},
|
|
94
|
-
petFriendlyAnim: {
|
|
95
|
-
kupos: petFriendlyAnimation,
|
|
96
|
-
pullman: pullmanPetFriendlyAnimation,
|
|
97
|
-
opsites: opsitesPetFriendlyAnimation,
|
|
98
|
-
linatal: linatalPetFriendlyAnimation,
|
|
99
|
-
},
|
|
100
|
-
priorityStageAnim: {
|
|
101
|
-
kupos: priorityStageAnimation,
|
|
102
|
-
pullman: pullmanPriorityStageAnimation,
|
|
103
|
-
opsites: opsitesPriorityStageAnimation,
|
|
104
|
-
linatal: linatalPriorityStageAnimation,
|
|
105
|
-
},
|
|
106
|
-
flexibleIcon: {
|
|
107
|
-
kupos: flexibleAnimation,
|
|
108
|
-
pullman: pullmanFlexibleAnimation,
|
|
109
|
-
opsites: opsitesFlexibleAnimation,
|
|
110
|
-
linatal: linatalFlexibleAnimation,
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
|
|
114
121
|
const getAnimationIcon = (icon: string) => {
|
|
115
|
-
const animation =
|
|
122
|
+
const animation = ANIMATION_MAP[icon];
|
|
116
123
|
if (!animation) return null;
|
|
117
124
|
return animation[siteType] ?? animation.kupos;
|
|
118
125
|
};
|
|
@@ -151,9 +158,7 @@ function ServiceItemPB({
|
|
|
151
158
|
style={{
|
|
152
159
|
filter: color === "white" ? "brightness(0) invert(1)" : "",
|
|
153
160
|
}}
|
|
154
|
-
className=
|
|
155
|
-
moreAnemities ? "w-[16px] h-[16px]" : "w-[16px] h-[16px]"
|
|
156
|
-
}`}
|
|
161
|
+
className="object-contain w-[16px] h-[16px]"
|
|
157
162
|
/>
|
|
158
163
|
);
|
|
159
164
|
};
|
|
@@ -171,6 +176,11 @@ function ServiceItemPB({
|
|
|
171
176
|
|
|
172
177
|
let isSoldOut = serviceItem.available_seats <= 0;
|
|
173
178
|
|
|
179
|
+
const showPromo = Math.random() > 0.5;
|
|
180
|
+
|
|
181
|
+
const isItemExpanded = serviceItem.id === isExpand || isExpand === true;
|
|
182
|
+
const grayscaleClass = isSoldOut ? "grayscale" : "";
|
|
183
|
+
|
|
174
184
|
const renderIcon = (iconKey: string, size: string = "14px") => {
|
|
175
185
|
const iconValue = serviceItem.icons?.[iconKey];
|
|
176
186
|
if (iconValue) {
|
|
@@ -179,7 +189,7 @@ function ServiceItemPB({
|
|
|
179
189
|
<img
|
|
180
190
|
src={iconValue}
|
|
181
191
|
alt={iconKey}
|
|
182
|
-
className={`${`w-[${size}] h-[${size}]`}
|
|
192
|
+
className={`${`w-[${size}] h-[${size}]`} `}
|
|
183
193
|
/>
|
|
184
194
|
);
|
|
185
195
|
}
|
|
@@ -187,136 +197,8 @@ function ServiceItemPB({
|
|
|
187
197
|
return null;
|
|
188
198
|
};
|
|
189
199
|
|
|
190
|
-
const getAllSeatTypes = () => {
|
|
191
|
-
if (!serviceItem?.seat_types?.length) {
|
|
192
|
-
return [{ label: "Salon cama", price: 0 }];
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
let seatTypesWithPrices = serviceItem.seat_types
|
|
196
|
-
.filter((item) => getFilteredSeats(item))
|
|
197
|
-
.map((val) => ({
|
|
198
|
-
label: val?.label,
|
|
199
|
-
price: val?.fare,
|
|
200
|
-
}));
|
|
201
|
-
|
|
202
|
-
seatTypesWithPrices.sort((a, b) => a.price - b.price);
|
|
203
|
-
|
|
204
|
-
return seatTypesWithPrices;
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const getSortedSeatTypes = () => {
|
|
208
|
-
if (!serviceItem?.seat_types?.length) {
|
|
209
|
-
return [{ label: "Salon cama", price: 0 }];
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
let seatTypesWithPrices = getAllSeatTypes();
|
|
213
|
-
const premiumIndex = seatTypesWithPrices.findIndex(
|
|
214
|
-
(item) => item.label === "Premium",
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
if (premiumIndex >= 3) {
|
|
218
|
-
seatTypesWithPrices[2] = seatTypesWithPrices[premiumIndex];
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
seatTypesWithPrices = seatTypesWithPrices.slice(0, 2);
|
|
222
|
-
|
|
223
|
-
return seatTypesWithPrices;
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
const getUniqueSeats = () => {
|
|
227
|
-
const allSeatTypes = getAllSeatTypes();
|
|
228
|
-
const seatMap = new Map();
|
|
229
|
-
|
|
230
|
-
allSeatTypes.forEach((seat) => {
|
|
231
|
-
if (SEAT_EXCEPTIONS.includes(seat.label)) return;
|
|
232
|
-
|
|
233
|
-
// Only check if the label already exists in the map, don't compare prices
|
|
234
|
-
if (!seatMap.has(seat.label)) {
|
|
235
|
-
seatMap.set(seat.label, seat);
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
return Array.from(seatMap.values());
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
const getNumberOfSeats = () => {
|
|
243
|
-
return serviceItem.seat_types.filter(
|
|
244
|
-
(val) => !SEAT_EXCEPTIONS.includes(val.label),
|
|
245
|
-
).length;
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
const getSeatNames = () => {
|
|
249
|
-
const uniqueSeats = getUniqueSeats();
|
|
250
|
-
const sortedSeatTypes = getSortedSeatTypes();
|
|
251
|
-
|
|
252
|
-
if (removeDuplicateSeats) {
|
|
253
|
-
return uniqueSeats.map((val, key: number) =>
|
|
254
|
-
SEAT_EXCEPTIONS.includes(val.label) ? null : (
|
|
255
|
-
<span
|
|
256
|
-
key={key}
|
|
257
|
-
className={`flex items-center justify-between text-[13.33px] ${
|
|
258
|
-
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
259
|
-
}`}
|
|
260
|
-
>
|
|
261
|
-
{typeof val.label === "string" || typeof val.label === "number"
|
|
262
|
-
? isPeru
|
|
263
|
-
? CommonService.truncateSeatLabel(val.label)
|
|
264
|
-
: val.label
|
|
265
|
-
: null}
|
|
266
|
-
</span>
|
|
267
|
-
),
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
return sortedSeatTypes.map((val, key: number) =>
|
|
271
|
-
SEAT_EXCEPTIONS.includes(val.label) ? null : (
|
|
272
|
-
<span
|
|
273
|
-
key={key}
|
|
274
|
-
className={`flex items-center justify-between text-[13.33px] ${
|
|
275
|
-
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
276
|
-
}`}
|
|
277
|
-
>
|
|
278
|
-
{typeof val.label === "string" || typeof val.label === "number"
|
|
279
|
-
? val.label
|
|
280
|
-
: null}
|
|
281
|
-
</span>
|
|
282
|
-
),
|
|
283
|
-
);
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
const getSeatPrice = () => {
|
|
287
|
-
const sortedSeatTypes = getSortedSeatTypes();
|
|
288
|
-
const uniqueSeats = getUniqueSeats();
|
|
289
|
-
if (removeDuplicateSeats) {
|
|
290
|
-
return uniqueSeats.map((val, key) => (
|
|
291
|
-
<span key={key}>
|
|
292
|
-
{serviceItem?.available_seats <= 0
|
|
293
|
-
? CommonService.currency(0, currencySign)
|
|
294
|
-
: CommonService.currency(val.price, currencySign)}
|
|
295
|
-
</span>
|
|
296
|
-
));
|
|
297
|
-
}
|
|
298
|
-
return sortedSeatTypes.map((val, key: number) => {
|
|
299
|
-
return SEAT_EXCEPTIONS.includes(val.label) ? null : (
|
|
300
|
-
<span key={key} className="flex items-center text-[13.33px] bold-text">
|
|
301
|
-
{typeof val.price === "string"
|
|
302
|
-
? serviceItem?.available_seats <= 0
|
|
303
|
-
? CommonService.currency(0, currencySign)
|
|
304
|
-
: CommonService.currency(val.price, currencySign)
|
|
305
|
-
: typeof val.price === "number"
|
|
306
|
-
? serviceItem?.available_seats <= 0
|
|
307
|
-
? CommonService.currency(0, currencySign)
|
|
308
|
-
: CommonService.currency(val.price, currencySign)
|
|
309
|
-
: null}
|
|
310
|
-
</span>
|
|
311
|
-
);
|
|
312
|
-
});
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
const getFilteredSeats = (item) => {
|
|
316
|
-
return item;
|
|
317
|
-
};
|
|
318
|
-
|
|
319
200
|
const checkMidnight = () => {
|
|
201
|
+
setIsExpand(null);
|
|
320
202
|
if (
|
|
321
203
|
cityOrigin?.label &&
|
|
322
204
|
cityDestination?.label &&
|
|
@@ -395,56 +277,37 @@ function ServiceItemPB({
|
|
|
395
277
|
),
|
|
396
278
|
});
|
|
397
279
|
return;
|
|
398
|
-
} else {
|
|
399
|
-
onBookButtonPress();
|
|
400
280
|
}
|
|
281
|
+
|
|
282
|
+
onBookButtonPress();
|
|
401
283
|
};
|
|
402
284
|
|
|
403
285
|
const depTime = serviceItem.dep_time || "";
|
|
404
|
-
|
|
405
|
-
// Extract hours and minutes and check for AM/PM
|
|
406
286
|
const hasAM = depTime.includes("AM");
|
|
407
287
|
const hasPM = depTime.includes("PM");
|
|
408
|
-
const
|
|
409
|
-
const [hour, minute] = timePart.split(":").map(Number);
|
|
410
|
-
|
|
411
|
-
// Convert to 24-hour format
|
|
412
|
-
let cleanedDepTime;
|
|
413
|
-
if (hasAM) {
|
|
414
|
-
cleanedDepTime =
|
|
415
|
-
hour === 12
|
|
416
|
-
? `00:${minute < 10 ? "0" + minute : minute}`
|
|
417
|
-
: `${hour < 10 ? "0" + hour : hour}:${
|
|
418
|
-
minute < 10 ? "0" + minute : minute
|
|
419
|
-
}`;
|
|
420
|
-
} else if (hasPM) {
|
|
421
|
-
cleanedDepTime =
|
|
422
|
-
hour === 12
|
|
423
|
-
? `${hour}:${minute < 10 ? "0" + minute : minute}`
|
|
424
|
-
: `${hour + 12}:${minute < 10 ? "0" + minute : minute}`;
|
|
425
|
-
} else {
|
|
426
|
-
cleanedDepTime = timePart;
|
|
427
|
-
}
|
|
288
|
+
const cleanedDepTime = convertTo24Hour(depTime);
|
|
428
289
|
|
|
429
290
|
const items = [
|
|
430
291
|
{
|
|
431
|
-
key: "
|
|
432
|
-
width: "
|
|
292
|
+
key: "amenities",
|
|
293
|
+
width: "20%",
|
|
294
|
+
condition: true,
|
|
433
295
|
render: (
|
|
434
|
-
<
|
|
435
|
-
showRating={showRating}
|
|
296
|
+
<AmenitiesBlock
|
|
436
297
|
serviceItem={serviceItem}
|
|
298
|
+
metaData={metaData}
|
|
437
299
|
isSoldOut={isSoldOut}
|
|
438
300
|
colors={colors}
|
|
439
|
-
|
|
440
|
-
|
|
301
|
+
isPeru={isPeru}
|
|
302
|
+
getAnimationIcon={getAnimationIcon}
|
|
303
|
+
getAmenityName={CommonService.getAmenityName}
|
|
304
|
+
SvgAmenities={SvgAmenities}
|
|
441
305
|
/>
|
|
442
306
|
),
|
|
443
307
|
},
|
|
444
|
-
|
|
445
308
|
{
|
|
446
309
|
key: "duration",
|
|
447
|
-
width: "
|
|
310
|
+
width: "12%",
|
|
448
311
|
condition: serviceItem.duration,
|
|
449
312
|
render: (
|
|
450
313
|
<DurationBlock
|
|
@@ -457,6 +320,22 @@ function ServiceItemPB({
|
|
|
457
320
|
),
|
|
458
321
|
},
|
|
459
322
|
|
|
323
|
+
{
|
|
324
|
+
key: "directo",
|
|
325
|
+
width: "12%",
|
|
326
|
+
condition: serviceItem?.is_direct_trip,
|
|
327
|
+
render: (
|
|
328
|
+
<div className="flex items-center gap-[10px] text-[12.5px] z-10 mt-[6px]">
|
|
329
|
+
<LottiePlayer
|
|
330
|
+
animationData={getAnimationIcon("directoAnim")}
|
|
331
|
+
width="14px"
|
|
332
|
+
height="14px"
|
|
333
|
+
/>
|
|
334
|
+
<div>{translation?.directService}</div>
|
|
335
|
+
</div>
|
|
336
|
+
),
|
|
337
|
+
},
|
|
338
|
+
|
|
460
339
|
{
|
|
461
340
|
key: "pet",
|
|
462
341
|
width: "20%",
|
|
@@ -487,28 +366,10 @@ function ServiceItemPB({
|
|
|
487
366
|
/>
|
|
488
367
|
),
|
|
489
368
|
},
|
|
490
|
-
|
|
491
|
-
{
|
|
492
|
-
key: "amenities",
|
|
493
|
-
width: "20%",
|
|
494
|
-
render: (
|
|
495
|
-
<AmenitiesBlock
|
|
496
|
-
serviceItem={serviceItem}
|
|
497
|
-
metaData={metaData}
|
|
498
|
-
isSoldOut={isSoldOut}
|
|
499
|
-
colors={colors}
|
|
500
|
-
isPeru={isPeru}
|
|
501
|
-
getAnimationIcon={getAnimationIcon}
|
|
502
|
-
getAmenityName={CommonService.getAmenityName}
|
|
503
|
-
SvgAmenities={SvgAmenities}
|
|
504
|
-
/>
|
|
505
|
-
),
|
|
506
|
-
},
|
|
507
369
|
];
|
|
508
370
|
|
|
509
|
-
const amenitiesItem = items.find((i) => i.key === "amenities");
|
|
510
371
|
const otherItems = items.filter(
|
|
511
|
-
(i) => i.key !== "
|
|
372
|
+
(i) => i.key !== "pet" && i.key !== "flexible" && !!i.condition,
|
|
512
373
|
);
|
|
513
374
|
|
|
514
375
|
return (
|
|
@@ -545,40 +406,77 @@ function ServiceItemPB({
|
|
|
545
406
|
<div
|
|
546
407
|
className={`relative ${
|
|
547
408
|
serviceItem.offer_text ? "mb-[55px]" : "mb-[10px]"
|
|
548
|
-
}
|
|
549
|
-
serviceItem?.is_direct_trip ||
|
|
550
|
-
serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
|
|
551
|
-
showTopLabel
|
|
552
|
-
? "mt-[24px]"
|
|
553
|
-
: "mt-[20px]"
|
|
554
|
-
} `}
|
|
409
|
+
} mt-[14px]`}
|
|
555
410
|
>
|
|
411
|
+
<TopAmenities
|
|
412
|
+
showPromo={showPromo}
|
|
413
|
+
showTopLabel={showTopLabel}
|
|
414
|
+
isSoldOut={isSoldOut}
|
|
415
|
+
priceColor={colors.priceColor}
|
|
416
|
+
buttonColor={colors.kuposButtonColor}
|
|
417
|
+
boardingIcon={renderIcon("whiteBoardingIcon", "14px")}
|
|
418
|
+
getAnimationIcon={getAnimationIcon}
|
|
419
|
+
/>
|
|
556
420
|
<div
|
|
557
|
-
className=
|
|
558
|
-
|
|
559
|
-
|
|
421
|
+
className="bg-white mx-auto relative"
|
|
422
|
+
style={{
|
|
423
|
+
border: `1px solid ${colors.priceColor}`,
|
|
424
|
+
// showPromo
|
|
425
|
+
// ? `1px solid ${colors.priceColor}`
|
|
426
|
+
// : "1px solid #ccc",
|
|
427
|
+
borderRadius:
|
|
428
|
+
// showPromo || showTopLabel ?
|
|
429
|
+
"10px 0 10px 10px",
|
|
430
|
+
// : "10px",
|
|
431
|
+
}}
|
|
560
432
|
>
|
|
561
|
-
<div
|
|
433
|
+
<div
|
|
434
|
+
// className="p-[15px] pt-[20px]"
|
|
435
|
+
className=" pt-[20px]"
|
|
436
|
+
style={{
|
|
437
|
+
padding: coachKey
|
|
438
|
+
? "15px 15px 20px 15px"
|
|
439
|
+
: "20px 15px 11px 15px",
|
|
440
|
+
}}
|
|
441
|
+
>
|
|
562
442
|
<div
|
|
563
|
-
className="grid text-[#464647] w-full [grid-template-columns:
|
|
564
|
-
|
|
443
|
+
// className="grid text-[#464647] w-full [grid-template-columns:18%_28%_2.5%_28%_15.5%] gap-x-[2%] items-center"
|
|
444
|
+
className="grid text-[#464647] w-full [grid-template-columns:22%_28%_2.5%_24%_15.5%] gap-x-[2%] items-center"
|
|
445
|
+
// style={{ marginTop: showTopLabel ? "8px" : "" }}
|
|
565
446
|
>
|
|
566
447
|
{/* OPERATOR LOGO */}
|
|
567
|
-
<div
|
|
568
|
-
|
|
448
|
+
<div
|
|
449
|
+
style={{
|
|
450
|
+
display: "flex",
|
|
451
|
+
flexDirection: "column",
|
|
452
|
+
gap: "5px",
|
|
453
|
+
}}
|
|
454
|
+
>
|
|
455
|
+
<div
|
|
456
|
+
// className="flex items-center justify-center m-[auto]"
|
|
457
|
+
className=""
|
|
458
|
+
>
|
|
569
459
|
<img
|
|
570
460
|
src={serviceItem.operator_details[0]}
|
|
571
461
|
alt="service logo"
|
|
572
|
-
className={`
|
|
462
|
+
className={`h-auto w-[150px] object-contain ${
|
|
573
463
|
isSoldOut ? "grayscale" : ""
|
|
574
464
|
}`}
|
|
575
465
|
/>
|
|
466
|
+
{isCiva ? (
|
|
467
|
+
<div className="text-[13.33px] black-text ml-2">
|
|
468
|
+
{serviceItem.operator_details[2]}
|
|
469
|
+
</div>
|
|
470
|
+
) : null}
|
|
576
471
|
</div>
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
472
|
+
<RatingBlock
|
|
473
|
+
showRating={showRating}
|
|
474
|
+
serviceItem={serviceItem}
|
|
475
|
+
isSoldOut={isSoldOut}
|
|
476
|
+
colors={colors}
|
|
477
|
+
t={t}
|
|
478
|
+
translation={translation}
|
|
479
|
+
/>
|
|
582
480
|
</div>
|
|
583
481
|
|
|
584
482
|
{/* DATE AND TIME - Grid Layout */}
|
|
@@ -602,7 +500,7 @@ function ServiceItemPB({
|
|
|
602
500
|
<img
|
|
603
501
|
src={serviceItem.icons?.origin}
|
|
604
502
|
alt="origin"
|
|
605
|
-
className={`w-[
|
|
503
|
+
className={`w-[16px] h-auto mr-[8px] ${
|
|
606
504
|
isSoldOut ? "grayscale" : ""
|
|
607
505
|
}`}
|
|
608
506
|
/>
|
|
@@ -619,7 +517,7 @@ function ServiceItemPB({
|
|
|
619
517
|
<div className="h-[20px] flex items-center">
|
|
620
518
|
<img
|
|
621
519
|
src={serviceItem.icons?.destination}
|
|
622
|
-
className={`w-[
|
|
520
|
+
className={`w-[16px] h-auto mr-[8px] ${
|
|
623
521
|
isSoldOut ? "grayscale" : ""
|
|
624
522
|
}`}
|
|
625
523
|
style={{ opacity: isSoldOut ? 0.5 : 1 }}
|
|
@@ -738,151 +636,87 @@ function ServiceItemPB({
|
|
|
738
636
|
></div>
|
|
739
637
|
{/* SEATS */}
|
|
740
638
|
<div className="content-center">
|
|
741
|
-
<
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
>
|
|
751
|
-
<div
|
|
752
|
-
className="flex flex-col justify-between"
|
|
753
|
-
style={{ gap: "10px" }}
|
|
754
|
-
>
|
|
755
|
-
{getSeatNames()}
|
|
756
|
-
</div>
|
|
757
|
-
<div
|
|
758
|
-
className="flex flex-col justify-between absolute inset-y-0 right-0 left-1/2 h-full"
|
|
759
|
-
style={{
|
|
760
|
-
color: isSoldOut ? "#c0c0c0" : colors.priceColor,
|
|
761
|
-
top: 0,
|
|
762
|
-
bottom: 0,
|
|
763
|
-
left: "clamp(60%, 65% + (100vw - 1300px) * 0.1, 65%)",
|
|
764
|
-
// left: "68%",
|
|
765
|
-
right: 0,
|
|
766
|
-
justifyContent:
|
|
767
|
-
getNumberOfSeats() < 2 || removeDuplicateSeats
|
|
768
|
-
? "center"
|
|
769
|
-
: "",
|
|
770
|
-
gap: "10px",
|
|
771
|
-
}}
|
|
772
|
-
>
|
|
773
|
-
{getSeatPrice()}
|
|
774
|
-
</div>
|
|
775
|
-
</div>
|
|
639
|
+
<SeatSection
|
|
640
|
+
seatTypes={serviceItem.seat_types}
|
|
641
|
+
availableSeats={serviceItem.available_seats}
|
|
642
|
+
isSoldOut={isSoldOut}
|
|
643
|
+
priceColor={colors.priceColor}
|
|
644
|
+
currencySign={currencySign}
|
|
645
|
+
removeDuplicateSeats={removeDuplicateSeats}
|
|
646
|
+
isPeru={isPeru}
|
|
647
|
+
/>
|
|
776
648
|
</div>
|
|
777
649
|
|
|
778
650
|
{/* BUTTON */}
|
|
779
|
-
<div>
|
|
780
|
-
<button
|
|
781
|
-
onClick={() => (!isSoldOut ? checkMidnight() : null)}
|
|
782
|
-
disabled={serviceDetailsLoading}
|
|
783
|
-
className={`w-full ${
|
|
784
|
-
serviceDetailsLoading || isSoldOut
|
|
785
|
-
? "py-[12px]"
|
|
786
|
-
: "py-[12px]"
|
|
787
|
-
} text-[13.33px] font-bold text-white rounded-[10px] border-none px-[20px] flex items-center justify-center`}
|
|
788
|
-
style={{
|
|
789
|
-
backgroundColor:
|
|
790
|
-
serviceDetailsLoading || isSoldOut
|
|
791
|
-
? "lightgray"
|
|
792
|
-
: colors.kuposButtonColor,
|
|
793
|
-
cursor:
|
|
794
|
-
serviceDetailsLoading || isSoldOut
|
|
795
|
-
? "not-allowed"
|
|
796
|
-
: "pointer",
|
|
797
|
-
}}
|
|
798
|
-
>
|
|
799
|
-
<span className="min-w-[75px] flex justify-center items-center bold-text uppercase">
|
|
800
|
-
{isSoldOut ? renderIcon("soldOutIcon", "14px") : null}
|
|
801
651
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
</div>
|
|
820
|
-
)}
|
|
821
|
-
</div>
|
|
822
|
-
) : null}
|
|
823
|
-
|
|
824
|
-
{/* <div className="flex items-center mt-[15px] border-t border-[#eee] pt-[10px]">
|
|
825
|
-
<div
|
|
826
|
-
className="grid items-center gap-[12px] w-full"
|
|
827
|
-
style={{
|
|
828
|
-
gridTemplateColumns: "30% 20% 20% 20% auto",
|
|
829
|
-
}}
|
|
830
|
-
>
|
|
831
|
-
{items
|
|
832
|
-
.sort((a, b) =>
|
|
833
|
-
a.key === "amenities"
|
|
834
|
-
? 1
|
|
835
|
-
: b.key === "amenities"
|
|
836
|
-
? -1
|
|
837
|
-
: 0,
|
|
838
|
-
)
|
|
839
|
-
.map((item) => (
|
|
840
|
-
<div key={item.key} className="flex items-center">
|
|
841
|
-
{item.condition === false ? (
|
|
842
|
-
<div style={{ minHeight: "20px", width: "100%" }} />
|
|
843
|
-
) : (
|
|
844
|
-
item.render
|
|
652
|
+
<div>
|
|
653
|
+
{showLastSeats ? (
|
|
654
|
+
<div
|
|
655
|
+
className="flex justify-end mr-[11px] "
|
|
656
|
+
style={{
|
|
657
|
+
marginBottom:
|
|
658
|
+
serviceItem?.available_seats < 10 &&
|
|
659
|
+
serviceItem?.available_seats > 0
|
|
660
|
+
? "6px"
|
|
661
|
+
: "0",
|
|
662
|
+
}}
|
|
663
|
+
>
|
|
664
|
+
{serviceItem?.available_seats < 10 &&
|
|
665
|
+
serviceItem?.available_seats > 0 && (
|
|
666
|
+
<div className="text-[12.5px] text-[#464647] mt-1 text-center">
|
|
667
|
+
¡ Últimos Asientos!
|
|
668
|
+
</div>
|
|
845
669
|
)}
|
|
846
|
-
</div>
|
|
847
|
-
))}
|
|
848
|
-
</div>
|
|
849
|
-
</div> */}
|
|
850
|
-
|
|
851
|
-
<div className="flex items-center mt-[15px] border-t border-[#eee] pt-[10px]">
|
|
852
|
-
{/* 🔹 LEFT SIDE (GRID ITEMS) */}
|
|
853
|
-
<div
|
|
854
|
-
className="grid items-center gap-[2%] flex-1"
|
|
855
|
-
style={{
|
|
856
|
-
gridTemplateColumns: "40% 18% 23% 23%",
|
|
857
|
-
// otherItems
|
|
858
|
-
// .map((i) => i.width)
|
|
859
|
-
// .join(" "),
|
|
860
|
-
}}
|
|
861
|
-
>
|
|
862
|
-
{otherItems.map((item) => (
|
|
863
|
-
<div key={item.key} className="flex items-center ">
|
|
864
|
-
{item.render}
|
|
865
670
|
</div>
|
|
866
|
-
)
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
671
|
+
) : null}
|
|
672
|
+
<KuposButton
|
|
673
|
+
isSoldOut={isSoldOut}
|
|
674
|
+
isLoading={serviceDetailsLoading}
|
|
675
|
+
buttonColor={colors.kuposButtonColor}
|
|
676
|
+
buyLabel={translation?.buyButton}
|
|
677
|
+
soldOutLabel={translation?.soldOutButton}
|
|
678
|
+
soldOutIcon={renderIcon("soldOutIcon", "14px")}
|
|
679
|
+
onClick={checkMidnight}
|
|
680
|
+
/>
|
|
872
681
|
</div>
|
|
873
682
|
</div>
|
|
683
|
+
<BottomAmenities
|
|
684
|
+
otherItems={otherItems}
|
|
685
|
+
serviceItem={serviceItem}
|
|
686
|
+
grayscaleClass={grayscaleClass}
|
|
687
|
+
isSoldOut={isSoldOut}
|
|
688
|
+
isItemExpanded={isItemExpanded}
|
|
689
|
+
colors={colors}
|
|
690
|
+
translation={translation}
|
|
691
|
+
getAnimationIcon={getAnimationIcon}
|
|
692
|
+
downArrowIcon={renderIcon("downArrow", "10px")}
|
|
693
|
+
onToggleExpand={() =>
|
|
694
|
+
setIsExpand &&
|
|
695
|
+
setIsExpand(isItemExpanded ? null : serviceItem.id)
|
|
696
|
+
}
|
|
697
|
+
/>
|
|
874
698
|
</div>
|
|
875
699
|
</div>
|
|
876
700
|
|
|
701
|
+
{/* 🔹 EXPANDABLE DROPDOWN (below the card) */}
|
|
702
|
+
{isItemExpanded && (
|
|
703
|
+
<ExpandedDropdown
|
|
704
|
+
serviceItem={serviceItem}
|
|
705
|
+
showPromo={showPromo}
|
|
706
|
+
colors={colors}
|
|
707
|
+
grayscaleClass={grayscaleClass}
|
|
708
|
+
translation={translation}
|
|
709
|
+
getAnimationIcon={getAnimationIcon}
|
|
710
|
+
/>
|
|
711
|
+
)}
|
|
712
|
+
|
|
877
713
|
{children}
|
|
878
714
|
{/* Bottom discount banner */}
|
|
879
715
|
{serviceItem?.offer_text && (
|
|
880
716
|
<div
|
|
881
|
-
className=
|
|
717
|
+
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]"
|
|
882
718
|
style={{
|
|
883
|
-
backgroundColor:
|
|
884
|
-
? colors?.bottomStripColor
|
|
885
|
-
: colors?.bottomStripColor,
|
|
719
|
+
backgroundColor: colors?.bottomStripColor,
|
|
886
720
|
opacity: isSoldOut ? 0.5 : 1,
|
|
887
721
|
}}
|
|
888
722
|
>
|
|
@@ -894,83 +728,6 @@ function ServiceItemPB({
|
|
|
894
728
|
<span className="ml-[10px]">{serviceItem?.offer_text}</span>
|
|
895
729
|
</div>
|
|
896
730
|
)}
|
|
897
|
-
|
|
898
|
-
<div className="absolute -top-[11px] left-0 w-full flex items-center justify-end gap-[12px] pr-[15px] z-10 ">
|
|
899
|
-
{showTopLabel && (
|
|
900
|
-
<div
|
|
901
|
-
className={`flex items-center gap-[10px] py-[4px] px-[14px] rounded-[38px] text-[12.5px] z-20`}
|
|
902
|
-
style={{
|
|
903
|
-
backgroundColor: isSoldOut
|
|
904
|
-
? "#ddd"
|
|
905
|
-
: colors.ratingBottomColor,
|
|
906
|
-
}}
|
|
907
|
-
>
|
|
908
|
-
<div className={isSoldOut ? "grayscale" : ""}>
|
|
909
|
-
<LottiePlayer
|
|
910
|
-
// animationData={serviceItem.icons.priorityStageAnim}
|
|
911
|
-
animationData={getAnimationIcon("priorityStageAnim")}
|
|
912
|
-
width="14px"
|
|
913
|
-
height="14px"
|
|
914
|
-
/>
|
|
915
|
-
</div>
|
|
916
|
-
<div
|
|
917
|
-
className={
|
|
918
|
-
isSoldOut ? "text-white" : `text-[${colors.topLabelColor}]`
|
|
919
|
-
}
|
|
920
|
-
>
|
|
921
|
-
{showTopLabel}
|
|
922
|
-
</div>
|
|
923
|
-
</div>
|
|
924
|
-
)}
|
|
925
|
-
{serviceItem?.is_transpordo && (
|
|
926
|
-
<div
|
|
927
|
-
className={`flex items-center gap-[10px] py-[4px] text-white px-[14px] rounded-[38px] text-[12.5px] z-20`}
|
|
928
|
-
style={{
|
|
929
|
-
backgroundColor: isSoldOut ? "#ddd" : colors.tooltipColor,
|
|
930
|
-
}}
|
|
931
|
-
>
|
|
932
|
-
<LottiePlayer
|
|
933
|
-
animationData={serviceItem.icons.connectingServiceIcon}
|
|
934
|
-
// animationData={getAnimationIcon(connectingServiceIcon)}
|
|
935
|
-
width="14px"
|
|
936
|
-
height="14px"
|
|
937
|
-
/>
|
|
938
|
-
<div>{"Conexión"}</div>
|
|
939
|
-
</div>
|
|
940
|
-
)}
|
|
941
|
-
{serviceItem?.is_direct_trip && (
|
|
942
|
-
<div
|
|
943
|
-
className={`flex items-center gap-[10px] py-[4px] text-white px-[14px] rounded-[38px] text-[12.5px] z-20 `}
|
|
944
|
-
style={{
|
|
945
|
-
backgroundColor: isSoldOut ? "#ddd" : colors.tooltipColor,
|
|
946
|
-
}}
|
|
947
|
-
>
|
|
948
|
-
<LottiePlayer
|
|
949
|
-
// animationData={serviceItem.icons.directoAnim}
|
|
950
|
-
animationData={getAnimationIcon("directoAnim")}
|
|
951
|
-
width="14px"
|
|
952
|
-
height="14px"
|
|
953
|
-
/>
|
|
954
|
-
<div>{translation?.directService}</div>
|
|
955
|
-
</div>
|
|
956
|
-
)}
|
|
957
|
-
{serviceItem?.train_type_label === "Tren Express (Nuevo)" && (
|
|
958
|
-
<div
|
|
959
|
-
className={`flex items-center gap-[10px] py-[4px] text-white px-[14px] rounded-[38px] text-[12.5px] z-20 `}
|
|
960
|
-
style={{
|
|
961
|
-
backgroundColor: isSoldOut ? "#ddd" : colors.tooltipColor,
|
|
962
|
-
}}
|
|
963
|
-
>
|
|
964
|
-
<LottiePlayer
|
|
965
|
-
// animationData={serviceItem.icons.directoAnim}
|
|
966
|
-
animationData={getAnimationIcon("directoAnim")}
|
|
967
|
-
width="14px"
|
|
968
|
-
height="14px"
|
|
969
|
-
/>
|
|
970
|
-
<div>{"Tren Express"}</div>
|
|
971
|
-
</div>
|
|
972
|
-
)}
|
|
973
|
-
</div>
|
|
974
731
|
</div>
|
|
975
732
|
)}
|
|
976
733
|
</>
|