kupos-ui-components-lib 9.1.1 → 9.1.2
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/directo.json +1 -1
- package/dist/components/ServiceItem/PeruServiceItemDesktop.js +1 -1
- package/dist/components/ServiceItem/RatingHover.js +32 -33
- package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemDesktop.js +147 -267
- package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemMobile.js +87 -278
- package/dist/components/ServiceItem/mobileTypes.d.ts +5 -0
- package/dist/components/ServiceItem/types.d.ts +7 -0
- package/dist/styles.css +131 -32
- package/dist/ui/AmenitiesBlock.js +23 -30
- package/dist/ui/BottomAmenities/BottomAmenities.js +0 -1
- package/dist/ui/DurationBlock.js +4 -4
- package/dist/ui/FlexibleBlock.js +5 -6
- package/dist/ui/PetBlock.js +1 -3
- package/dist/ui/RatingBlock.d.ts +9 -1
- package/dist/ui/RatingBlock.js +7 -3
- package/dist/utils/CommonService.d.ts +1 -1
- package/dist/utils/CommonService.js +2 -0
- package/package.json +2 -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/components/ServiceItem/PeruServiceItemDesktop.tsx +1 -0
- package/src/components/ServiceItem/RatingHover.tsx +44 -45
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +313 -537
- package/src/components/ServiceItem/ServiceItemMobile.tsx +213 -530
- package/src/components/ServiceItem/mobileTypes.ts +5 -0
- package/src/components/ServiceItem/types.ts +7 -0
- package/src/ui/AmenitiesBlock.tsx +50 -29
- package/src/ui/BottomAmenities/BottomAmenities.tsx +110 -0
- package/src/ui/DateTimeSection/DateTimeSection.tsx +207 -0
- package/src/ui/DirectoBlock.tsx +31 -0
- package/src/ui/DurationBlock.tsx +4 -4
- package/src/ui/ExpendedDropDown/ExpandedDropdown.tsx +103 -0
- package/src/ui/FlexibleBlock.tsx +6 -5
- package/src/ui/KuposButton/KuposButton.tsx +48 -0
- package/src/ui/PetBlock.tsx +2 -2
- package/src/ui/RatingBlock.tsx +18 -6
- package/src/ui/SeatSection/SeatSection.tsx +207 -0
- package/src/ui/TopAmenities/TopAmenities.tsx +127 -0
- package/src/ui/mobileweb/BottomAmenitiesMobile.tsx +169 -0
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +192 -0
- package/src/ui/mobileweb/ExpandedDropdownMobile.tsx +56 -0
- package/src/ui/mobileweb/SeatSectionMobile.tsx +256 -0
- package/src/ui/mobileweb/TopAmenitieMobile.tsx +126 -0
- package/src/utils/CommonService.ts +2 -0
|
@@ -3,6 +3,11 @@ import LottiePlayer from "../../assets/LottiePlayer";
|
|
|
3
3
|
import DateService from "../../utils/DateService";
|
|
4
4
|
import { MobileServiceItemProps } from "./mobileTypes";
|
|
5
5
|
import commonService from "../../utils/CommonService";
|
|
6
|
+
import TopAmenitieMobile from "../../ui/mobileweb/TopAmenitieMobile";
|
|
7
|
+
import BottomAmenitiesMobile from "../../ui/mobileweb/BottomAmenitiesMobile";
|
|
8
|
+
import SeatSectionMobile from "../../ui/mobileweb/SeatSectionMobile";
|
|
9
|
+
import DateTimeSectionMobile from "../../ui/mobileweb/DateTimeSectionMobile";
|
|
10
|
+
import ExpandedDropdownMobile from "../../ui/mobileweb/ExpandedDropdownMobile";
|
|
6
11
|
|
|
7
12
|
const SEAT_EXCEPTIONS = ["Asiento mascota"];
|
|
8
13
|
|
|
@@ -28,6 +33,8 @@ function ServiceItemMobile({
|
|
|
28
33
|
amenitiesData,
|
|
29
34
|
setShowDropdown,
|
|
30
35
|
showDropdown,
|
|
36
|
+
isExpanded,
|
|
37
|
+
setIsExpanded,
|
|
31
38
|
setAmenetiesAtomValue,
|
|
32
39
|
isCiva,
|
|
33
40
|
currencySign,
|
|
@@ -37,8 +44,41 @@ function ServiceItemMobile({
|
|
|
37
44
|
removeDuplicateSeats,
|
|
38
45
|
isLinatal,
|
|
39
46
|
}: MobileServiceItemProps): React.ReactElement {
|
|
47
|
+
const isItemExpanded = serviceItem.id === isExpanded;
|
|
40
48
|
const isPetSeat = (Object.keys(serviceItem?.pet_seat_info) || []).length > 0;
|
|
41
49
|
let isSoldOut = serviceItem.available_seats <= 0;
|
|
50
|
+
const showPromo = Math.random() > 0.5;
|
|
51
|
+
|
|
52
|
+
const countdownSeconds = 7830;
|
|
53
|
+
|
|
54
|
+
const startCountdown = (node: HTMLSpanElement | null) => {
|
|
55
|
+
if (!node) return;
|
|
56
|
+
|
|
57
|
+
const prevId = node.dataset.countdownId;
|
|
58
|
+
if (prevId) clearInterval(Number(prevId));
|
|
59
|
+
|
|
60
|
+
let remaining = countdownSeconds;
|
|
61
|
+
|
|
62
|
+
const formatTime = (totalSecs: number) => {
|
|
63
|
+
const h = Math.floor(totalSecs / 3600);
|
|
64
|
+
const m = Math.floor((totalSecs % 3600) / 60);
|
|
65
|
+
const s = totalSecs % 60;
|
|
66
|
+
return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
node.textContent = formatTime(remaining);
|
|
70
|
+
|
|
71
|
+
const id = setInterval(() => {
|
|
72
|
+
remaining -= 1;
|
|
73
|
+
if (remaining <= 0) {
|
|
74
|
+
remaining = 0;
|
|
75
|
+
clearInterval(id);
|
|
76
|
+
}
|
|
77
|
+
node.textContent = formatTime(remaining);
|
|
78
|
+
}, 1000);
|
|
79
|
+
|
|
80
|
+
node.dataset.countdownId = String(id);
|
|
81
|
+
};
|
|
42
82
|
|
|
43
83
|
const labelId =
|
|
44
84
|
typeof serviceItem.boarding_stages === "string"
|
|
@@ -61,194 +101,6 @@ function ServiceItemMobile({
|
|
|
61
101
|
}
|
|
62
102
|
};
|
|
63
103
|
|
|
64
|
-
const seatTypes = () => {
|
|
65
|
-
let seatTypes = serviceItem.seat_types
|
|
66
|
-
?.filter((item) => getFilteredSeats(item.label))
|
|
67
|
-
?.sort((a, b) => a.fare - b.fare) // Add this line to sort by fare
|
|
68
|
-
?.slice(0, 2)
|
|
69
|
-
?.map((type, i) =>
|
|
70
|
-
exceptions.includes(type.label) ? null : (
|
|
71
|
-
<div
|
|
72
|
-
className={
|
|
73
|
-
serviceItem.seat_types?.length > 2
|
|
74
|
-
? "w-[100%] flex flex-row justify-between "
|
|
75
|
-
: "w-[100%] flex flex-row justify-between items-center"
|
|
76
|
-
}
|
|
77
|
-
key={i}
|
|
78
|
-
>
|
|
79
|
-
<span
|
|
80
|
-
className="min-[420]:text-[13px] text-[12px] "
|
|
81
|
-
style={{
|
|
82
|
-
// marginLeft: "10px",
|
|
83
|
-
color: isSoldOut ? "#bbb" : "#464647",
|
|
84
|
-
}}
|
|
85
|
-
>
|
|
86
|
-
{type.label}
|
|
87
|
-
</span>
|
|
88
|
-
<span
|
|
89
|
-
className={"min-[420]:text-[13px] text-[12px] bold-text"}
|
|
90
|
-
style={{ color: isSoldOut ? "#bbb" : colors.seatPriceColor }}
|
|
91
|
-
>
|
|
92
|
-
{commonService.currency(type.fare, currencySign)}
|
|
93
|
-
</span>
|
|
94
|
-
</div>
|
|
95
|
-
),
|
|
96
|
-
);
|
|
97
|
-
return seatTypes;
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const seatTypesWithRemoveDuplicateSeats = () => {
|
|
101
|
-
const seatMap = new Map();
|
|
102
|
-
|
|
103
|
-
serviceItem.seat_types
|
|
104
|
-
?.filter((item) => getFilteredSeats(item.label))
|
|
105
|
-
?.forEach((item) => {
|
|
106
|
-
if (exceptions.includes(item.key as any)) return;
|
|
107
|
-
const existing = seatMap.get(item.label);
|
|
108
|
-
if (
|
|
109
|
-
!existing ||
|
|
110
|
-
parseFloat(item.fare as any) < parseFloat(existing.fare)
|
|
111
|
-
) {
|
|
112
|
-
seatMap.set(item.label, item);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
const uniqueSeats = Array.from(seatMap.values())
|
|
117
|
-
.sort((a, b) => a.fare - b.fare)
|
|
118
|
-
.slice(0, 3);
|
|
119
|
-
return uniqueSeats.map((type, i) => {
|
|
120
|
-
return exceptions.includes(type.label) ? null : (
|
|
121
|
-
<div
|
|
122
|
-
className={
|
|
123
|
-
serviceItem.seat_types?.length > 2
|
|
124
|
-
? "w-[100%] flex flex-row justify-between "
|
|
125
|
-
: "w-[100%] flex flex-row justify-between items-center"
|
|
126
|
-
}
|
|
127
|
-
key={i}
|
|
128
|
-
>
|
|
129
|
-
<span
|
|
130
|
-
className="min-[420]:text-[13px] text-[11px] "
|
|
131
|
-
style={{
|
|
132
|
-
// marginLeft: "10px",
|
|
133
|
-
color: isSoldOut ? "#bbb" : "#464647",
|
|
134
|
-
}}
|
|
135
|
-
>
|
|
136
|
-
{commonService.truncateSeatLabel(type.label)}
|
|
137
|
-
</span>
|
|
138
|
-
<span
|
|
139
|
-
className={"min-[420]:text-[13px] text-[11px] bold-text"}
|
|
140
|
-
style={{ color: isSoldOut ? "#bbb" : colors.seatPriceColor }}
|
|
141
|
-
>
|
|
142
|
-
{/* {serviceItem?.operator_service_name === "Pullman San Andrés" &&
|
|
143
|
-
serviceItem?.available_seats <= 0
|
|
144
|
-
? null
|
|
145
|
-
: commonService.currency(type.fare, currencySign)} */}
|
|
146
|
-
|
|
147
|
-
{serviceItem?.available_seats <= 0 && !isPeru
|
|
148
|
-
? commonService.currency(0, currencySign)
|
|
149
|
-
: commonService.currency(type.fare, currencySign)}
|
|
150
|
-
</span>
|
|
151
|
-
</div>
|
|
152
|
-
);
|
|
153
|
-
});
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
const getFilteredSeats = (item) => {
|
|
157
|
-
return item;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
const getAmenitiesImage = (name: string): string => {
|
|
161
|
-
switch (name) {
|
|
162
|
-
case "air_condtion.png": {
|
|
163
|
-
return serviceItem?.icons?.airConditionIcon;
|
|
164
|
-
}
|
|
165
|
-
case "baggage.png": {
|
|
166
|
-
return serviceItem?.icons?.baggageIcon;
|
|
167
|
-
}
|
|
168
|
-
case "charging_plug.png": {
|
|
169
|
-
return serviceItem?.icons?.chargingIcon;
|
|
170
|
-
}
|
|
171
|
-
case "coffee.png": {
|
|
172
|
-
return serviceItem?.icons?.coffeeIcon;
|
|
173
|
-
}
|
|
174
|
-
case "food_new_icon.png": {
|
|
175
|
-
return serviceItem?.icons?.foodIcon;
|
|
176
|
-
}
|
|
177
|
-
case "gaming.png": {
|
|
178
|
-
return serviceItem?.icons?.gamingIcon;
|
|
179
|
-
}
|
|
180
|
-
case "handicap.png": {
|
|
181
|
-
return serviceItem?.icons?.handicapIcon;
|
|
182
|
-
}
|
|
183
|
-
case "mobile_ticket.png": {
|
|
184
|
-
return serviceItem?.icons?.mobileTicketIcon;
|
|
185
|
-
}
|
|
186
|
-
case "movie.png": {
|
|
187
|
-
return serviceItem?.icons?.movieIcon;
|
|
188
|
-
}
|
|
189
|
-
case "restrooms.png": {
|
|
190
|
-
return serviceItem?.icons?.restroomsIcon;
|
|
191
|
-
}
|
|
192
|
-
case "snacks_new.png": {
|
|
193
|
-
return serviceItem?.icons?.snackIcon;
|
|
194
|
-
}
|
|
195
|
-
case "wifi.png": {
|
|
196
|
-
return serviceItem?.icons?.wifiIcon;
|
|
197
|
-
}
|
|
198
|
-
case "cortina_divisoria.png": {
|
|
199
|
-
return serviceItem?.icons?.cortinaIcon;
|
|
200
|
-
}
|
|
201
|
-
case "frazada.png": {
|
|
202
|
-
return serviceItem?.icons?.frazaIcon;
|
|
203
|
-
}
|
|
204
|
-
case "blanket.png": {
|
|
205
|
-
return serviceItem?.icons?.blankketIcon;
|
|
206
|
-
}
|
|
207
|
-
case "cctv.png": {
|
|
208
|
-
return serviceItem?.icons?.cctvIcon;
|
|
209
|
-
}
|
|
210
|
-
case "cup_holder.png": {
|
|
211
|
-
return serviceItem?.icons?.cupHolderIcon;
|
|
212
|
-
}
|
|
213
|
-
case "emergency_contact.png": {
|
|
214
|
-
return serviceItem?.icons?.emergencyContactIcon;
|
|
215
|
-
}
|
|
216
|
-
case "emergency_exit.png": {
|
|
217
|
-
return serviceItem?.icons?.emergencyExitIcon;
|
|
218
|
-
}
|
|
219
|
-
case "fire_extinguisher.png": {
|
|
220
|
-
return serviceItem?.icons?.fireExtinguisherIcon;
|
|
221
|
-
}
|
|
222
|
-
case "reading_light.png": {
|
|
223
|
-
return serviceItem?.icons?.readingLIghtIcon;
|
|
224
|
-
}
|
|
225
|
-
case "seat_belt.png": {
|
|
226
|
-
return serviceItem?.icons?.sercurityBeltIcon;
|
|
227
|
-
}
|
|
228
|
-
case "service_on_board.png": {
|
|
229
|
-
return serviceItem?.icons?.serviceOnBoardIcon;
|
|
230
|
-
}
|
|
231
|
-
case "personal_tv.png": {
|
|
232
|
-
return serviceItem?.icons?.personalTVIcon;
|
|
233
|
-
}
|
|
234
|
-
case "pet_admission.png": {
|
|
235
|
-
return serviceItem?.icons?.petAdmissionIcon;
|
|
236
|
-
}
|
|
237
|
-
case "music.png": {
|
|
238
|
-
return serviceItem?.icons?.musicIcon;
|
|
239
|
-
}
|
|
240
|
-
case "headset.png": {
|
|
241
|
-
return serviceItem?.icons?.headPhoneIcon;
|
|
242
|
-
}
|
|
243
|
-
case "allows_cancellation.png": {
|
|
244
|
-
return serviceItem?.icons?.allowCancellationIcon;
|
|
245
|
-
}
|
|
246
|
-
default: {
|
|
247
|
-
return "";
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
|
-
|
|
252
104
|
const amenities = () => {
|
|
253
105
|
const raw = serviceItem?.operator_details?.[3];
|
|
254
106
|
const list = Array.isArray(raw)
|
|
@@ -261,8 +113,8 @@ function ServiceItemMobile({
|
|
|
261
113
|
<img
|
|
262
114
|
key={i}
|
|
263
115
|
className="amenity"
|
|
264
|
-
height={
|
|
265
|
-
width={
|
|
116
|
+
height={12}
|
|
117
|
+
width={12}
|
|
266
118
|
// src={getAmenitiesImage(amenitiesData?.[am]?.toLowerCase())}
|
|
267
119
|
src={commonService.getAmenitiesImage(
|
|
268
120
|
amenitiesData?.[am]?.toLowerCase(),
|
|
@@ -298,32 +150,6 @@ function ServiceItemMobile({
|
|
|
298
150
|
isConexion = true;
|
|
299
151
|
}
|
|
300
152
|
|
|
301
|
-
const depTime = serviceItem.dep_time || "";
|
|
302
|
-
|
|
303
|
-
// Extract hours and minutes and check for AM/PM
|
|
304
|
-
const hasAM = depTime.includes("AM");
|
|
305
|
-
const hasPM = depTime.includes("PM");
|
|
306
|
-
const [timePart] = depTime.split(/AM|PM/).map((part) => part.trim());
|
|
307
|
-
const [hour, minute] = timePart.split(":").map(Number);
|
|
308
|
-
|
|
309
|
-
// Convert to 24-hour format
|
|
310
|
-
let cleanedDepTime;
|
|
311
|
-
if (hasAM) {
|
|
312
|
-
cleanedDepTime =
|
|
313
|
-
hour === 12
|
|
314
|
-
? `00:${minute < 10 ? "0" + minute : minute}`
|
|
315
|
-
: `${hour < 10 ? "0" + hour : hour}:${
|
|
316
|
-
minute < 10 ? "0" + minute : minute
|
|
317
|
-
}`;
|
|
318
|
-
} else if (hasPM) {
|
|
319
|
-
cleanedDepTime =
|
|
320
|
-
hour === 12
|
|
321
|
-
? `${hour}:${minute < 10 ? "0" + minute : minute}`
|
|
322
|
-
: `${hour + 12}:${minute < 10 ? "0" + minute : minute}`;
|
|
323
|
-
} else {
|
|
324
|
-
cleanedDepTime = timePart;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
153
|
return (
|
|
328
154
|
<div
|
|
329
155
|
className={`relative ${
|
|
@@ -338,23 +164,39 @@ function ServiceItemMobile({
|
|
|
338
164
|
} `}
|
|
339
165
|
style={{ backgroundColor: "#fff", zIndex: 1 }}
|
|
340
166
|
>
|
|
167
|
+
{/* <TopAmenitieMobile
|
|
168
|
+
showTopLabel={showTopLabel}
|
|
169
|
+
isSoldOut={isSoldOut}
|
|
170
|
+
seatPriceColor={colors.seatPriceColor}
|
|
171
|
+
bombAnim={serviceItem.icons.bombAnim}
|
|
172
|
+
priorityStageAnim={serviceItem.icons.priorityStageAnim}
|
|
173
|
+
countdownSeconds={countdownSeconds}
|
|
174
|
+
onCountdownEnd={() => {
|
|
175
|
+
const cardEl = document.getElementById(
|
|
176
|
+
`service-card-${serviceItem.id}`,
|
|
177
|
+
);
|
|
178
|
+
if (!cardEl) return;
|
|
179
|
+
cardEl.style.border = "1px solid #ccc";
|
|
180
|
+
if (!showTopLabel) {
|
|
181
|
+
cardEl.style.borderRadius = "10px";
|
|
182
|
+
}
|
|
183
|
+
}}
|
|
184
|
+
offerText={serviceItem?.offer_text}
|
|
185
|
+
/> */}
|
|
341
186
|
<div
|
|
342
|
-
className={"
|
|
343
|
-
style={{
|
|
187
|
+
className={" rounded-[20px]"}
|
|
188
|
+
style={{
|
|
189
|
+
backgroundColor: "#fff",
|
|
190
|
+
zIndex: 1,
|
|
191
|
+
// borderRadius: showTopLabel ? "10px 0 10px 10px" : "10px",
|
|
192
|
+
borderRadius: "12px",
|
|
193
|
+
border: "1px solid #ccc",
|
|
194
|
+
}}
|
|
344
195
|
>
|
|
345
|
-
<div
|
|
346
|
-
className={`p-[12px] ${
|
|
347
|
-
serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
|
|
348
|
-
showTopLabel ||
|
|
349
|
-
serviceItem?.is_direct_trip ||
|
|
350
|
-
serviceItem?.is_transpordo
|
|
351
|
-
? "mt-[10px]"
|
|
352
|
-
: ""
|
|
353
|
-
}`}
|
|
354
|
-
>
|
|
196
|
+
<div style={{ padding: "12px 12px 8px 12px" }}>
|
|
355
197
|
{/* Header with operator info and favorite */}
|
|
356
|
-
<div className="flex justify-between mb-[
|
|
357
|
-
<div className="flex items-center
|
|
198
|
+
<div className="flex justify-between items-center mb-[10px]">
|
|
199
|
+
<div className="flex items-center justify-between">
|
|
358
200
|
<div className="w-[120px] overflow-y-hidden">
|
|
359
201
|
<img
|
|
360
202
|
src={serviceItem.operator_details[0]}
|
|
@@ -369,296 +211,99 @@ function ServiceItemMobile({
|
|
|
369
211
|
{serviceItem?.operator_details[2]}
|
|
370
212
|
</div>
|
|
371
213
|
) : showRating ? (
|
|
372
|
-
<div className="flex min-[420]:text-[13px] text-[12px]
|
|
373
|
-
<
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
214
|
+
<div className="flex min-[420]:text-[13px] text-[12px] items-center">
|
|
215
|
+
<div className="flex items-center">
|
|
216
|
+
<div className="flex items-center">
|
|
217
|
+
<img
|
|
218
|
+
src={serviceItem.icons.rating}
|
|
219
|
+
alt="origin"
|
|
220
|
+
className={`w-[12px] h-[12px] mr-[4px] object-contain ${
|
|
221
|
+
isSoldOut ? "grayscale" : ""
|
|
222
|
+
}`}
|
|
223
|
+
/>
|
|
224
|
+
<span style={{ lineHeight: "normal" }}>
|
|
225
|
+
{getServiceStars(serviceItem)}
|
|
226
|
+
</span>
|
|
227
|
+
</div>
|
|
228
|
+
|
|
229
|
+
<div
|
|
230
|
+
className="flex items-center cursor-pointer "
|
|
231
|
+
style={{ color: isSoldOut ? "#bbb" : "text-[#464647]" }}
|
|
232
|
+
>
|
|
233
|
+
<span className="ml-[3px] min-[420]:text-[13px] text-[12px] text-ellipsis">
|
|
234
|
+
{serviceItem.operator_details[2]}
|
|
235
|
+
</span>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
383
238
|
</div>
|
|
384
239
|
) : null}
|
|
385
240
|
</div>
|
|
386
241
|
{showLastSeats ? (
|
|
387
|
-
<div className="flex justify-end
|
|
242
|
+
<div className="flex justify-end ">
|
|
388
243
|
{serviceItem?.available_seats < 10 &&
|
|
389
244
|
serviceItem?.available_seats > 0 && (
|
|
390
|
-
<
|
|
391
|
-
className="text-[12px] text-[red] mt-1 flex justify-end pt-[5px] pb-[5px] pl-[15px] pr-[15px] rounded-[8px] "
|
|
392
|
-
style={{
|
|
393
|
-
backgroundColor: colors.lastSeatBg,
|
|
394
|
-
color: colors.lastSeatText,
|
|
395
|
-
}}
|
|
396
|
-
>
|
|
245
|
+
<div className="text-[10px] text-[#464647] text-center">
|
|
397
246
|
¡ Últimos Asientos!
|
|
398
|
-
</
|
|
247
|
+
</div>
|
|
399
248
|
)}
|
|
400
249
|
</div>
|
|
401
250
|
) : null}
|
|
402
251
|
</div>
|
|
403
252
|
|
|
404
|
-
<
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
{
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
) : (
|
|
459
|
-
DateService.formatTime(serviceItem.dep_time)
|
|
460
|
-
)}
|
|
461
|
-
</div>
|
|
462
|
-
</div>
|
|
463
|
-
</div>
|
|
464
|
-
</div>
|
|
465
|
-
{isCiva ? null : (
|
|
466
|
-
<div
|
|
467
|
-
className={`flex items-center min-[420]:text-[13px] text-[12px] justify-between ${
|
|
468
|
-
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
469
|
-
}`}
|
|
470
|
-
>
|
|
471
|
-
<div className="flex items-center" style={{ flex: 1 }}>
|
|
472
|
-
<div>
|
|
473
|
-
{" "}
|
|
474
|
-
{destinationLabel ? (
|
|
475
|
-
<div className="w-[60px]">{destinationLabel}</div>
|
|
476
|
-
) : (
|
|
477
|
-
<div className="w-[14px] h-auto mr-[5px]">
|
|
478
|
-
<img
|
|
479
|
-
src={serviceItem.icons?.destination}
|
|
480
|
-
alt="destination"
|
|
481
|
-
className={`w-[14px] h-auto mr-[5px] ${
|
|
482
|
-
isSoldOut ? "grayscale" : ""
|
|
483
|
-
}`}
|
|
484
|
-
/>
|
|
485
|
-
</div>
|
|
486
|
-
)}
|
|
487
|
-
</div>
|
|
488
|
-
<div
|
|
489
|
-
className="flex items-center relative capitalize justify-between "
|
|
490
|
-
style={{ flex: 1 }}
|
|
491
|
-
>
|
|
492
|
-
<span className="cursor-pointer black-text">
|
|
493
|
-
{DateService.getServiceItemDate(
|
|
494
|
-
serviceItem.arrival_date,
|
|
495
|
-
)}
|
|
496
|
-
</span>
|
|
497
|
-
<div className="absolute left-[50%]">•</div>
|
|
498
|
-
<div className="font-[900] relative black-text">
|
|
499
|
-
{DateService.formatTime(serviceItem.arr_time)}
|
|
500
|
-
</div>
|
|
501
|
-
</div>
|
|
502
|
-
</div>
|
|
503
|
-
</div>
|
|
504
|
-
)}
|
|
505
|
-
</div>
|
|
506
|
-
<div
|
|
507
|
-
style={{
|
|
508
|
-
width: "1px",
|
|
509
|
-
height: "2.5rem",
|
|
510
|
-
backgroundColor: "#ccc",
|
|
511
|
-
margin: "auto",
|
|
512
|
-
}}
|
|
513
|
-
></div>
|
|
514
|
-
{/* SEATS */}
|
|
515
|
-
<div
|
|
516
|
-
className="content-center"
|
|
517
|
-
style={{
|
|
518
|
-
width: isPeru ? "40%" : "40%",
|
|
519
|
-
}}
|
|
520
|
-
>
|
|
521
|
-
<div
|
|
522
|
-
className="flex flex-col justify-between h-[2.5rem] "
|
|
523
|
-
style={{
|
|
524
|
-
gap: isSoldOut ? "0px" : "5px",
|
|
525
|
-
justifyContent:
|
|
526
|
-
serviceItem.seat_types?.length > 2
|
|
527
|
-
? "space-between"
|
|
528
|
-
: "center",
|
|
529
|
-
}}
|
|
530
|
-
>
|
|
531
|
-
{removeDuplicateSeats
|
|
532
|
-
? seatTypesWithRemoveDuplicateSeats()
|
|
533
|
-
: seatTypes()}
|
|
534
|
-
|
|
535
|
-
{isSoldOut ? (
|
|
536
|
-
<div className="flex justify-end">
|
|
537
|
-
<span
|
|
538
|
-
className={
|
|
539
|
-
"min-[420]:text-[13px] text-[12px] text-[#ccc]"
|
|
540
|
-
}
|
|
541
|
-
>
|
|
542
|
-
Agotado
|
|
543
|
-
</span>
|
|
544
|
-
</div>
|
|
545
|
-
) : null}
|
|
546
|
-
</div>
|
|
547
|
-
</div>
|
|
548
|
-
</div>
|
|
549
|
-
<div className="bg-[#E6E6E6] -ml-[12px] -mr-[12px] mt-[10px] mb-[10px] h-[1px]"></div>
|
|
550
|
-
<div
|
|
551
|
-
className={`${"flex justify-between items-center items-center "}`}
|
|
552
|
-
>
|
|
553
|
-
{/* Rating */}
|
|
554
|
-
<div>
|
|
555
|
-
<div className="flex items-center ">
|
|
556
|
-
<div
|
|
557
|
-
className="flex items-center cursor-pointer "
|
|
558
|
-
style={{ color: isSoldOut ? "#bbb" : "text-[#464647]" }}
|
|
559
|
-
>
|
|
560
|
-
<span className="ml-[3px] min-[420]:text-[13px] text-[12px] bold-text">
|
|
561
|
-
{serviceItem.operator_details[2]}
|
|
562
|
-
</span>
|
|
563
|
-
</div>
|
|
564
|
-
</div>
|
|
565
|
-
</div>
|
|
566
|
-
|
|
567
|
-
<div
|
|
568
|
-
className="flex relative "
|
|
569
|
-
style={{ color: isSoldOut ? "#bbb" : "text-[#464647]" }}
|
|
570
|
-
>
|
|
571
|
-
<div
|
|
572
|
-
className={`w-[12px] h-auto mr-[2px] ${
|
|
573
|
-
isSoldOut ? "grayscale" : ""
|
|
574
|
-
}`}
|
|
575
|
-
>
|
|
576
|
-
{renderIcon("hours", "14px")}
|
|
577
|
-
</div>
|
|
578
|
-
|
|
579
|
-
<div
|
|
580
|
-
className={`cursor-default group min-[420]:text-[13px] text-[12px] ${
|
|
581
|
-
isSoldOut ? "text-[#c0c0c0]" : ""
|
|
582
|
-
}`}
|
|
583
|
-
style={{ lineHeight: "normal" }}
|
|
584
|
-
>
|
|
585
|
-
{serviceItem.duration}hrs
|
|
586
|
-
</div>
|
|
587
|
-
</div>
|
|
588
|
-
|
|
589
|
-
<div style={{ opacity: isSoldOut ? 0.5 : 1 }}>{amenities()}</div>
|
|
590
|
-
|
|
591
|
-
{(serviceItem.is_change_ticket || isPetSeat) && (
|
|
592
|
-
<div
|
|
593
|
-
onClick={() => {
|
|
594
|
-
setShowDropdown(!showDropdown);
|
|
595
|
-
setAmenetiesAtomValue({
|
|
596
|
-
service: serviceItem,
|
|
597
|
-
showTopLabel: showTopLabel,
|
|
598
|
-
});
|
|
599
|
-
}}
|
|
600
|
-
className="flex items-center"
|
|
601
|
-
>
|
|
602
|
-
{serviceItem.pet_seat_info &&
|
|
603
|
-
Object.keys(serviceItem.pet_seat_info).length > 0 ? (
|
|
604
|
-
<div className="flex items-center">
|
|
605
|
-
<div className={`relative group cursor-default `}>
|
|
606
|
-
<div className="flex items-center">
|
|
607
|
-
<div
|
|
608
|
-
className={`mr-[5px] ${isSoldOut ? "grayscale" : ""}`}
|
|
609
|
-
>
|
|
610
|
-
<LottiePlayer
|
|
611
|
-
animationData={serviceItem.icons.petFriendlyAnim}
|
|
612
|
-
width="20px"
|
|
613
|
-
height="20px"
|
|
614
|
-
/>
|
|
615
|
-
</div>
|
|
616
|
-
</div>
|
|
617
|
-
</div>
|
|
618
|
-
</div>
|
|
619
|
-
) : null}
|
|
620
|
-
|
|
621
|
-
{/* Flexible ticket */}
|
|
622
|
-
{serviceItem.is_change_ticket && (
|
|
623
|
-
<div className="flex items-center">
|
|
624
|
-
<div className="relative group cursor-default">
|
|
625
|
-
<div className="flex items-center">
|
|
626
|
-
<div
|
|
627
|
-
className={`mr-[5px] ${isSoldOut ? "grayscale" : ""}`}
|
|
628
|
-
>
|
|
629
|
-
<LottiePlayer
|
|
630
|
-
animationData={serviceItem.icons.flexibleAnim}
|
|
631
|
-
width="20px"
|
|
632
|
-
height="20px"
|
|
633
|
-
/>
|
|
634
|
-
</div>
|
|
635
|
-
</div>
|
|
636
|
-
</div>
|
|
637
|
-
</div>
|
|
638
|
-
)}
|
|
639
|
-
|
|
640
|
-
{serviceItem?.is_tracking_enabled && (
|
|
641
|
-
<div className="flex items-center mr-[10px]">
|
|
642
|
-
<div
|
|
643
|
-
className={`h-auto mr-[4px] min-[420]:text-[13px] text-[11px] text-[#464647] ${
|
|
644
|
-
isSoldOut ? "grayscale" : ""
|
|
645
|
-
}`}
|
|
646
|
-
>
|
|
647
|
-
<LottiePlayer
|
|
648
|
-
animationData={serviceItem.icons.locationAnim}
|
|
649
|
-
width="20px"
|
|
650
|
-
height="20px"
|
|
651
|
-
/>
|
|
652
|
-
</div>
|
|
653
|
-
</div>
|
|
654
|
-
)}
|
|
655
|
-
|
|
656
|
-
{(serviceItem.is_change_ticket || isPetSeat) && (
|
|
657
|
-
<img src={serviceItem.icons.plus} alt="icon" width={11} />
|
|
658
|
-
)}
|
|
659
|
-
</div>
|
|
660
|
-
)}
|
|
661
|
-
</div>
|
|
253
|
+
<DateTimeSectionMobile
|
|
254
|
+
onBookButtonPress={onBookButtonPress}
|
|
255
|
+
isCiva={isCiva}
|
|
256
|
+
isSoldOut={isSoldOut}
|
|
257
|
+
isLinatal={isLinatal}
|
|
258
|
+
isPeru={isPeru}
|
|
259
|
+
orignLabel={orignLabel}
|
|
260
|
+
destinationLabel={destinationLabel}
|
|
261
|
+
originIcon={serviceItem.icons?.origin}
|
|
262
|
+
destinationIcon={serviceItem.icons?.destination}
|
|
263
|
+
travelDate={serviceItem.travel_date}
|
|
264
|
+
arrivalDate={serviceItem.arrival_date}
|
|
265
|
+
depTime={serviceItem.dep_time}
|
|
266
|
+
arrTime={serviceItem.arr_time}
|
|
267
|
+
seatTypes={serviceItem.seat_types}
|
|
268
|
+
seatPriceColor={colors.seatPriceColor}
|
|
269
|
+
currencySign={currencySign}
|
|
270
|
+
availableSeats={serviceItem.available_seats}
|
|
271
|
+
removeDuplicateSeats={removeDuplicateSeats}
|
|
272
|
+
/>
|
|
273
|
+
{/* <div className="bg-[#E6E6E6] -ml-[12px] -mr-[12px] mt-[10px] mb-[10px] h-[1px]"></div> */}
|
|
274
|
+
<div className="bg-[#E6E6E6] mt-[10px] mb-[10px] h-[1px]"></div>
|
|
275
|
+
|
|
276
|
+
<BottomAmenitiesMobile
|
|
277
|
+
isSoldOut={isSoldOut}
|
|
278
|
+
amenitiesNodes={amenities()}
|
|
279
|
+
hoursIcon={renderIcon("hours", "14px")}
|
|
280
|
+
duration={serviceItem.duration?.toString()}
|
|
281
|
+
isDirectTrip={serviceItem?.is_direct_trip}
|
|
282
|
+
directoColor={colors.directoColor}
|
|
283
|
+
directoAnim={serviceItem.icons.directoAnim}
|
|
284
|
+
isChangeTicket={serviceItem.is_change_ticket}
|
|
285
|
+
isPetSeat={isPetSeat}
|
|
286
|
+
petSeatInfo={serviceItem.pet_seat_info}
|
|
287
|
+
petFriendlyAnim={serviceItem.icons.petFriendlyAnim}
|
|
288
|
+
flexibleAnim={serviceItem.icons.flexibleAnim}
|
|
289
|
+
isTrackingEnabled={serviceItem?.is_tracking_enabled}
|
|
290
|
+
locationAnim={serviceItem.icons.locationAnim}
|
|
291
|
+
downArrowIcon={serviceItem.icons.downArrow}
|
|
292
|
+
showDropdown={isItemExpanded}
|
|
293
|
+
setShowDropdown={() =>
|
|
294
|
+
setIsExpanded(isItemExpanded ? null : serviceItem.id)
|
|
295
|
+
}
|
|
296
|
+
// onDropdownToggle={() => {
|
|
297
|
+
// setShowDropdown(!showDropdown);
|
|
298
|
+
// setAmenetiesAtomValue({
|
|
299
|
+
// service: serviceItem,
|
|
300
|
+
// showTopLabel: showTopLabel,
|
|
301
|
+
// });
|
|
302
|
+
// }}
|
|
303
|
+
onDropdownToggle={() => {
|
|
304
|
+
setIsExpanded(isItemExpanded ? null : serviceItem.id);
|
|
305
|
+
}}
|
|
306
|
+
/>
|
|
662
307
|
</div>
|
|
663
308
|
|
|
664
309
|
{serviceItem?.offer_text && (
|
|
@@ -672,21 +317,58 @@ function ServiceItemMobile({
|
|
|
672
317
|
opacity: isSoldOut ? 0.5 : 1,
|
|
673
318
|
}}
|
|
674
319
|
>
|
|
320
|
+
{/* <div className="flex justify-between items-center w-full">
|
|
321
|
+
<div className="flex items-center">
|
|
322
|
+
<LottiePlayer
|
|
323
|
+
animationData={serviceItem.icons.bombAnim}
|
|
324
|
+
width="18px"
|
|
325
|
+
height="18px"
|
|
326
|
+
/>
|
|
327
|
+
<span className="bold-text ml-[8px]">
|
|
328
|
+
{" "}
|
|
329
|
+
{serviceItem?.offer_text || ""}
|
|
330
|
+
</span>
|
|
331
|
+
</div>
|
|
332
|
+
<div>
|
|
333
|
+
Termina en
|
|
334
|
+
<span
|
|
335
|
+
className="bold-text text-end"
|
|
336
|
+
ref={startCountdown}
|
|
337
|
+
style={{
|
|
338
|
+
fontVariantNumeric: "tabular-nums",
|
|
339
|
+
display: "inline-block",
|
|
340
|
+
// minWidth: "70px",
|
|
341
|
+
}}
|
|
342
|
+
/>
|
|
343
|
+
</div>
|
|
344
|
+
</div> */}
|
|
675
345
|
<LottiePlayer
|
|
676
346
|
animationData={serviceItem.icons.promoAnim}
|
|
677
347
|
width="18px"
|
|
678
348
|
height="18px"
|
|
679
349
|
/>
|
|
680
|
-
<
|
|
681
|
-
|
|
682
|
-
|
|
350
|
+
<div className=" flex items-center mt-[2px]">
|
|
351
|
+
<span className="ml-[6px] text-[#fff] min-[380px]:text-[11px] text-[6px]">
|
|
352
|
+
{serviceItem?.offer_text || ""}
|
|
353
|
+
</span>{" "}
|
|
354
|
+
| Termina en
|
|
355
|
+
<span
|
|
356
|
+
className="bold-text"
|
|
357
|
+
ref={startCountdown}
|
|
358
|
+
style={{
|
|
359
|
+
fontVariantNumeric: "tabular-nums",
|
|
360
|
+
display: "inline-block",
|
|
361
|
+
// minWidth: "70px",
|
|
362
|
+
}}
|
|
363
|
+
/>
|
|
364
|
+
</div>
|
|
683
365
|
</div>
|
|
684
366
|
)}
|
|
685
367
|
|
|
686
|
-
<div className="absolute -top-[14px] left-0 w-full flex items-center justify-end gap-[12px] pr-[
|
|
368
|
+
<div className="absolute -top-[14px] left-0 w-full flex items-center justify-end gap-[12px] pr-[13px] z-10 ">
|
|
687
369
|
{showTopLabel && (
|
|
688
370
|
<div
|
|
689
|
-
className={`flex items-center gap-[2px] py-[
|
|
371
|
+
className={`flex items-center gap-[2px] py-[4px] px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20 `}
|
|
690
372
|
style={{
|
|
691
373
|
backgroundColor: isSoldOut ? "#ccc" : colors.ratingBottomColor,
|
|
692
374
|
}}
|
|
@@ -707,7 +389,6 @@ function ServiceItemMobile({
|
|
|
707
389
|
</div>
|
|
708
390
|
</div>
|
|
709
391
|
)}
|
|
710
|
-
|
|
711
392
|
{isConexion && (
|
|
712
393
|
<div
|
|
713
394
|
className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[11px] z-20 ${
|
|
@@ -722,22 +403,7 @@ function ServiceItemMobile({
|
|
|
722
403
|
<div>Conexión</div>
|
|
723
404
|
</div>
|
|
724
405
|
)}
|
|
725
|
-
|
|
726
|
-
<div
|
|
727
|
-
className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20 `}
|
|
728
|
-
style={{
|
|
729
|
-
backgroundColor: isSoldOut ? "#ddd" : colors.tooltipBgColor,
|
|
730
|
-
color: isSoldOut ? "#bbb" : colors.directoColor,
|
|
731
|
-
}}
|
|
732
|
-
>
|
|
733
|
-
<LottiePlayer
|
|
734
|
-
animationData={serviceItem.icons.directoAnim}
|
|
735
|
-
width="16px"
|
|
736
|
-
height="16px"
|
|
737
|
-
/>
|
|
738
|
-
<div className="ml-[5px]">Directo</div>
|
|
739
|
-
</div>
|
|
740
|
-
)}
|
|
406
|
+
|
|
741
407
|
{serviceItem?.train_type_label === "Tren Express (Nuevo)" && (
|
|
742
408
|
<div
|
|
743
409
|
className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] min-[420]:text-[12px] text-[10px] z-20 `}
|
|
@@ -755,6 +421,23 @@ function ServiceItemMobile({
|
|
|
755
421
|
)}
|
|
756
422
|
</div>
|
|
757
423
|
</div>
|
|
424
|
+
|
|
425
|
+
{/* 🔹 EXPANDABLE DROPDOWN (below the card) */}
|
|
426
|
+
<div
|
|
427
|
+
style={{
|
|
428
|
+
display: "grid",
|
|
429
|
+
gridTemplateRows: isItemExpanded ? "1fr" : "0fr",
|
|
430
|
+
opacity: isItemExpanded ? 1 : 0,
|
|
431
|
+
transition:
|
|
432
|
+
"grid-template-rows 0.3s ease-in-out, opacity 0.25s ease-in-out",
|
|
433
|
+
position: "relative",
|
|
434
|
+
zIndex: -1,
|
|
435
|
+
}}
|
|
436
|
+
>
|
|
437
|
+
<div style={{ overflow: "hidden", minHeight: 0, marginTop: "-10px" }}>
|
|
438
|
+
<ExpandedDropdownMobile serviceItem={serviceItem} />
|
|
439
|
+
</div>
|
|
440
|
+
</div>
|
|
758
441
|
</div>
|
|
759
442
|
);
|
|
760
443
|
}
|