kupos-ui-components-lib 9.11.7 → 9.11.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
  2. package/dist/components/ServiceItem/ServiceItemDesktop.js +22 -4
  3. package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
  4. package/dist/components/ServiceItem/ServiceItemMobile.js +1 -1
  5. package/dist/components/ServiceItem/mobileTypes.d.ts +1 -0
  6. package/dist/components/ServiceItem/types.d.ts +7 -0
  7. package/dist/styles.css +6 -0
  8. package/dist/ui/BottomAmenities/BottomAmenities.d.ts +2 -1
  9. package/dist/ui/BottomAmenities/BottomAmenities.js +4 -2
  10. package/dist/ui/DateTimeSection/DateTimeSection.js +4 -4
  11. package/dist/ui/SeatSection/SeatSection.d.ts +7 -1
  12. package/dist/ui/SeatSection/SeatSection.js +44 -12
  13. package/dist/ui/mobileweb/DateTimeSectionMobile.d.ts +2 -1
  14. package/dist/ui/mobileweb/DateTimeSectionMobile.js +13 -7
  15. package/dist/ui/mobileweb/SeatSectionMobile.d.ts +2 -1
  16. package/dist/ui/mobileweb/SeatSectionMobile.js +22 -15
  17. package/dist/utils/CommonService.d.ts +1 -1
  18. package/dist/utils/CommonService.js +5 -1
  19. package/package.json +1 -1
  20. package/src/components/ServiceItem/ServiceItemDesktop.tsx +47 -1
  21. package/src/components/ServiceItem/ServiceItemMobile.tsx +2 -1
  22. package/src/components/ServiceItem/mobileTypes.ts +31 -26
  23. package/src/components/ServiceItem/types.ts +12 -0
  24. package/src/ui/BottomAmenities/BottomAmenities.tsx +5 -1
  25. package/src/ui/DateTimeSection/DateTimeSection.tsx +4 -4
  26. package/src/ui/SeatSection/SeatSection.tsx +91 -21
  27. package/src/ui/mobileweb/DateTimeSectionMobile.tsx +47 -34
  28. package/src/ui/mobileweb/SeatSectionMobile.tsx +27 -12
  29. package/src/utils/CommonService.ts +7 -1
