kupos-ui-components-lib 10.4.39 → 10.4.41

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.
@@ -120,6 +120,9 @@ class DiscountBannersMobile extends React.Component {
120
120
  React.createElement("span", { className: `bold-text flex-shrink-0 rounded-full text-center text-[#464647] overflow-hidden whitespace-nowrap ${sizeClasses.chip}`, style: chipPillInArt
121
121
  ? undefined
122
122
  : { backgroundColor: "rgba(255,255,255,0.55)" } }, label),
123
+ showFlamePercent && (React.createElement("span", { className: `bold-text absolute text-[#ffffff] text-center pointer-events-none ${sizeClasses.flameBadge}`, style: Object.assign(Object.assign({}, FLAME_CENTER), { transform: "translate(-50%, -50%)", textShadow: "0 1px 2px rgba(0,0,0,0.28)", fontWeight: 900, whiteSpace: "nowrap" }) },
124
+ card.amount,
125
+ React.createElement("span", { className: sizeClasses.flamePercent, style: { fontWeight: 700 } }, "%"))),
123
126
  React.createElement("span", { className: `flex flex-col ${sizeClasses.column}` },
124
127
  React.createElement("span", { className: `bold-text text-[#464647] ${sizeClasses.discount}` }, card.discountLabel),
125
128
  React.createElement("span", { className: `bold-text ${sizeClasses.subtitle}`, style: { color: accentColor } }, card.subtitle))));
@@ -1,12 +1,13 @@
1
- import greenArt from "../../assets/images/discount/instant.png";
1
+ import greenArt from "../../assets/images/discount/green_new.png";
2
2
  import yellowArt from "../../assets/images/discount/yellow.png";
3
3
  import blueArt from "../../assets/images/discount/blue.png";
4
- import lastMinuteArt from "../../assets/images/discount/last.png";
5
- import firstTimeArt from "../../assets/images/discount/first.png";
4
+ import lastMinuteArt from "../../assets/images/discount/last_minute.png";
5
+ import firstTimeArt from "../../assets/images/discount/purple.png";
6
6
  import cashbackArt from "../../assets/images/discount/cash.png";
7
- import roundTripArt from "../../assets/images/discount/round.png";
8
- import promoCodeArt from "../../assets/images/discount/promo.png";
7
+ import roundTripArt from "../../assets/images/discount/green_rt.png";
8
+ import promoCodeArt from "../../assets/images/discount/yellow.png";
9
9
  import seatLevelArt from "../../assets/images/discount/seat.png";
10
+ import instantArt from "../../assets/images/discount/yellow_instant.png";
10
11
  export function toImageUrl(art) {
11
12
  if (typeof art === "string")
12
13
  return art;
@@ -27,11 +28,11 @@ export const DEFAULT_BACKGROUND_IMAGES = [
27
28
  blueArt,
28
29
  ].map(toImageUrl);
29
30
  export const CAMPAIGN_ART = {
30
- last_minute: { image: toImageUrl(lastMinuteArt), accent: "#4457C7" },
31
- first_time: { image: toImageUrl(firstTimeArt), accent: "#D63384" },
31
+ last_minute: { image: toImageUrl(lastMinuteArt), accent: "#1633DB" },
32
+ first_time: { image: toImageUrl(firstTimeArt), accent: "#FB488E" },
32
33
  cashback: { image: toImageUrl(cashbackArt), accent: "#0069D1" },
33
- round_trip: { image: toImageUrl(roundTripArt), accent: "#5C8A00" },
34
- instant_discount: { image: toImageUrl(promoCodeArt), accent: "#E08A00" },
34
+ round_trip: { image: toImageUrl(roundTripArt), accent: "#107E23" },
35
+ instant_discount: { image: toImageUrl(instantArt), accent: "#FDA105" },
35
36
  seat_level: { image: toImageUrl(seatLevelArt), accent: "#B87500" },
36
- promo_code: { image: toImageUrl(seatLevelArt), accent: "#B87500" },
37
+ promo_code: { image: toImageUrl(promoCodeArt), accent: "#FFC000" },
37
38
  };
@@ -117,9 +117,15 @@ function PeruSeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, cur
117
117
  // Single seat type → original behaviour (one lowest-fare price)
118
118
  const allSeats = getAllSeatTypes(seatTypes);
119
119
  const lowestFare = allSeats.length > 0 ? allSeats[0].price : 0;
120
- const { discountedPrice } = CommonService.calculateDiscountedPrice(lowestFare, serviceItem);
121
- return (React.createElement(React.Fragment, null,
122
- React.createElement("span", { className: "flex items-center text-[13.33px] bold-text" }, formatPrice(discountedPrice))));
120
+ const { originalPrice, discountedPrice } = CommonService.calculateDiscountedPrice(lowestFare, serviceItem);
121
+ const price = (React.createElement("span", { className: "flex items-center text-[13.33px] bold-text" }, formatPrice(showOriginalFare ? originalPrice : discountedPrice)));
122
+ // Inclination fares sit under "Desde", same as the stacked rows above.
123
+ if (hasInclination) {
124
+ return (React.createElement("div", { className: "relative" },
125
+ React.createElement("span", { className: "text-[12px] font-normal text-[#6a6a6a] absolute", style: { top: "-15px" } }, "Desde"),
126
+ price));
127
+ }
128
+ return price;
123
129
  };
