kupos-ui-components-lib 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/README copy.md +125 -0
  2. package/README.md +125 -0
  3. package/build-css.js +28 -0
  4. package/copy-assets.js +45 -0
  5. package/dist/KuposUIComponent.d.ts +84 -0
  6. package/dist/KuposUIComponent.js +49 -0
  7. package/dist/ResponsiveServiceItem.d.ts +3 -0
  8. package/dist/ResponsiveServiceItem.js +10 -0
  9. package/dist/ServiceItemDesktop.d.ts +3 -0
  10. package/dist/ServiceItemDesktop.js +6 -0
  11. package/dist/ServiceItemMobile.d.ts +3 -0
  12. package/dist/ServiceItemMobile.js +5 -0
  13. package/dist/ServiceItemMobileView.d.ts +4 -0
  14. package/dist/ServiceItemMobileView.js +33 -0
  15. package/dist/ServiceItemPb.d.ts +4 -0
  16. package/dist/ServiceItemPb.js +486 -0
  17. package/dist/ServivceItemPbMobile.d.ts +4 -0
  18. package/dist/ServivceItemPbMobile.js +248 -0
  19. package/dist/assets/LottieIcon.d.ts +7 -0
  20. package/dist/assets/LottieIcon.js +8 -0
  21. package/dist/assets/LottieIcon.tsx +26 -0
  22. package/dist/assets/LottiePlayer.d.ts +20 -0
  23. package/dist/assets/LottiePlayer.js +24 -0
  24. package/dist/assets/LottiePlayer.tsx +63 -0
  25. package/dist/assets/PopupComponent.d.ts +12 -0
  26. package/dist/assets/PopupComponent.js +18 -0
  27. package/dist/assets/PopupComponent.tsx +65 -0
  28. package/dist/assets/images/amenities/Icon_More-Amenities.svg +1 -0
  29. package/dist/assets/images/amenities/Restrooms-white.svg +1 -0
  30. package/dist/assets/images/amenities/Restrooms.svg +1 -0
  31. package/dist/assets/images/amenities/air_condtion-white.svg +1 -0
  32. package/dist/assets/images/amenities/air_condtion.svg +1 -0
  33. package/dist/assets/images/amenities/amenity-cortina.png +0 -0
  34. package/dist/assets/images/amenities/baggage-white.svg +1 -0
  35. package/dist/assets/images/amenities/baggage.svg +1 -0
  36. package/dist/assets/images/amenities/charging_plug-white.svg +1 -0
  37. package/dist/assets/images/amenities/charging_plug.svg +17 -0
  38. package/dist/assets/images/amenities/coffee.svg +1 -0
  39. package/dist/assets/images/amenities/cortina_divisoria.svg +19 -0
  40. package/dist/assets/images/amenities/divider-curtain.svg +34 -0
  41. package/dist/assets/images/amenities/food_new_icon-white.svg +1 -0
  42. package/dist/assets/images/amenities/food_new_icon.svg +1 -0
  43. package/dist/assets/images/amenities/frazda_amenity.svg +11 -0
  44. package/dist/assets/images/amenities/handicap-white.svg +1 -0
  45. package/dist/assets/images/amenities/handicap.svg +1 -0
  46. package/dist/assets/images/amenities/icon-app-cortina.svg +19 -0
  47. package/dist/assets/images/amenities/mobile_ticket-white.svg +1 -0
  48. package/dist/assets/images/amenities/mobile_ticket.svg +29 -0
  49. package/dist/assets/images/amenities/movie-white.svg +1 -0
  50. package/dist/assets/images/amenities/movie.svg +1 -0
  51. package/dist/assets/images/amenities/music-white.svg +1 -0
  52. package/dist/assets/images/amenities/music.svg +1 -0
  53. package/dist/assets/images/amenities/snacks_new-white.svg +1 -0
  54. package/dist/assets/images/amenities/snacks_new.svg +27 -0
  55. package/dist/assets/images/amenities/whatsapp-charges-info-icon.svg +5 -0
  56. package/dist/assets/images/amenities/wifi-white.svg +1 -0
  57. package/dist/assets/images/amenities/wifi.svg +1 -0
  58. package/dist/assets/images/anims/service_list/flexible.json +391 -0
  59. package/dist/assets/images/anims/service_list/location.json +589 -0
  60. package/dist/assets/images/index.d.ts +32 -0
  61. package/dist/assets/images/index.js +35 -0
  62. package/dist/assets/images/index.ts +35 -0
  63. package/dist/components/InternationalServicePopupBody.d.ts +3 -0
  64. package/dist/components/InternationalServicePopupBody.js +21 -0
  65. package/dist/components/PaymentSideBar/PaymentSideBarDesktop.d.ts +4 -0
  66. package/dist/components/PaymentSideBar/PaymentSideBarDesktop.js +107 -0
  67. package/dist/components/PaymentSideBar/PaymentSideBarMobile.d.ts +4 -0
  68. package/dist/components/PaymentSideBar/PaymentSideBarMobile.js +115 -0
  69. package/dist/components/PaymentSideBar/ResponsivePaymentSideBar.d.ts +3 -0
  70. package/dist/components/PaymentSideBar/ResponsivePaymentSideBar.js +10 -0
  71. package/dist/components/PaymentSideBar/index.d.ts +5 -0
  72. package/dist/components/PaymentSideBar/index.js +4 -0
  73. package/dist/components/PaymentSideBar/types.d.ts +38 -0
  74. package/dist/components/PaymentSideBar/types.js +1 -0
  75. package/dist/components/ServiceItem/ResponsiveServiceItem.d.ts +3 -0
  76. package/dist/components/ServiceItem/ResponsiveServiceItem.js +10 -0
  77. package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +4 -0
  78. package/dist/components/ServiceItem/ServiceItemDesktop.js +486 -0
  79. package/dist/components/ServiceItem/ServiceItemMobile.d.ts +4 -0
  80. package/dist/components/ServiceItem/ServiceItemMobile.js +248 -0
  81. package/dist/components/ServiceItem/index.d.ts +5 -0
  82. package/dist/components/ServiceItem/index.js +4 -0
  83. package/dist/components/ServiceItem/mobileTypes.d.ts +141 -0
  84. package/dist/components/ServiceItem/mobileTypes.js +1 -0
  85. package/dist/components/ServiceItem/types.d.ts +164 -0
  86. package/dist/components/ServiceItem/types.js +1 -0
  87. package/dist/components/ServiceList/ResponsiveServiceList.d.ts +3 -0
  88. package/dist/components/ServiceList/ResponsiveServiceList.js +10 -0
  89. package/dist/components/ServiceList/ServiceListDesktop.d.ts +4 -0
  90. package/dist/components/ServiceList/ServiceListDesktop.js +164 -0
  91. package/dist/components/ServiceList/ServiceListMobile.d.ts +4 -0
  92. package/dist/components/ServiceList/ServiceListMobile.js +195 -0
  93. package/dist/components/ServiceList/index.d.ts +5 -0
  94. package/dist/components/ServiceList/index.js +4 -0
  95. package/dist/components/ServiceList/types.d.ts +35 -0
  96. package/dist/components/ServiceList/types.js +1 -0
  97. package/dist/example.d.ts +5 -0
  98. package/dist/example.js +240 -0
  99. package/dist/index.d.ts +13 -0
  100. package/dist/index.js +15 -0
  101. package/dist/mobileTypes.d.ts +141 -0
  102. package/dist/mobileTypes.js +1 -0
  103. package/dist/styles.css +803 -0
  104. package/dist/types.d.ts +151 -0
  105. package/dist/types.js +1 -0
  106. package/dist/utils/DateService.d.ts +16 -0
  107. package/dist/utils/DateService.js +160 -0
  108. package/dist/utils/ModalEventManager.d.ts +40 -0
  109. package/dist/utils/ModalEventManager.js +329 -0
  110. package/kupos-service-item-package-1.0.0.tgz +0 -0
  111. package/package.json +43 -0
  112. package/postcss.config.js +6 -0
  113. package/src/KuposUIComponent.tsx +152 -0
  114. package/src/ServiceItemPb.tsx +1048 -0
  115. package/src/assets/LottieIcon.tsx +26 -0
  116. package/src/assets/LottiePlayer.tsx +63 -0
  117. package/src/assets/PopupComponent.tsx +65 -0
  118. package/src/assets/images/amenities/Icon_More-Amenities.svg +1 -0
  119. package/src/assets/images/amenities/Restrooms-white.svg +1 -0
  120. package/src/assets/images/amenities/Restrooms.svg +1 -0
  121. package/src/assets/images/amenities/air_condtion-white.svg +1 -0
  122. package/src/assets/images/amenities/air_condtion.svg +1 -0
  123. package/src/assets/images/amenities/amenity-cortina.png +0 -0
  124. package/src/assets/images/amenities/baggage-white.svg +1 -0
  125. package/src/assets/images/amenities/baggage.svg +1 -0
  126. package/src/assets/images/amenities/charging_plug-white.svg +1 -0
  127. package/src/assets/images/amenities/charging_plug.svg +17 -0
  128. package/src/assets/images/amenities/coffee.svg +1 -0
  129. package/src/assets/images/amenities/cortina_divisoria.svg +19 -0
  130. package/src/assets/images/amenities/divider-curtain.svg +34 -0
  131. package/src/assets/images/amenities/food_new_icon-white.svg +1 -0
  132. package/src/assets/images/amenities/food_new_icon.svg +1 -0
  133. package/src/assets/images/amenities/frazda_amenity.svg +11 -0
  134. package/src/assets/images/amenities/handicap-white.svg +1 -0
  135. package/src/assets/images/amenities/handicap.svg +1 -0
  136. package/src/assets/images/amenities/icon-app-cortina.svg +19 -0
  137. package/src/assets/images/amenities/mobile_ticket-white.svg +1 -0
  138. package/src/assets/images/amenities/mobile_ticket.svg +29 -0
  139. package/src/assets/images/amenities/movie-white.svg +1 -0
  140. package/src/assets/images/amenities/movie.svg +1 -0
  141. package/src/assets/images/amenities/music-white.svg +1 -0
  142. package/src/assets/images/amenities/music.svg +1 -0
  143. package/src/assets/images/amenities/snacks_new-white.svg +1 -0
  144. package/src/assets/images/amenities/snacks_new.svg +27 -0
  145. package/src/assets/images/amenities/whatsapp-charges-info-icon.svg +5 -0
  146. package/src/assets/images/amenities/wifi-white.svg +1 -0
  147. package/src/assets/images/amenities/wifi.svg +1 -0
  148. package/src/assets/images/anims/service_list/flexible.json +391 -0
  149. package/src/assets/images/anims/service_list/location.json +589 -0
  150. package/src/assets/images/index.ts +35 -0
  151. package/src/components/InternationalServicePopupBody.tsx +40 -0
  152. package/src/components/PaymentSideBar/PaymentSideBarDesktop.tsx +183 -0
  153. package/src/components/PaymentSideBar/PaymentSideBarMobile.tsx +197 -0
  154. package/src/components/PaymentSideBar/ResponsivePaymentSideBar.tsx +14 -0
  155. package/src/components/PaymentSideBar/index.ts +5 -0
  156. package/src/components/PaymentSideBar/types.ts +44 -0
  157. package/src/components/ServiceItem/ResponsiveServiceItem.tsx +14 -0
  158. package/src/components/ServiceItem/ServiceItemDesktop.tsx +1048 -0
  159. package/src/components/ServiceItem/ServiceItemMobile.tsx +544 -0
  160. package/src/components/ServiceItem/index.ts +5 -0
  161. package/src/components/ServiceItem/mobileTypes.ts +159 -0
  162. package/src/components/ServiceItem/types.ts +163 -0
  163. package/src/components/ServiceList/ResponsiveServiceList.tsx +14 -0
  164. package/src/components/ServiceList/ServiceListDesktop.tsx +353 -0
  165. package/src/components/ServiceList/ServiceListMobile.tsx +400 -0
  166. package/src/components/ServiceList/index.ts +5 -0
  167. package/src/components/ServiceList/types.ts +43 -0
  168. package/src/dummyData.json +73 -0
  169. package/src/example.tsx +348 -0
  170. package/src/index.ts +37 -0
  171. package/src/lottie-player.d.ts +0 -0
  172. package/src/styles.css +77 -0
  173. package/src/types.ts +150 -0
  174. package/src/utils/DateService.ts +197 -0
  175. package/src/utils/ModalEventManager.ts +405 -0
  176. package/tailwind.config.js +39 -0
  177. package/tsconfig.json +18 -0