@@ -131,6 +131,13 @@ function ServiceItemPB({
131
131
  showLoginModal,
132
132
  isLoggedIn,
133
133
  showLoginOption,
134
+ isTrain,
135
+ selectedSeatKey,
136
+ onSeatSelect,
137
+ onTrainButtonClick,
138
+ showSeatSelectionError,
139
+ onShowSeatSelectionError,
140
+ onClearSeatSelectionError,
134
141
  isFeatureDropDownExpand,
135
142
  setIsFeatureDropDownExpand,
136
143
  ticketQuantity,
@@ -145,6 +152,15 @@ function ServiceItemPB({
145
152
  isFlores,
146
153
  operatorLabel,
147
154
  }: ServiceItemProps & { currencySign?: string }): React.ReactElement {
155
+ const handleSeatSelect = (
156
+ key: any,
157
+ price: number,
158
+ seatKey: string,
159
+ apiSeatType?: string,
160
+ ) => {
161
+ onClearSeatSelectionError?.();
162
+ onSeatSelect?.(key, price, seatKey, apiSeatType);
163
+ };
148
164
  const getAnimationIcon = (icon: string) => {
149
165
  const animation = ANIMATION_MAP[icon];
150
166
  if (!animation) return null;
@@ -366,6 +382,17 @@ function ServiceItemPB({
366
382
  return;
367
383
  }
368
384
 
385
+ if (isTrain) {
386
+ if (!selectedSeatKey) {
387
+ onShowSeatSelectionError?.(serviceItem.id);
388
+ return;
389
+ }
390
+ if (onTrainButtonClick) {
391
+ onTrainButtonClick();
392
+ return;
393
+ }
394
+ }
395
+
369
396
  onBookButtonPress();
370
397
  };
371
398
 
@@ -558,7 +585,9 @@ function ServiceItemPB({
558
585
  : "",
559
586
  }}
560
587
  >
561
- <div className="grid text-[#464647] w-full [grid-template-columns:20%_30%_2.5%_24%_15.5%] gap-x-[2%] items-center">
588
+ <div
589
+ className={`grid text-[#464647] w-full ${isTrain ? "[grid-template-columns:16%_30%_2.5%_28%_15.5%]" : "[grid-template-columns:20%_30%_2.5%_24%_15.5%]"} gap-x-[2%] items-center`}
590
+ >
562
591
  {/* OPERATOR LOGO */}
563
592
  <div className="flex flex-col gap-[5px]">
564
593
  <div>
@@ -620,6 +649,10 @@ function ServiceItemPB({
620
649
  isPeru={isPeru}
621
650
  renderIcon={renderIcon}
622
651
  discountSeatPriceColor={colors.discountSeatPriceColor}
652
+ isTrain={isTrain}
653
+ selectedSeatKey={selectedSeatKey}
654
+ onSeatSelect={handleSeatSelect}
655
+ topLabelColor={colors.topLabelColor}
623
656
  tooltipColor={colors.tooltipColor}
624
657
  />
625
658
  </div>
@@ -636,6 +669,18 @@ function ServiceItemPB({
636
669
  soldOutIcon={renderIcon("soldOutIcon", "14px")}
637
670
  onClick={checkMidnight}
638
671
  />
672
+ {showSeatSelectionError === serviceItem.id && isTrain && (
673
+ <div className="flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]">
674
+ <div
675
+ className="text-[9px] text-center whitespace-nowrap"
676
+ style={{
677
+ color: colors.seatPriceColor,
678
+ }}
679
+ >
680
+ Selecciona el tipo de servicio
681
+ </div>
682
+ </div>
683
+ )}
639
684
  {showLastSeats ? (
640
685
  <div className="flex justify-center mr-[11px] w-[100%] right-[0px] absolute left-[0] top-[40px]">
641
686
  {serviceItem?.available_seats < 10 &&
@@ -668,6 +713,7 @@ function ServiceItemPB({
668
713
  setIsExpand(isItemExpanded ? null : serviceItem.id)
669
714
  }
670
715
  isPeru={isPeru}
716
+ isTrain={isTrain}
671
717
  />
672
718
  </div>
673
719
  </div>
@@ -46,6 +46,8 @@ function ServiceItemMobile({
46
46
  removeDuplicateSeats,
47
47
  isLinatal,
48
48
  viewersConfig,
49
+ operatorLabel,
50
+ isTrain,
49
51
  isFeatureDropDownExpand,
50
52
  setIsFeatureDropDownExpand,
51
53
  ticketQuantity,
@@ -61,7 +63,6 @@ function ServiceItemMobile({
61
63
  onTimeDropdownToggle,
62
64
  wowDealData,
63
65
  isFlores,
64
- operatorLabel
65
66
  }: MobileServiceItemProps): React.ReactElement {
66
67
  const isItemExpanded = serviceItem.id === isExpanded;
67
68
  const isPetSeat = (Object.keys(serviceItem?.pet_seat_info) || []).length > 0;
@@ -135,36 +135,36 @@ export interface MobileServiceItemProps {
135
135
  bombAnim?: string;
136
136
  whiteBoardingIcon?: string;
137
137
  downArrow?: string;
138
- personIcon?: string
138
+ personIcon?: string;
139
139
  specialDeparture?: string;
140
140
  fireIcon?: string;
141
141
  directoIcon?: string;
142
- whiteFireIcon?: string
143
- femaleAnim?:string
144
- thunderAnim?: string
145
- personsAnim?: string
146
- whiteOrigin?: string,
147
- whiteDestination?: string,
148
- userIcon?: string,
149
-
150
- sheildIcon?: string,
151
- busIcon?: string,
152
- whiteDownArrow?: string,
153
- empressaIcon?: string,
154
- flexibleIcon?: string,
155
- listoIcon?: string,
156
- precioIcon?: string,
157
- confirmarIcon?: string
142
+ whiteFireIcon?: string;
143
+ femaleAnim?: string;
144
+ thunderAnim?: string;
145
+ personsAnim?: string;
146
+ whiteOrigin?: string;
147
+ whiteDestination?: string;
148
+ userIcon?: string;
149
+
150
+ sheildIcon?: string;
151
+ busIcon?: string;
152
+ whiteDownArrow?: string;
153
+ empressaIcon?: string;
154
+ flexibleIcon?: string;
155
+ listoIcon?: string;
156
+ precioIcon?: string;
157
+ confirmarIcon?: string;
158
158
  cancelTicketIcon?: string;
159
159
  changeTicketIcon?: string;
160
160
  petFriendlyIcon?: string;
161
- womenSeatIcon?: string
161
+ womenSeatIcon?: string;
162
162
  [key: string]: string | Record<string, string | undefined> | undefined;
163
163
  };
164
164
  useLottieFor?: string[];
165
165
  };
166
166
  onBookButtonPress?: () => void;
167
- onRemateUiButtonClick?: ()=> void;
167
+ onRemateUiButtonClick?: () => void;
168
168
  terminals?: any[];
169
169
  showDropdown?: boolean;
170
170
  setShowDropdown?: (value: boolean) => void;
@@ -208,7 +208,7 @@ export interface MobileServiceItemProps {
208
208
  seatPriceColor?: string;
209
209
  rightGradiantColor?: string;
210
210
  leftGradiantColor?: string;
211
- discountSeatPriceColor?: string
211
+ discountSeatPriceColor?: string;
212
212
  };
213
213
  isCiva?: boolean;
214
214
  currencySign?: string;
@@ -221,23 +221,28 @@ export interface MobileServiceItemProps {
221
221
  showLastSeats?: boolean;
222
222
  removeDuplicateSeats?: boolean;
223
223
  isLinatal?: boolean;
224
- viewersConfig?: {
224
+ viewersConfig?: {
225
225
  min: number;
226
226
  max: number;
227
227
  interval?: number; // ms, default 5000
228
228
  label?: string; // e.g. "personas están viendo este viaje"
229
229
  icon?: string; // optional icon URL
230
230
  };
231
- isFeatureDropDownExpand?: any;
231
+ isTrain?: boolean;
232
+ isFeatureDropDownExpand?: any;
232
233
  setIsFeatureDropDownExpand?: (value: any) => void;
233
234
  ticketQuantity?: number;
234
- onIncreaseTicketQuantity?: (serviceItem: MobileServiceItemProps["serviceItem"]) => void;
235
- onDecreaseTicketQuantity?: (serviceItem: MobileServiceItemProps["serviceItem"]) => void;
235
+ onIncreaseTicketQuantity?: (
236
+ serviceItem: MobileServiceItemProps["serviceItem"],
237
+ ) => void;
238
+ onDecreaseTicketQuantity?: (
239
+ serviceItem: MobileServiceItemProps["serviceItem"],
240
+ ) => void;
236
241
  cityOrigin?: { value: number; label: string };
237
242
  cityDestination?: { value: number; label: string };
238
- isNewUi?: boolean
243
+ isNewUi?: boolean;
239
244
 
240
- selectedTimeSlot?: string;
245
+ selectedTimeSlot?: string;
241
246
  onTimeSlotChange?: (slot: string) => void;
242
247
  isTimeDropdownOpen?: string | number | null;
243
248
  onTimeDropdownToggle?: (id?: string | number | null) => void;
@@ -252,6 +252,18 @@ export interface ServiceItemProps {
252
252
  showLoginModal?: any;
253
253
  isLoggedIn?: any;
254
254
  showLoginOption?: boolean;
255
+ isTrain?: boolean;
256
+ selectedSeatKey?: any;
257
+ onSeatSelect?: (
258
+ key: any,
259
+ price: number,
260
+ seatKey: string,
261
+ apiSeatType?: string,
262
+ ) => void;
263
+ onTrainButtonClick?: any;
264
+ showSeatSelectionError?: string | null;
265
+ onShowSeatSelectionError?: (serviceId: string) => void;
266
+ onClearSeatSelectionError?: () => void;
255
267
  selectedTimeSlot?: string;
256
268
  onTimeSlotChange?: (slot: string) => void;
257
269
  isTimeDropdownOpen?: string | number | null;
@@ -28,6 +28,7 @@ interface BottomAmenitiesProps {
28
28
  downArrowIcon?: React.ReactNode;
29
29
  onToggleExpand: () => void;
30
30
  isPeru?: boolean;
31
+ isTrain?: boolean;
31
32
  }
32
33
 
33
34
  function BottomAmenities({
@@ -42,6 +43,7 @@ function BottomAmenities({
42
43
  downArrowIcon,
43
44
  onToggleExpand,
44
45
  isPeru,
46
+ isTrain,
45
47
  }: BottomAmenitiesProps): React.ReactElement {
46
48
  const hasPetInfo =
47
49
  serviceItem.pet_seat_info &&
@@ -59,7 +61,9 @@ function BottomAmenities({
59
61
  className="grid items-center gap-[2%] flex-1 "
60
62
  style={{
61
63
  // gridTemplateColumns: " 28% 21% 23% 23%",
62
- gridTemplateColumns: "25.3% 17% 23% 23%",
64
+ gridTemplateColumns: isTrain
65
+ ? "20.6% 17% 23% 23%"
66
+ : "25.3% 17% 23% 23%",
63
67
  }}
64
68
  >
65
69
  {otherItems.map((item) => (
@@ -119,7 +119,7 @@ function DateTimeSection({
119
119
  metaData={metaData}
120
120
  colors={colors}
121
121
  >
122
- <span className="cursor-pointer bold-text capitalize">
122
+ <span className="cursor-pointer bold-text capitalize whitespace-nowrap">
123
123
  {DateService.getServiceItemDate(serviceItem.travel_date)}
124
124
  </span>
125
125
  </StageTooltip>
@@ -134,7 +134,7 @@ function DateTimeSection({
134
134
  metaData={metaData}
135
135
  colors={colors}
136
136
  >
137
- <span className="cursor-pointer bold-text capitalize">
137
+ <span className="cursor-pointer bold-text capitalize whitespace-nowrap">
138
138
  {DateService.getServiceItemDate(serviceItem.arrival_date)}
139
139
  </span>
140
140
  </StageTooltip>
@@ -169,7 +169,7 @@ function DateTimeSection({
169
169
  metaData={metaData}
170
170
  colors={colors}
171
171
  >
172
- <div className="font-[900] bold-text">
172
+ <div className="font-[900] bold-text whitespace-nowrap">
173
173
  {isLinatal ? (
174
174
  <>
175
175
  {cleanedDepTime} <span>{hasPM ? "PM" : hasAM ? "AM" : ""}</span>
@@ -193,7 +193,7 @@ function DateTimeSection({
193
193
  metaData={metaData}
194
194
  colors={colors}
195
195
  >
196
- <div className="font-[900] bold-text">
196
+ <div className="font-[900] bold-text whitespace-nowrap">
197
197
  {removeArrivalTime
198
198
  ? "\u00A0"
199
199
  : serviceItem.arr_time
@@ -7,6 +7,8 @@ interface SeatType {
7
7
  label: string;
8
8
  fare: number;
9
9
  key: any;
10
+ apiSeatType?: string;
11
+ api_seat_type?: string;
10
12
  }
11
13
 
12
14
  interface SeatSectionProps {
@@ -21,6 +23,15 @@ interface SeatSectionProps {
21
23
  serviceItem?: any;
22
24
  renderIcon?: (iconKey: string, size?: string) => React.ReactNode;
23
25
  discountSeatPriceColor?: string;
26
+ isTrain?: boolean;
27
+ selectedSeatKey?: any;
28
+ onSeatSelect?: (
29
+ key: any,
30
+ price: number,
31
+ seatKey: string,
32
+ apiSeatType?: string,
33
+ ) => void;
34
+ topLabelColor?: string;
24
35
  tooltipColor?: string;
25
36
  }
26
37
 
@@ -32,6 +43,8 @@ function getAllSeatTypes(seatTypes: SeatType[]) {
32
43
  let seatTypesWithPrices = seatTypes.filter(Boolean).map((val) => ({
33
44
  label: val?.label,
34
45
  price: val?.fare,
46
+ key: val?.key,
47
+ apiSeatType: val?.apiSeatType || val?.api_seat_type,
35
48
  }));
36
49
 
37
50
  seatTypesWithPrices.sort((a, b) => a.price - b.price);
@@ -39,7 +52,7 @@ function getAllSeatTypes(seatTypes: SeatType[]) {
39
52
  return seatTypesWithPrices;
40
53
  }
41
54
 
42
- function getSortedSeatTypes(seatTypes: SeatType[]) {
55
+ function getSortedSeatTypes(seatTypes: SeatType[], isTrain: any) {
43
56
  if (!seatTypes?.length) {
44
57
  return [{ label: "Salon cama", price: 0 }];
45
58
  }
@@ -53,7 +66,9 @@ function getSortedSeatTypes(seatTypes: SeatType[]) {
53
66
  seatTypesWithPrices[2] = seatTypesWithPrices[premiumIndex];
54
67
  }
55
68
 
56
- seatTypesWithPrices = seatTypesWithPrices.slice(0, 2);
69
+ if (!isTrain) {
70
+ seatTypesWithPrices = seatTypesWithPrices.slice(0, 2);
71
+ }
57
72
 
58
73
  const seenPrices = new Set<number>();
59
74
  seatTypesWithPrices = seatTypesWithPrices.filter((seat) => {
@@ -98,15 +113,19 @@ function SeatSection({
98
113
  priceColor,
99
114
  currencySign,
100
115
  removeDuplicateSeats,
116
+ selectedSeatKey,
117
+ onSeatSelect,
101
118
  isPeru,
102
119
  serviceItem,
103
120
  renderIcon,
104
121
  dpSeatColor,
105
122
  discountSeatPriceColor,
123
+ isTrain,
124
+ topLabelColor,
106
125
  tooltipColor,
107
126
  }: SeatSectionProps): React.ReactElement {
108
127
  const uniqueSeats = getUniqueSeats(seatTypes);
109
- const sortedSeatTypes = getSortedSeatTypes(seatTypes);
128
+ const sortedSeatTypes = getSortedSeatTypes(seatTypes, isTrain);
110
129
  const numberOfSeats = getNumberOfSeats(seatTypes);
111
130
  const isCentered = numberOfSeats < 2 || removeDuplicateSeats;
112
131
 
@@ -118,22 +137,68 @@ function SeatSection({
118
137
  const renderSeatNames = () => {
119
138
  const seats = removeDuplicateSeats ? uniqueSeats : sortedSeatTypes;
120
139
 
121
- return seats.map((val, key: number) =>
122
- SEAT_EXCEPTIONS.includes(val.label) ? null : (
123
- <span
124
- key={key}
125
- className={`flex items-center justify-between text-[13.33px] ${
126
- isSoldOut ? "text-[#c0c0c0]" : ""
127
- }`}
140
+ return seats.map((val, key: number) => {
141
+ return SEAT_EXCEPTIONS.includes(val.label) ? null : (
142
+ <div
143
+ className="flex items-center"
144
+ style={isTrain ? { cursor: "pointer" } : undefined}
145
+ onClick={
146
+ isTrain && !isSoldOut
147
+ ? () =>
148
+ val.label === selectedSeatKey
149
+ ? onSeatSelect?.(null, 0, "", "")
150
+ : onSeatSelect?.(
151
+ val.label,
152
+ val.price,
153
+ val.key,
154
+ (val as any).apiSeatType,
155
+ )
156
+ : undefined
157
+ }
128
158
  >
129
- {typeof val.label === "string" || typeof val.label === "number"
130
- ? removeDuplicateSeats && isPeru
131
- ? CommonService.truncateSeatLabel(val.label)
132
- : val.label
133
- : null}
134
- </span>
135
- ),
136
- );
159
+ {isTrain && (
160
+ <div
161
+ style={{
162
+ border: `1px solid ${val.label === selectedSeatKey ? topLabelColor : "#ccc"}`,
163
+ borderRadius: "50%",
164
+ width: "14px",
165
+ height: "14px",
166
+ minWidth: "14px",
167
+ marginRight: "10px",
168
+ display: "flex",
169
+ alignItems: "center",
170
+ justifyContent: "center",
171
+ }}
172
+ >
173
+ {val.label === selectedSeatKey && (
174
+ <div
175
+ style={{
176
+ backgroundColor: topLabelColor,
177
+ borderRadius: "50%",
178
+ width: "7px",
179
+ height: "7px",
180
+ }}
181
+ />
182
+ )}
183
+ </div>
184
+ )}
185
+ <span
186
+ key={key}
187
+ className={`flex items-center justify-between text-[13.33px] whitespace-nowrap ${
188
+ isSoldOut ? "text-[#c0c0c0]" : ""
189
+ }`}
190
+ >
191
+ {typeof val.label === "string" || typeof val.label === "number"
192
+ ? removeDuplicateSeats && isPeru
193
+ ? CommonService.truncateSeatLabel(val.label)
194
+ : isTrain
195
+ ? CommonService.capitalize(String(val.label))
196
+ : val.label
197
+ : null}
198
+ </span>
199
+ </div>
200
+ );
201
+ });
137
202
  };
138
203
 
139
204
  const renderSeatPrices = () => {
@@ -239,6 +304,7 @@ function SeatSection({
239
304
  }
240
305
  return null;
241
306
  })();
307
+ console.log("🚀 ~ SeatSection ~ serviceItem:", serviceItem);
242
308
 
243
309
  // Hide the % OFF badge when max_discount is capping the percentage discount
244
310
  // (i.e. both percentage and max_discount exist, and the raw % amount exceeds the cap)
@@ -310,7 +376,9 @@ function SeatSection({
310
376
 
311
377
  <span className="text-[13.33px] flex flex-col">
312
378
  {operatorServiceName ? (
313
- <span className="text-[13.33px]">{seatLabel}</span>
379
+ <span className="text-[13.33px] whitespace-nowrap">
380
+ {seatLabel}
381
+ </span>
314
382
  ) : (
315
383
  <span className="text-[13.33px]">Desde</span>
316
384
  )}
@@ -533,7 +601,7 @@ function SeatSection({
533
601
  style={{ textAlign: "center" }}
534
602
  >
535
603
  <span
536
- className="text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative"
604
+ className="text-[13.33px] font-normal leading-[20px] text-[#9f9f9f] relative whitespace-nowrap"
537
605
  style={{
538
606
  position: "relative",
539
607
  }}
@@ -595,7 +663,9 @@ function SeatSection({
595
663
  color: isSoldOut ? "#c0c0c0" : priceColor,
596
664
  top: 0,
597
665
  bottom: 0,
598
- left: "clamp(60%, 65% + (100vw - 1300px) * 0.1, 65%)",
666
+ left: isTrain
667
+ ? "73%"
668
+ : "clamp(60%, 65% + (100vw - 1300px) * 0.1, 65%)",
599
669
  right: 0,
600
670
  justifyContent: isCentered ? "center" : "",
601
671
  gap: "10px",
@@ -25,6 +25,7 @@ interface DateTimeSectionMobileProps {
25
25
  tooltipBgColor?: string;
26
26
  showLastSeats?: boolean;
27
27
  discountSeatPriceColor?: string;
28
+ isTrain?: boolean;
28
29
  }
29
30
 
30
31
  const pad = (n: number) => (n < 10 ? "0" + n : String(n));
@@ -67,41 +68,47 @@ const TimeRow: React.FC<TimeRowProps> = ({
67
68
  isSoldOut,
68
69
  }) => {
69
70
  const formattedDate = DateService.getServiceItemDate(date);
70
- const dotPositionClass = formattedDate.includes("dom") ? "max-[399px]:left-[53%]" : "";
71
- return <div
72
- className={`flex items-center min-[420]:text-[13px] text-[12px] justify-between ${
73
- isSoldOut ? "text-[#c0c0c0]" : ""
74
- }`}
75
- >
76
- <div className="flex items-center" style={{ flex: 1 }}>
77
- <div>
78
- {" "}
79
- {label ? (
80
- <div className="w-[60px]">{label}</div>
81
- ) : (
82
- <div className="w-[12px] h-auto mr-[5px]">
83
- <img
84
- src={icon}
85
- alt={alt}
86
- className={`w-[12px] h-auto mr-[5px] ${
87
- isSoldOut ? "grayscale" : ""
88
- }`}
89
- />
71
+ const dotPositionClass = formattedDate.includes("dom")
72
+ ? "max-[399px]:left-[53%]"
73
+ : "";
74
+ return (
75
+ <div
76
+ className={`flex items-center min-[420]:text-[13px] text-[12px] justify-between ${
77
+ isSoldOut ? "text-[#c0c0c0]" : ""
78
+ }`}
79
+ >
80
+ <div className="flex items-center" style={{ flex: 1 }}>
81
+ <div>
82
+ {" "}
83
+ {label ? (
84
+ <div className="w-[60px]">{label}</div>
85
+ ) : (
86
+ <div className="w-[12px] h-auto mr-[5px]">
87
+ <img
88
+ src={icon}
89
+ alt={alt}
90
+ className={`w-[12px] h-auto mr-[5px] ${
91
+ isSoldOut ? "grayscale" : ""
92
+ }`}
93
+ />
94
+ </div>
95
+ )}
96
+ </div>
97
+ <div
98
+ className="flex items-center relative capitalize justify-between"
99
+ style={{ flex: 1 }}
100
+ >
101
+ <span className="cursor-pointer black-text whitespace-nowrap">
102
+ {formattedDate}
103
+ </span>
104
+ <div className={`absolute left-[50%] ${dotPositionClass}`}>•</div>
105
+ <div className="font-[900] relative black-text whitespace-nowrap">
106
+ {timeContent}
90
107
  </div>
91
- )}
92
- </div>
93
- <div
94
- className="flex items-center relative capitalize justify-between"
95
- style={{ flex: 1 }}
96
- >
97
- <span className="cursor-pointer black-text">
98
- {formattedDate}
99
- </span>
100
- <div className={`absolute left-[50%] ${dotPositionClass}`}>•</div>
101
- <div className="font-[900] relative black-text">{timeContent}</div>
108
+ </div>
102
109
  </div>
103
110
  </div>
104
- </div>;
111
+ );
105
112
  };
106
113
 
107
114
  function DateTimeSectionMobile({
@@ -127,6 +134,7 @@ function DateTimeSectionMobile({
127
134
  tooltipBgColor,
128
135
  showLastSeats,
129
136
  discountSeatPriceColor,
137
+ isTrain,
130
138
  }: DateTimeSectionMobileProps): React.ReactElement {
131
139
  const { cleaned: cleanedDepTime, hasAM, hasPM } = getCleanedDepTime(depTime);
132
140
 
@@ -153,8 +161,12 @@ function DateTimeSectionMobile({
153
161
  >
154
162
  {/* DATE AND TIME */}
155
163
  <div
156
- className="min-h-[2.5rem] flex flex-col justify-between gap-[4px] w-[50%] "
157
- style={{ justifyContent: isCiva && "center" }}
164
+ className={`flex flex-col gap-[4px] w-[50%] ${isTrain ? "justify-center" : "justify-between"}`}
165
+ style={{
166
+ justifyContent: isCiva && "center",
167
+ minHeight: isTrain ? undefined : "2.5rem",
168
+ alignSelf: isTrain ? "stretch" : undefined,
169
+ }}
158
170
  >
159
171
  <TimeRow
160
172
  label={orignLabel}
@@ -198,6 +210,7 @@ function DateTimeSectionMobile({
198
210
  tooltipBgColor={tooltipBgColor}
199
211
  showLastSeats={showLastSeats}
200
212
  discountSeatPriceColor={discountSeatPriceColor}
213
+ isTrain={isTrain}
201
214
  />
202
215
  </div>
203
216
  );