124
130
  const seats = removeDuplicateSeats ? uniqueSeats : sortedSeatTypes;
125
131
  const discountedSeats = seats.map((seat) => (Object.assign(Object.assign({}, seat), CommonService.calculateDiscountedPrice(seat.price, serviceItem))));
@@ -134,6 +140,7 @@ function PeruSeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, cur
134
140
  // Tier B (ui_type 1) announces the offer elsewhere, so the fare itself must
135
141
  // render exactly as it would with no discount.
136
142
  const showOriginalFare = hasDiscount && uiType === 1;
143
+ const hasStrikeOff = hasDiscount && !showOriginalFare;
137
144
  const discountType = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discount_type;
138
145
  const discountValueRaw = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.discount_value;
139
146
  const maxDiscount = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.max_discount;
@@ -189,35 +196,20 @@ function PeruSeatSection({ seatTypes, availableSeats, isSoldOut, priceColor, cur
189
196
  : filteredSeats[0].label
190
197
  : null;
191
198
  return (React.createElement(React.Fragment, null,
192
- hasDiscount && (React.createElement("span", { className: "text-[13.33px]", style: {
199
+ hasStrikeOff && (React.createElement("span", { className: "text-[13.33px]", style: {
193
200
  color: "#999",
194
201
  } }, "Antes")),
195
- React.createElement("span", { className: "text-[13.33px] flex flex-col" }, !hasDiscount ? (React.createElement("span", { className: "text-[13.33px] whitespace-nowrap flex items-center", style: {
202
+ React.createElement("span", { className: "text-[13.33px] flex flex-col" }, !hasStrikeOff ? (React.createElement("span", { className: "text-[13.33px] whitespace-nowrap flex items-center", style: {
196
203
  opacity: isSoldOut ? 0.5 : 1,
197
204
  } },
198
- isSeatIcon && !hasDiscount && (React.createElement("img", { src: getSeatTypeIcon(seatLabel, serviceItem), alt: "seattype", style: {
205
+ isSeatIcon && (React.createElement("img", { src: getSeatTypeIcon(seatLabel, serviceItem), alt: "seattype", style: {
199
206
  width: "20px",
200
207
  height: "20px",
201
208
  marginRight: "5px",
202
209
  } })),
203
210
  CommonService.capitalize(seatLabel))) : (React.createElement("span", { className: "text-[13.33px]" }, "Desde")))));
204
211
  };
205
- if (hasDiscount && discountSeat && !(uiType === 1 && showSeatTypeRows)) {
206
- // Tier B (ui_type 1): offer text is announced elsewhere, but the fare
207
- // itself must render exactly as it would with no discount — no
208
- // strike-off, no badge, no fire icon.
209
- if (uiType === 1) {
210
- return (React.createElement("div", { className: "grid grid-cols-2 items-center text-[13.33px] relative", style: { opacity: isSoldOut ? 0.5 : 1 } },
211
- React.createElement("div", { className: "col-start-1 row-start-3 flex h-[20px] items-end" },
212
- React.createElement("span", { className: "text-[13.33px] font-normal leading-[20px] text-[#464647]" }, discountSeat.label)),
213
- React.createElement("div", { className: "col-start-2 row-start-3 flex h-[30px] items-end justify-center relative" },
214
- React.createElement("span", { className: "flex items-center gap-[6px] bold-text leading-[30px]", style: {
215
- color: isSoldOut ? "#c0c0c0" : "#464647",
216
- fontSize: "13.33px",
217
- } }, availableSeats <= 0
218
- ? CommonService.currency(0, currencySign)
219
- : CommonService.discountedCurrency(discountSeat.originalPrice, currencySign)))));
220
- }
212
+ if (hasDiscount && discountSeat && uiType !== 1) {
221
213
  return (React.createElement("div", { className: "grid grid-cols-2 items-center text-[13.33px] relative", style: { opacity: isSoldOut ? 0.5 : 1 } },
222
214
  React.createElement("div", { className: "col-start-1 row-start-2 flex items-center" },
223
215
  React.createElement("span", { className: "text-[13.33px] font-normal leading-[22px] text-[#ccc]" }, "Antes")),
@@ -94,18 +94,20 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
94
94
  })));
95
95
  }
96
96
  const { originalPrice, discountedPrice } = commonService.calculateDiscountedPrice(lowestFare, serviceItem);
97
+ const hasStrikeOff = originalPrice !== discountedPrice && !showOriginalFare;
97
98
  const seatLabel = uniqueSeats.length > 0
98
99
  ? commonService.truncateSeatLabel(uniqueSeats[0].label)
99
100
  : null;
100
101
  return (React.createElement(React.Fragment, null,
101
- originalPrice !== discountedPrice && (React.createElement("div", { className: "w-[100%] flex flex-row justify-between items-center" },
102
+ hasStrikeOff && (React.createElement("div", { className: "w-[100%] flex flex-row justify-between items-center" },
102
103
  React.createElement("span", { className: "min-[420]:text-[13px] text-[12px]", style: { color: "#bbb" } }, "Antes"),
103
104
  React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] line-through", style: { color: "#bbb" } }, commonService.currency(originalPrice, currencySign)))),
104
- React.createElement("div", { className: "w-[100%] flex flex-row justify-between items-center" },
105
- React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] bold-text", style: { color: isSoldOut ? "#bbb" : "#464647" } }, originalPrice !== discountedPrice
105
+ React.createElement("div", { className: "relative w-[100%] flex flex-row justify-between items-center" },
106
+ hasInclination && !hasStrikeOff && (React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] absolute", style: { color: "#6a6a6a", top: -20, right: 0 } }, "Desde")),
107
+ React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] bold-text", style: { color: isSoldOut ? "#bbb" : "#464647" } }, hasStrikeOff
106
108
  ? "Desde"
107
109
  : commonService.capitalize(seatLabel) || "Desde"),
108
- React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] bold-text", style: { color: priceColor } }, commonService.currency(discountedPrice, currencySign)))));
110
+ React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] bold-text", style: { color: priceColor } }, commonService.currency(showOriginalFare ? originalPrice : discountedPrice, currencySign)))));
109
111
  };
110
112
  const renderDpSeats = () => {
111
113
  var _a;
@@ -254,55 +256,55 @@ function SeatSectionMobile({ seatTypes: seatTypesData, isSoldOut, isPeru, seatPr
254
256
  } },
255
257
  ((_k = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.icons) === null || _k === void 0 ? void 0 : _k.fireIcon) ? (React.createElement("img", { src: serviceItem.icons.fireIcon, alt: "discount", className: "h-[16px] w-[16px] object-contain", style: { filter: isSoldOut ? "grayscale" : "" } })) : null,
256
258
  commonService.discountedCurrency(Number(firstSeatFare), currencySign)),
257
- isSoldOut ? (React.createElement("span", { className: "col-span-2 min-[420]:text-[13px] text-right text-[12px] text-[#ccc]" }, "Agotado")) : null)) : hasDiscount &&
258
- discountSeat &&
259
- !(isPeru && showSeatTypeRows && isOfferTextOnlyTier) ? (React.createElement("div", null,
260
- React.createElement("div", { className: "relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] " },
261
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.ui_type) !== 1 && discountBadgeText && (React.createElement(React.Fragment, null,
262
- React.createElement("div", { className: "absolute -top-[18px] right-[0px]", style: {
263
- animation: "pulse-zoom 2s ease-in-out infinite",
264
- opacity: isSoldOut ? 0.5 : 1,
265
- } },
266
- React.createElement("span", { className: "rounded-[100px] px-[8px] text-[12px] bold-text leading-[20px] text-[#fff]", style: {
267
- backgroundColor: tooltipBgColor,
268
- } }, discountBadgeText)),
269
- React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-[#c2c2c2]" }, "Antes"),
270
- React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-right ", style: {
271
- position: "relative",
272
- display: "inline-block",
273
- overflow: "hidden",
274
- color: discountSeatPriceColor,
259
+ isSoldOut ? (React.createElement("span", { className: "col-span-2 min-[420]:text-[13px] text-right text-[12px] text-[#ccc]" }, "Agotado")) : null)) : // Peru Tier B (ui_type 1) falls through to the regular layout — same
260
+ // colours and "Desde" as a service with no discount, original fare.
261
+ hasDiscount && discountSeat && !(isPeru && isOfferTextOnlyTier) ? (React.createElement("div", null,
262
+ React.createElement("div", { className: "relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] " },
263
+ (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.ui_type) !== 1 && discountBadgeText && (React.createElement(React.Fragment, null,
264
+ React.createElement("div", { className: "absolute -top-[18px] right-[0px]", style: {
265
+ animation: "pulse-zoom 2s ease-in-out infinite",
266
+ opacity: isSoldOut ? 0.5 : 1,
267
+ } },
268
+ React.createElement("span", { className: "rounded-[100px] px-[8px] text-[12px] bold-text leading-[20px] text-[#fff]", style: {
269
+ backgroundColor: tooltipBgColor,
270
+ } }, discountBadgeText)),
271
+ React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-[#c2c2c2]" }, "Antes"),
272
+ React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[20px] text-right ", style: {
273
+ position: "relative",
274
+ display: "inline-block",
275
+ overflow: "hidden",
276
+ color: discountSeatPriceColor,
277
+ } },
278
+ commonService.currency(discountSeat.originalPrice, currencySign),
279
+ React.createElement("span", { style: {
280
+ position: "absolute",
281
+ top: "35%",
282
+ left: "50%",
283
+ width: "80%",
284
+ height: "1px",
285
+ background: discountSeatCrossPriceColor,
286
+ transform: "rotate(-12deg)",
287
+ transformOrigin: "center",
288
+ } })))),
289
+ React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[24px]", style: { color: isSoldOut ? "#bbb" : "#464647" } }, isOfferTextOnlyTier
290
+ ? commonService.capitalize(commonService.truncateSeatLabel(discountSeat.label))
291
+ : "Desde"),
292
+ React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: {
293
+ color: isSoldOut
294
+ ? "#bbb"
295
+ : (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.ui_type) === 1
296
+ ? "#464647"
297
+ : discountSeatPriceColor || "#ff5964",
275
298
  } },
276
- commonService.currency(discountSeat.originalPrice, currencySign),
277
- React.createElement("span", { style: {
278
- position: "absolute",
279
- top: "35%",
280
- left: "50%",
281
- width: "80%",
282
- height: "1px",
283
- background: discountSeatCrossPriceColor,
284
- transform: "rotate(-12deg)",
285
- transformOrigin: "center",
286
- } })))),
287
- React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] leading-[24px]", style: { color: isSoldOut ? "#bbb" : "#464647" } }, isOfferTextOnlyTier
288
- ? commonService.capitalize(commonService.truncateSeatLabel(discountSeat.label))
289
- : "Desde"),
290
- React.createElement("span", { className: "flex items-center justify-end gap-[4px] text-[14px] bold-text leading-[24px]", style: {
291
- color: isSoldOut
292
- ? "#bbb"
293
- : (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.ui_type) === 1
294
- ? "#464647"
295
- : discountSeatPriceColor || "#ff5964",
296
- } },
297
- (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.ui_type) !== 1 && ((_l = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.icons) === null || _l === void 0 ? void 0 : _l.fireIcon) ? (React.createElement("img", { src: serviceItem.icons.fireIcon, alt: "discount", className: "h-[16px] w-[16px] object-contain", style: { opacity: isSoldOut ? 0.5 : 1 } })) : null,
298
- commonService.discountedCurrency((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.ui_type) === 1
299
- ? discountSeat.originalPrice
300
- : discountSeat.discountedPrice, currencySign))))) : (React.createElement("div", { className: `flex flex-col justify-between ${isTrain ? "" : "h-[2.5rem]"} `, style: {
301
- gap: isSoldOut ? "0px" : "5px",
302
- justifyContent: hasMultipleTypes ? "space-between" : "center",
303
- } },
304
- renderSeats(),
305
- isSoldOut ? (React.createElement("div", { className: "flex justify-end" },
306
- React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] text-[#ccc]" }, "Agotado"))) : null))));
299
+ (serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.ui_type) !== 1 && ((_l = serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.icons) === null || _l === void 0 ? void 0 : _l.fireIcon) ? (React.createElement("img", { src: serviceItem.icons.fireIcon, alt: "discount", className: "h-[16px] w-[16px] object-contain", style: { opacity: isSoldOut ? 0.5 : 1 } })) : null,
300
+ commonService.discountedCurrency((serviceItem === null || serviceItem === void 0 ? void 0 : serviceItem.ui_type) === 1
301
+ ? discountSeat.originalPrice
302
+ : discountSeat.discountedPrice, currencySign))))) : (React.createElement("div", { className: `flex flex-col justify-between ${isTrain ? "" : "h-[2.5rem]"} `, style: {
303
+ gap: isSoldOut ? "0px" : "5px",
304
+ justifyContent: hasMultipleTypes ? "space-between" : "center",
305
+ } },
306
+ renderSeats(),
307
+ isSoldOut ? (React.createElement("div", { className: "flex justify-end" },
308
+ React.createElement("span", { className: "min-[420]:text-[13px] text-[12px] text-[#ccc]" }, "Agotado"))) : null))));
307
309
  }
308
310
  export default SeatSectionMobile;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kupos-ui-components-lib",
3
- "version": "10.4.39",
3
+ "version": "10.4.41",
4
4
  "description": "A reusable UI components package",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -190,7 +190,7 @@ class DiscountBannersMobile extends React.Component<
190
190
  >
191
191
  {label}
192
192
  </span>
193
- {/* {showFlamePercent && (
193
+ {showFlamePercent && (
194
194
  <span
195
195
  className={`bold-text absolute text-[#ffffff] text-center pointer-events-none ${sizeClasses.flameBadge}`}
196
196
  style={{
@@ -209,7 +209,7 @@ class DiscountBannersMobile extends React.Component<
209
209
  %
210
210
  </span>
211
211
  </span>
212
- )} */}
212
+ )}
213
213
  <span className={`flex flex-col ${sizeClasses.column}`}>
214
214
  <span
215
215
  className={`bold-text text-[#464647] ${sizeClasses.discount}`}
@@ -1,13 +1,13 @@
1
- import greenArt from "../../assets/images/discount/instant.png";
1
+ import greenArt from "../../assets/images/discount/green_new.png";
2
2
  import yellowArt from "../../assets/images/discount/yellow.png";
3
3
  import blueArt from "../../assets/images/discount/blue.png";
4
- import lastMinuteArt from "../../assets/images/discount/last.png";
5
- import firstTimeArt from "../../assets/images/discount/first.png";
4
+ import lastMinuteArt from "../../assets/images/discount/last_minute.png";
5
+ import firstTimeArt from "../../assets/images/discount/purple.png";
6
6
  import cashbackArt from "../../assets/images/discount/cash.png";
7
- import roundTripArt from "../../assets/images/discount/round.png";
8
- import promoCodeArt from "../../assets/images/discount/promo.png";
7
+ import roundTripArt from "../../assets/images/discount/green_rt.png";
8
+ import promoCodeArt from "../../assets/images/discount/yellow.png";
9
9
  import seatLevelArt from "../../assets/images/discount/seat.png";
10
- import instantArt from "../../assets/images/discount/instant.png";
10
+ import instantArt from "../../assets/images/discount/yellow_instant.png";
11
11
 
12
12
  export type ImageRef =
13
13
  | string
@@ -32,11 +32,11 @@ export const DEFAULT_BACKGROUND_IMAGES: string[] = [
32
32
  ].map(toImageUrl);
33
33
 
34
34
  export const CAMPAIGN_ART: Record<string, { image: string; accent: string }> = {
35
- last_minute: { image: toImageUrl(lastMinuteArt), accent: "#4457C7" },
36
- first_time: { image: toImageUrl(firstTimeArt), accent: "#D63384" },
35
+ last_minute: { image: toImageUrl(lastMinuteArt), accent: "#1633DB" },
36
+ first_time: { image: toImageUrl(firstTimeArt), accent: "#FB488E" },
37
37
  cashback: { image: toImageUrl(cashbackArt), accent: "#0069D1" },
38
- round_trip: { image: toImageUrl(roundTripArt), accent: "#5C8A00" },
39
- instant_discount: { image: toImageUrl(promoCodeArt), accent: "#E08A00" },
38
+ round_trip: { image: toImageUrl(roundTripArt), accent: "#107E23" },
39
+ instant_discount: { image: toImageUrl(instantArt), accent: "#FDA105" },
40
40
  seat_level: { image: toImageUrl(seatLevelArt), accent: "#B87500" },
41
- promo_code: { image: toImageUrl(seatLevelArt), accent: "#B87500" },
41
+ promo_code: { image: toImageUrl(promoCodeArt), accent: "#FFC000" },
42
42
  };
@@ -211,18 +211,30 @@ function PeruSeatSection({
211
211
  // Single seat type → original behaviour (one lowest-fare price)
212
212
  const allSeats = getAllSeatTypes(seatTypes);
213
213
  const lowestFare = allSeats.length > 0 ? allSeats[0].price : 0;
214
- const { discountedPrice } = CommonService.calculateDiscountedPrice(
215
- lowestFare,
216
- serviceItem,
214
+ const { originalPrice, discountedPrice } =
215
+ CommonService.calculateDiscountedPrice(lowestFare, serviceItem);
216
+ const price = (
217
+ <span className="flex items-center text-[13.33px] bold-text">
218
+ {formatPrice(showOriginalFare ? originalPrice : discountedPrice)}
219
+ </span>
217
220
  );
218
221
 
219
- return (
220
- <>
221
- <span className="flex items-center text-[13.33px] bold-text">
222
- {formatPrice(discountedPrice)}
223
- </span>
224
- </>
225
- );
222
+ // Inclination fares sit under "Desde", same as the stacked rows above.
223
+ if (hasInclination) {
224
+ return (
225
+ <div className="relative">
226
+ <span
227
+ className="text-[12px] font-normal text-[#6a6a6a] absolute"
228
+ style={{ top: "-15px" }}
229
+ >
230
+ Desde
231
+ </span>
232
+ {price}
233
+ </div>
234
+ );
235
+ }
236
+
237
+ return price;
226
238
  };
227
239
 
228
240
  const seats = removeDuplicateSeats ? uniqueSeats : sortedSeatTypes;
@@ -246,6 +258,7 @@ function PeruSeatSection({
246
258
  // Tier B (ui_type 1) announces the offer elsewhere, so the fare itself must
247
259
  // render exactly as it would with no discount.
248
260
  const showOriginalFare = hasDiscount && uiType === 1;
261
+ const hasStrikeOff = hasDiscount && !showOriginalFare;
249
262
  const discountType = serviceItem?.discount_type;
250
263
  const discountValueRaw = serviceItem?.discount_value;
251
264
  const maxDiscount = serviceItem?.max_discount;
@@ -331,7 +344,7 @@ function PeruSeatSection({
331
344
 
332
345
  return (
333
346
  <>
334
- {hasDiscount && (
347
+ {hasStrikeOff && (
335
348
  <span
336
349
  className="text-[13.33px]"
337
350
  style={{
@@ -343,14 +356,14 @@ function PeruSeatSection({
343
356
  )}
344
357
 
345
358
  <span className="text-[13.33px] flex flex-col">
346
- {!hasDiscount ? (
359
+ {!hasStrikeOff ? (
347
360
  <span
348
361
  className="text-[13.33px] whitespace-nowrap flex items-center"
349
362
  style={{
350
363
  opacity: isSoldOut ? 0.5 : 1,
351
364
  }}
352
365
  >
353
- {isSeatIcon && !hasDiscount && (
366
+ {isSeatIcon && (
354
367
  <img
355
368
  src={
356
369
  getSeatTypeIcon(
@@ -376,42 +389,8 @@ function PeruSeatSection({
376
389
  );
377
390
  };
378
391
 
379
- if (hasDiscount && discountSeat && !(uiType === 1 && showSeatTypeRows)) {
380
- // Tier B (ui_type 1): offer text is announced elsewhere, but the fare
381
- // itself must render exactly as it would with no discount — no
382
- // strike-off, no badge, no fire icon.
383
- if (uiType === 1) {
384
- return (
385
- <div
386
- className="grid grid-cols-2 items-center text-[13.33px] relative"
387
- style={{ opacity: isSoldOut ? 0.5 : 1 }}
388
- >
389
- <div className="col-start-1 row-start-3 flex h-[20px] items-end">
390
- <span className="text-[13.33px] font-normal leading-[20px] text-[#464647]">
391
- {discountSeat.label}
392
- </span>
393
- </div>
394
-
395
- <div className="col-start-2 row-start-3 flex h-[30px] items-end justify-center relative">
396
- <span
397
- className="flex items-center gap-[6px] bold-text leading-[30px]"
398
- style={{
399
- color: isSoldOut ? "#c0c0c0" : "#464647",
400
- fontSize: "13.33px",
401
- }}
402
- >
403
- {availableSeats <= 0
404
- ? CommonService.currency(0, currencySign)
405
- : CommonService.discountedCurrency(
406
- discountSeat.originalPrice,
407
- currencySign,
408
- )}
409
- </span>
410
- </div>
411
- </div>
412
- );
413
- }
414
392
 
393
+ if (hasDiscount && discountSeat && uiType !== 1) {
415
394
  return (
416
395
  <div
417
396
  className="grid grid-cols-2 items-center text-[13.33px] relative"
@@ -230,6 +230,7 @@ function SeatSectionMobile({
230
230
 
231
231
  const { originalPrice, discountedPrice } =
232
232
  commonService.calculateDiscountedPrice(lowestFare, serviceItem);
233
+ const hasStrikeOff = originalPrice !== discountedPrice && !showOriginalFare;
233
234
 
234
235
  const seatLabel =
235
236
  uniqueSeats.length > 0
@@ -238,7 +239,7 @@ function SeatSectionMobile({
238
239
 
239
240
  return (
240
241
  <>
241
- {originalPrice !== discountedPrice && (
242
+ {hasStrikeOff && (
242
243
  <div className="w-[100%] flex flex-row justify-between items-center">
243
244
  <span
244
245
  className="min-[420]:text-[13px] text-[12px]"
@@ -254,12 +255,21 @@ function SeatSectionMobile({
254
255
  </span>
255
256
  </div>
256
257
  )}
257
- <div className="w-[100%] flex flex-row justify-between items-center">
258
+ <div className="relative w-[100%] flex flex-row justify-between items-center">
259
+ {/* Inclination fares sit under "Desde", same as the stacked rows above. */}
260
+ {hasInclination && !hasStrikeOff && (
261
+ <span
262
+ className="min-[420]:text-[13px] text-[12px] absolute"
263
+ style={{ color: "#6a6a6a", top: -20, right: 0 }}
264
+ >
265
+ Desde
266
+ </span>
267
+ )}
258
268
  <span
259
269
  className="min-[420]:text-[13px] text-[12px] bold-text"
260
270
  style={{ color: isSoldOut ? "#bbb" : "#464647" }}
261
271
  >
262
- {originalPrice !== discountedPrice
272
+ {hasStrikeOff
263
273
  ? "Desde"
264
274
  : commonService.capitalize(seatLabel) || "Desde"}
265
275
  </span>
@@ -267,7 +277,10 @@ function SeatSectionMobile({
267
277
  className="min-[420]:text-[13px] text-[12px] bold-text"
268
278
  style={{ color: priceColor }}
269
279
  >
270
- {commonService.currency(discountedPrice, currencySign)}
280
+ {commonService.currency(
281
+ showOriginalFare ? originalPrice : discountedPrice,
282
+ currencySign,
283
+ )}
271
284
  </span>
272
285
  </div>
273
286
  </>
@@ -594,9 +607,9 @@ function SeatSectionMobile({
594
607
  </span>
595
608
  ) : null}
596
609
  </div>
597
- ) : hasDiscount &&
598
- discountSeat &&
599
- !(isPeru && showSeatTypeRows && isOfferTextOnlyTier) ? (
610
+ ) : // Peru Tier B (ui_type 1) falls through to the regular layout — same
611
+ // colours and "Desde" as a service with no discount, original fare.
612
+ hasDiscount && discountSeat && !(isPeru && isOfferTextOnlyTier) ? (
600
613
  <div>
601
614
  <div className="relative grid grid-cols-[auto_auto] justify-between gap-x-[8px] ">
602
615
  {serviceItem?.ui_type !== 1 && discountBadgeText && (