@@ -0,0 +1,544 @@
1
+ import React from "react";
2
+ import LottiePlayer from "../../assets/LottiePlayer";
3
+ import DateService from "../../utils/DateService";
4
+ import { MobileServiceItemProps } from "./mobileTypes";
5
+
6
+ const SEAT_EXCEPTIONS = ["Asiento mascota"];
7
+
8
+ const exceptions = [
9
+ "gy",
10
+ ".gy",
11
+ "GY",
12
+ ".GY",
13
+ "Gy",
14
+ ".Gy",
15
+ "BLANCO",
16
+ "blanco",
17
+ "asiento_mascota",
18
+ ];
19
+
20
+ function ServiceItemMobile({
21
+ serviceItem,
22
+ onBookButtonPress,
23
+ colors,
24
+ busStage,
25
+ orignLabel,
26
+ destinationLabel,
27
+ amenitiesData,
28
+ setShowDropdown,
29
+ showDropdown,
30
+ setAmenetiesAtomValue,
31
+ }: MobileServiceItemProps): React.ReactElement {
32
+ const isPetSeat = (Object.keys(serviceItem?.pet_seat_info) || []).length > 0;
33
+ let isSoldOut = serviceItem.available_seats <= 0;
34
+
35
+ const currency = (amount: number) => {
36
+ const formattedAmount = amount
37
+ .toString()
38
+ .replace(/\B(?=(\d{3})+(?!\d))/g, ",");
39
+ return "$" + formattedAmount;
40
+ };
41
+
42
+ const labelId =
43
+ typeof serviceItem.boarding_stages === "string"
44
+ ? serviceItem.boarding_stages.split("|")[0]
45
+ : "";
46
+
47
+ const showTopLabel =
48
+ busStage &&
49
+ busStage[labelId] &&
50
+ busStage[labelId].split("|")[1] === "true" &&
51
+ busStage[labelId].split("|")[0];
52
+
53
+ const getServiceStars = (serviceItem) => {
54
+ try {
55
+ return serviceItem.operator_details && serviceItem.operator_details[1]
56
+ ? serviceItem.operator_details[1].toFixed(1)
57
+ : "0.0";
58
+ } catch (e) {
59
+ return "";
60
+ }
61
+ };
62
+
63
+ const seatTypes = () => {
64
+ let seatTypes = serviceItem.seat_types
65
+ ?.filter((item) => getFilteredSeats(item.label))
66
+ ?.sort((a, b) => a.fare - b.fare) // Add this line to sort by fare
67
+ ?.slice(0, 2)
68
+ ?.map((type, i) =>
69
+ exceptions.includes(type.label) ? null : (
70
+ <div
71
+ className={
72
+ serviceItem.seat_types?.length > 2
73
+ ? "w-[100%] flex flex-row justify-between "
74
+ : "w-[100%] flex flex-row justify-between items-center"
75
+ }
76
+ key={i}
77
+ >
78
+ <span className="text-[13px] " style={{ marginLeft: "10px" }}>
79
+ {type.label}
80
+ </span>
81
+ <span
82
+ className={"text-[13px] bold-text"}
83
+ style={{ color: isSoldOut ? "#c0c0c0" : colors.priceColor }}
84
+ >
85
+ {currency(type.fare)}
86
+ </span>
87
+ </div>
88
+ )
89
+ );
90
+ return seatTypes;
91
+ };
92
+
93
+ const getFilteredSeats = (item) => {
94
+ return item;
95
+ };
96
+
97
+ const getAmenitiesImage = (name: string): string => {
98
+ switch (name) {
99
+ case "air_condtion.png": {
100
+ return serviceItem?.icons?.airConditionIcon;
101
+ }
102
+ case "baggage.png": {
103
+ return serviceItem?.icons?.baggageIcon;
104
+ }
105
+ case "charging_plug.png": {
106
+ return serviceItem?.icons?.chargingIcon;
107
+ }
108
+ case "coffee.png": {
109
+ return serviceItem?.icons?.coffeeIcon;
110
+ }
111
+ case "food_new_icon.png": {
112
+ return serviceItem?.icons?.foodIcon;
113
+ }
114
+ case "gaming.png": {
115
+ return serviceItem?.icons?.gamingIcon;
116
+ }
117
+ case "handicap.png": {
118
+ return serviceItem?.icons?.handicapIcon;
119
+ }
120
+ case "mobile_ticket.png": {
121
+ return serviceItem?.icons?.mobileTicketIcon;
122
+ }
123
+ case "movie.png": {
124
+ return serviceItem?.icons?.movieIcon;
125
+ }
126
+ case "restrooms.png": {
127
+ return serviceItem?.icons?.restroomsIcon;
128
+ }
129
+ case "snacks_new.png": {
130
+ return serviceItem?.icons?.snackIcon;
131
+ }
132
+ case "wifi.png": {
133
+ return serviceItem?.icons?.wifiIcon;
134
+ }
135
+ case "cortina_divisoria.png": {
136
+ return serviceItem?.icons?.cortinaIcon;
137
+ }
138
+ case "frazada.png": {
139
+ return serviceItem?.icons?.frazaIcon;
140
+ }
141
+ default: {
142
+ return "";
143
+ }
144
+ }
145
+ };
146
+
147
+ const amenities = () => {
148
+ const raw = serviceItem?.operator_details?.[3];
149
+ const list = Array.isArray(raw)
150
+ ? raw
151
+ : typeof raw === "string"
152
+ ? raw.split("|").filter(Boolean)
153
+ : [];
154
+
155
+ const nodes = list
156
+ .slice(0, 2)
157
+ .map((am, i) => (
158
+ <img
159
+ key={i}
160
+ className="amenity"
161
+ height={15}
162
+ src={getAmenitiesImage(amenitiesData?.[am]?.toLowerCase())}
163
+ alt="icon"
164
+ />
165
+ ));
166
+
167
+ return nodes;
168
+ };
169
+
170
+ const renderIcon = (iconKey: string, size: string = "14px") => {
171
+ const iconValue = serviceItem.icons?.[iconKey];
172
+ if (iconValue) {
173
+ if (typeof iconValue === "string") {
174
+ return (
175
+ <img
176
+ src={iconValue}
177
+ alt={iconKey}
178
+ className={`${`w-[${size}] h-[${size}]`} mr-[5px]`}
179
+ />
180
+ );
181
+ }
182
+ }
183
+ return null;
184
+ };
185
+
186
+ let isConexion = false;
187
+
188
+ if (serviceItem?.is_transpordo) {
189
+ isConexion = true;
190
+ }
191
+
192
+ return (
193
+ <div
194
+ className={`relative ${
195
+ serviceItem.offer_text || serviceItem?.is_direct_trip
196
+ ? "mb-[60px]"
197
+ : "mb-[20px]"
198
+ } ${
199
+ serviceItem?.is_direct_trip ||
200
+ isConexion ||
201
+ serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
202
+ showTopLabel
203
+ ? "mt-[30px]"
204
+ : "mt-[20px]"
205
+ } `}
206
+ style={{ backgroundColor: "#fff", zIndex: 1 }}
207
+ >
208
+ <div
209
+ className={"border border-[#E6E6E6] rounded-[20px]"}
210
+ style={{ backgroundColor: "#fff", zIndex: 1 }}
211
+ >
212
+ <div
213
+ className={`p-[15px] ${
214
+ serviceItem?.train_type_label === "Tren Express (Nuevo)" ||
215
+ showTopLabel ||
216
+ serviceItem?.is_direct_trip ||
217
+ serviceItem?.is_transpordo
218
+ ? "mt-[10px]"
219
+ : ""
220
+ }`}
221
+ >
222
+ {/* Header with operator info and favorite */}
223
+ <div className="flex justify-between mb-[8px]">
224
+ <div className="flex items-center w-[50%] justify-between">
225
+ <div className="w-[120px] overflow-y-hidden">
226
+ <img
227
+ src={serviceItem.operator_details[0]}
228
+ alt="service logo"
229
+ className={`w-[100px] h-auto object-contain ${
230
+ isSoldOut ? "grayscale" : ""
231
+ }`}
232
+ />
233
+ </div>
234
+ <div className="flex text-[13px] bold-text">
235
+ <img
236
+ src={serviceItem.icons.rating}
237
+ alt="origin"
238
+ className={`w-[10px] h-[10px] mr-[4px] object-contain mt-[2px] ${
239
+ isSoldOut ? "grayscale" : ""
240
+ }`}
241
+ />
242
+ {getServiceStars(serviceItem)}
243
+ </div>
244
+ </div>
245
+ <div className="flex justify-end -mt-[5px] -mb-[5px] items-center pt-[5px] pb-[5px] text-center ">
246
+ {serviceItem?.available_seats < 10 &&
247
+ serviceItem?.available_seats > 0 && (
248
+ <span
249
+ className="text-[12px] text-[red] mt-1 flex
250
+ justify-end
251
+
252
+
253
+ pt-[5px] pb-[5px] pl-[15px] pr-[15px]
254
+ rounded-[8px] bg-[#DE051414]"
255
+ >
256
+ ¡ Últimos Asientos!
257
+ </span>
258
+ )}
259
+ </div>
260
+ </div>
261
+
262
+ <div
263
+ className="flex justify-between gap-[5px] w-full"
264
+ onClick={onBookButtonPress}
265
+ >
266
+ {/* DATE AND TIME */}
267
+ <div className="min-h-[2.5rem] flex flex-col justify-between gap-[4px] w-[50%]">
268
+ <div
269
+ className={`flex items-center text-[13px] justify-between ${
270
+ isSoldOut ? "text-[#c0c0c0]" : ""
271
+ }`}
272
+ >
273
+ <div className="flex items-center bold-text capitalize group ">
274
+ {orignLabel ? (
275
+ <div className="w-[60px]">{orignLabel}</div>
276
+ ) : (
277
+ <div className="w-[14px] h-auto mr-[5px]">
278
+ <img
279
+ src={serviceItem.icons?.origin}
280
+ alt="origin"
281
+ className={`w-[14px] h-auto mr-[5px] ${
282
+ isSoldOut ? "grayscale" : ""
283
+ }`}
284
+ />
285
+ </div>
286
+ )}
287
+ <span className="cursor-pointer black-text">
288
+ {DateService.getServiceItemDate(serviceItem.travel_date)}
289
+ </span>
290
+ </div>
291
+ <div className="mx-[8px]">•</div>
292
+ <div className="font-[900] relative black-text">
293
+ {DateService.formatTime(serviceItem.dep_time)}
294
+ </div>
295
+ </div>
296
+ <div
297
+ className={`flex items-center text-[13px] justify-between ${
298
+ isSoldOut ? "text-[#c0c0c0]" : ""
299
+ }`}
300
+ >
301
+ <div className="flex items-center bold-text capitalize group ">
302
+ {destinationLabel ? (
303
+ <div className="w-[60px]">{destinationLabel}</div>
304
+ ) : (
305
+ <div className="w-[14px] h-auto mr-[5px]">
306
+ <img
307
+ src={serviceItem.icons?.destination}
308
+ className={`w-[14px] h-auto mr-[5px] ${
309
+ isSoldOut ? "grayscale" : ""
310
+ }`}
311
+ />
312
+ </div>
313
+ )}
314
+ <span className="cursor-pointer black-text">
315
+ {DateService.getServiceItemDate(serviceItem.arrival_date)}
316
+ </span>
317
+ </div>
318
+ <div className="mx-[8px]">•</div>
319
+ <div className="font-[900] black-text">
320
+ {DateService.formatTime(serviceItem.arr_time)}
321
+ </div>
322
+ </div>
323
+ </div>
324
+ {/* SEATS */}
325
+ <div className="content-center w-[47%]">
326
+ <div className="flex flex-col justify-between h-[2.5rem] gap-[5px]">
327
+ {seatTypes()}
328
+
329
+ {isSoldOut ? (
330
+ <div>
331
+ <span className={"text-[13px]"}>Agotado</span>
332
+ </div>
333
+ ) : null}
334
+ </div>
335
+ </div>
336
+ </div>
337
+ <div className="bg-[#E6E6E6] -ml-[12px] -mr-[12px] mt-[10px] mb-[10px] h-[1px]"></div>
338
+ <div
339
+ className={`${"flex justify-between items-center mt-[15px] items-center "}`}
340
+ >
341
+ {/* Rating */}
342
+ <div>
343
+ <div className="flex items-center ">
344
+ <div
345
+ className="flex items-center cursor-pointer "
346
+ style={{ color: isSoldOut ? "#c0c0c0" : "" }}
347
+ >
348
+ <span className="ml-[3px] text-[#464647] text-[13px] bold-text">
349
+ {serviceItem.operator_details[2]}
350
+ </span>
351
+ </div>
352
+ </div>
353
+ </div>
354
+
355
+ <div className="flex relative text-[#464647]">
356
+ <div
357
+ className={`w-[12px] h-auto mr-[2px] ${
358
+ isSoldOut ? "grayscale" : ""
359
+ }`}
360
+ >
361
+ {renderIcon("hours", "12px")}
362
+ </div>
363
+ <div
364
+ className={`cursor-default group text-[13px] ${
365
+ isSoldOut ? "text-[#c0c0c0]" : ""
366
+ }`}
367
+ >
368
+ {serviceItem.duration}hrs
369
+ </div>
370
+ </div>
371
+
372
+ <div>{amenities()}</div>
373
+
374
+ {(serviceItem.is_change_ticket || isPetSeat) && (
375
+ <div
376
+ onClick={() => {
377
+ setShowDropdown(!showDropdown);
378
+ setAmenetiesAtomValue({
379
+ service: serviceItem,
380
+ showTopLabel: showTopLabel,
381
+ });
382
+ }}
383
+ className="flex items-center"
384
+ >
385
+ {serviceItem.pet_seat_info &&
386
+ Object.keys(serviceItem.pet_seat_info).length > 0 ? (
387
+ <div className="flex items-center">
388
+ <div className={`relative group cursor-default `}>
389
+ <div className="flex items-center">
390
+ <div
391
+ className={`mr-[5px] ${isSoldOut ? "grayscale" : ""}`}
392
+ >
393
+ <LottiePlayer
394
+ animationData={serviceItem.icons.petFriendlyAnim}
395
+ width="20px"
396
+ height="20px"
397
+ />
398
+ </div>
399
+ </div>
400
+ </div>
401
+ </div>
402
+ ) : null}
403
+
404
+ {/* Flexible ticket */}
405
+ {serviceItem.is_change_ticket && (
406
+ <div className="flex items-center">
407
+ <div className="relative group cursor-default">
408
+ <div className="flex items-center">
409
+ <div
410
+ className={`mr-[5px] ${isSoldOut ? "grayscale" : ""}`}
411
+ >
412
+ <LottiePlayer
413
+ animationData={serviceItem.icons.flexibleAnim}
414
+ width="20px"
415
+ height="20px"
416
+ />
417
+ </div>
418
+ </div>
419
+ </div>
420
+ </div>
421
+ )}
422
+
423
+ {serviceItem?.is_tracking_enabled && (
424
+ <div className="flex items-center mr-[10px]">
425
+ <div
426
+ className={`h-auto mr-[4px] text-[13px] text-[#464647] ${
427
+ isSoldOut ? "grayscale" : ""
428
+ }`}
429
+ >
430
+ <LottiePlayer
431
+ animationData={serviceItem.icons.locationAnim}
432
+ width="20px"
433
+ height="20px"
434
+ />
435
+ </div>
436
+ </div>
437
+ )}
438
+
439
+ {(serviceItem.is_change_ticket || isPetSeat) && (
440
+ <img src={serviceItem.icons.plus} alt="icon" width={11} />
441
+ )}
442
+ </div>
443
+ )}
444
+ </div>
445
+ </div>
446
+
447
+ {serviceItem?.offer_text && (
448
+ <div
449
+ 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]`}
450
+ style={{
451
+ backgroundColor: isSoldOut ? "" : colors?.bottomStripColor,
452
+ zIndex: -1,
453
+ color: "#fff",
454
+ }}
455
+ >
456
+ <LottiePlayer
457
+ animationData={serviceItem.icons.promoAnim}
458
+ width="18px"
459
+ height="18px"
460
+ />
461
+ <span className="ml-[10px] text-[#fff] text-[13px]">
462
+ {serviceItem?.offer_text}
463
+ </span>
464
+ </div>
465
+ )}
466
+
467
+ <div className="absolute -top-[14px] left-0 w-full flex items-center justify-end gap-[12px] pr-[20px] z-10 ">
468
+ {showTopLabel && (
469
+ <div
470
+ className={`flex items-center gap-[2px] py-[5px] px-[10px] rounded-[38px] text-[12px] z-20 ${
471
+ isSoldOut ? "bg-[#ddd]" : ``
472
+ }`}
473
+ style={{
474
+ backgroundColor: !isSoldOut && colors.ratingBottomColor,
475
+ }}
476
+ >
477
+ <div className={isSoldOut ? "grayscale" : ""}>
478
+ <LottiePlayer
479
+ animationData={serviceItem.icons.priorityStageAnim}
480
+ width="18px"
481
+ height="18px"
482
+ />
483
+ </div>
484
+ <div
485
+ className={
486
+ isSoldOut ? "text-white" : `text-[${colors.topLabelColor}]`
487
+ }
488
+ >
489
+ {showTopLabel}
490
+ </div>
491
+ </div>
492
+ )}
493
+
494
+ {isConexion && (
495
+ <div
496
+ className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] text-[12px] z-20 ${
497
+ isSoldOut ? "text-white" : `text-[${colors.topLabelColor}]`
498
+ }`}
499
+ style={{
500
+ backgroundColor: !isSoldOut && colors.ratingBottomColor,
501
+ }}
502
+ >
503
+ {renderIcon("airportIcon", "14px")}
504
+
505
+ <div>Conexión</div>
506
+ </div>
507
+ )}
508
+ {serviceItem?.is_direct_trip && (
509
+ <div
510
+ className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] text-[12px] z-20 `}
511
+ style={{
512
+ backgroundColor: isSoldOut ? "#ddd" : colors.tooltipColor,
513
+ }}
514
+ >
515
+ <LottiePlayer
516
+ animationData={serviceItem.icons.directoAnim}
517
+ width="20px"
518
+ height="20px"
519
+ />
520
+ <div>Directo</div>
521
+ </div>
522
+ )}
523
+ {serviceItem?.train_type_label === "Tren Express (Nuevo)" && (
524
+ <div
525
+ className={`flex items-center gap-[2px] py-[5px] text-white px-[10px] rounded-[38px] text-[12px] z-20 `}
526
+ style={{
527
+ backgroundColor: isSoldOut ? "#ddd" : colors.tooltipColor,
528
+ }}
529
+ >
530
+ <LottiePlayer
531
+ animationData={serviceItem.icons.directoAnim}
532
+ width="20px"
533
+ height="20px"
534
+ />
535
+ <div>{"Tren Express"}</div>
536
+ </div>
537
+ )}
538
+ </div>
539
+ </div>
540
+ </div>
541
+ );
542
+ }
543
+
544
+ export default ServiceItemMobile;
@@ -0,0 +1,5 @@
1
+ import ServiceItemDesktop from "./ServiceItemDesktop";
2
+ import ServiceItemMobile from "./ServiceItemMobile";
3
+ import ResponsiveServiceItem from "./ResponsiveServiceItem";
4
+ export { ServiceItemDesktop, ServiceItemMobile, ResponsiveServiceItem };
5
+ export type { ServiceItemProps } from "./types";
@@ -0,0 +1,159 @@
1
+ import React from "react";
2
+
3
+ // Define types for ServiceItemPB component
4
+ export interface MobileServiceItemProps {
5
+ busStage?: Record<string, string>;
6
+ amenitiesData?: any;
7
+ serviceItem: {
8
+ id: string;
9
+ is_transpordo?: boolean;
10
+ operator_details: [
11
+ string,
12
+ string | number,
13
+ string,
14
+ string | string[],
15
+ string[],
16
+ number?,
17
+ Record<string, number>?,
18
+ boolean?,
19
+ number?,
20
+ boolean?,
21
+ ]; // [logo, rating, name, category, amenities, unknown, ratingData, unknown, unknown, unknown]
22
+ travel_date: string;
23
+ arrival_date: string;
24
+ dep_time: string;
25
+ arr_time: string;
26
+ available_seats: number;
27
+ busstages?: Record<string, string>;
28
+ seat_types: Array<{
29
+ label: string;
30
+ fare: number;
31
+ }>;
32
+ boarding_stages?:
33
+ | Array<{
34
+ label: string;
35
+ time: string;
36
+ }>
37
+ | {
38
+ label: string;
39
+ time: string;
40
+ }
41
+ | string;
42
+ dropoff_stages?:
43
+ | Array<{
44
+ label: string;
45
+ time: string;
46
+ }>
47
+ | {
48
+ label: string;
49
+ time: string;
50
+ };
51
+ pet_seat_info?: Record<string, any>;
52
+ is_change_ticket?: boolean;
53
+ change_ticket_hours?: number;
54
+ duration?: number;
55
+ train_type_label?: string;
56
+ offer_text?: string;
57
+ is_direct_trip?: boolean;
58
+ is_train_type?: boolean;
59
+ operator_service_name?: string;
60
+ dep_validation_text?: string;
61
+ metaData?: {};
62
+ is_tracking_enabled?: boolean;
63
+ show_top_label?: boolean;
64
+ lottie?: {
65
+ location?: string;
66
+ flexible?: string;
67
+ };
68
+ amenities?: Array<{
69
+ icon: string;
70
+ label: string;
71
+ }>;
72
+ rating_details?: {
73
+ bus_quality: number;
74
+ punctuality: number;
75
+ service_quality: number;
76
+ service_recommendation: number;
77
+ total_reviews: number;
78
+ };
79
+ icons?: {
80
+ origin?: string;
81
+ destination?: string;
82
+ rating?: string;
83
+ duration?: string;
84
+ hours?: string;
85
+ flexibleAnim?: string;
86
+ locationAnim?: string;
87
+ announcement?: string;
88
+ directo?: string;
89
+ directoAnim?: string;
90
+ petFriendlyAnim?: string;
91
+ priorityStageAnim?: string;
92
+ promoAnim?: string;
93
+ priority?: string;
94
+ changeTicket?: string;
95
+ plus?: string;
96
+ petSeat?: string;
97
+ warningIcon?: string;
98
+ soldOutIcon?: string;
99
+ airConditionIcon?: string;
100
+ baggageIcon?: string;
101
+ chargingIcon?: string;
102
+ coffeeIcon?: string;
103
+ foodIcon?: string;
104
+ gamingIcon?: string;
105
+ handicapIcon?: string;
106
+ mobileTicketIcon?: string;
107
+ movieIcon?: string;
108
+ restroomsIcon?: string;
109
+ snackIcon?: string;
110
+ wifiIcon?: string;
111
+ cortinaIcon?: string;
112
+ frazaIcon?: string;
113
+ airportIcon?: string;
114
+ [key: string]: string | Record<string, string | undefined> | undefined;
115
+ };
116
+ useLottieFor?: string[];
117
+ };
118
+ onBookButtonPress?: () => void;
119
+ terminals?: any[];
120
+ showDropdown?: boolean;
121
+ setShowDropdown?: (value: boolean) => void;
122
+ setAmenetiesAtomValue?: (
123
+ value:
124
+ | {
125
+ service: MobileServiceItemProps["serviceItem"];
126
+ showTopLabel: string | boolean;
127
+ }
128
+ | null
129
+ | ((curr:
130
+ | {
131
+ service: MobileServiceItemProps["serviceItem"];
132
+ showTopLabel: string | boolean;
133
+ }
134
+ | null) =>
135
+ | {
136
+ service: MobileServiceItemProps["serviceItem"];
137
+ showTopLabel: string | boolean;
138
+ }
139
+ | null)
140
+ ) => void;
141
+ hours?: number;
142
+ change_ticket_hours?: number;
143
+ colors: {
144
+ kuposButtonColor?: string;
145
+ topLabelColor?: string;
146
+ tooltipColor?: string;
147
+ ratingBorderColor?: string;
148
+ ratingBottomColor?: string;
149
+ priceColor?: string;
150
+ secondaryBgColor?: string;
151
+ secondaryTextColor?: string;
152
+ primaryButtonTextColor?: string;
153
+ bottomStripColor?: string;
154
+ };
155
+
156
+ orignLabel?: string;
157
+ destinationLabel?: string;
158
+ variant?: "desktop" | "mobile" | "auto";
159
+ }