kupos-ui-components-lib 10.4.72 → 10.4.74

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.
@@ -147,7 +147,6 @@ class DiscountBannersDesktop extends React.Component {
147
147
  }
148
148
  render() {
149
149
  const { services = [], wowDealData, backgroundImages = [], artIncludesChipPill, accentColors = [], label = DEFAULT_LABEL, currencySign = "$", size = "default", selectedKey, className = "", style, } = this.props;
150
- console.log("🚀 ~ DiscountBannersDesktop ~ render ~ services:", services);
151
150
  // Compute cards directly — no useMemo
152
151
  const cards = deriveDiscountCards(services, wowDealData, currencySign);
153
152
  if (!cards.length)
@@ -107,6 +107,18 @@ function addOperatorLogo(card, service) {
107
107
  { url, name: service.operator_name || ((_f = service.operator_details) === null || _f === void 0 ? void 0 : _f[2]) },
108
108
  ];
109
109
  }
110
+ // savings_percent may be missing or sent as a string; fall back to the deal's prices so
111
+ // Remate still sorts by its real discount instead of dropping to 0%
112
+ function getWowDealPercent(wowDealData) {
113
+ const savings = Number(wowDealData.savings_percent);
114
+ if (savings > 0)
115
+ return savings;
116
+ const original = Number(wowDealData.original_price);
117
+ const final = Number(wowDealData.final_price);
118
+ return original > 0 && final >= 0 && final < original
119
+ ? ((original - final) / original) * 100
120
+ : 0;
121
+ }
110
122
  function toDiscountLabel(discount, currencySign) {
111
123
  if (discount.type === "fixed") {
112
124
  return `${CommonService.currencyRounded(discount.amount, currencySign)} de dcto`;
@@ -118,13 +130,14 @@ export function deriveDiscountCards(services = [], wowDealData, currencySign = "
118
130
  var _a, _b, _c, _d, _e;
119
131
  const cards = new Map();
120
132
  const wowServices = wowDealData === null || wowDealData === void 0 ? void 0 : wowDealData.services;
133
+ const wowDealPercent = wowDealData ? getWowDealPercent(wowDealData) : 0;
121
134
  const hasWowDeal = !!wowDealData &&
122
135
  ((Array.isArray(wowServices) && wowServices.length > 0) ||
123
- !!wowDealData.savings_percent);
136
+ wowDealPercent > 0);
124
137
  if (hasWowDeal) {
125
138
  const remateDiscount = {
126
139
  type: "percentage",
127
- amount: Math.round(wowDealData.savings_percent || 0),
140
+ amount: Math.round(wowDealPercent),
128
141
  };
129
142
  cards.set(REMATE_KEY, {
130
143
  key: REMATE_KEY,
@@ -217,8 +230,9 @@ export function deriveDiscountCards(services = [], wowDealData, currencySign = "
217
230
  return a.name.localeCompare(b.name, "es", { sensitivity: "base" });
218
231
  });
219
232
  }
220
- // Highest discount first. Percentages and fixed amounts can't be compared, so percentages
221
- // lead. The sort is stable, so on a tie Remate stays ahead and the rest keep service order.
233
+ // Highest discount first, Remate included — it takes its place by its percent rather than
234
+ // always leading. Percentages and fixed amounts can't be compared, so percentages lead.
235
+ // The sort is stable, so on a tie Remate stays ahead and the rest keep service order.
222
236
  return Array.from(cards.values()).sort((a, b) => {
223
237
  if (a.discountType !== b.discountType) {
224
238
  return a.discountType === "percentage" ? -1 : 1;
@@ -91,31 +91,13 @@ const FeatureServiceUiMobile = ({ serviceItem, showTopLabel, colors, isSoldOut,
91
91
  selectedSlotService.original_price) *
92
92
  100)
93
93
  : savingsPercent;
94
- // Convert "HH:MM" (24h) → "H:MM AM/PM"
95
- const formatTimeAmPm = (time) => {
96
- const match = time.match(/(\d{1,2}):(\d{2})/);
97
- if (!match)
98
- return time;
99
- let h = parseInt(match[1], 10);
100
- const m = match[2];
101
- const period = h >= 12 ? "PM" : "AM";
102
- h = h % 12 || 12;
103
- return `${h}:${m} ${period}`;
104
- };
105
- // Convert all HH:MM occurrences in a label string to AM/PM
106
- const formatLabelAmPm = (label) => label.replace(/(\d{1,2}):(\d{2})/g, (_, hh, mm) => {
107
- let h = parseInt(hh, 10);
108
- const period = h >= 12 ? "PM" : "AM";
109
- h = h % 12 || 12;
110
- return `${h}:${mm} ${period}`;
111
- });
112
- // The label shown on the dropdown button
113
- const departureRange = formatLabelAmPm((activeSlot === null || activeSlot === void 0 ? void 0 : activeSlot.label) || `Entre ${dealWindowFrom} y ${dealWindowTo}`);
114
- const currentWindowFrom = (activeSlot === null || activeSlot === void 0 ? void 0 : activeSlot.label)
115
- ? activeSlot.label.split(" - ")[0]
94
+ // The label shown on the dropdown button (24h format, e.g. "Entre 16:00 y 20:00")
95
+ const departureRange = (activeSlot === null || activeSlot === void 0 ? void 0 : activeSlot.label) || `Entre ${dealWindowFrom} y ${dealWindowTo}`;
96
+ const currentWindowFrom = activeSlot
97
+ ? commonService.minutesToTime(activeSlot.start)
116
98
  : dealWindowFrom;
117
- const currentWindowTo = (activeSlot === null || activeSlot === void 0 ? void 0 : activeSlot.label)
118
- ? activeSlot.label.split(" - ")[1]
99
+ const currentWindowTo = activeSlot
100
+ ? commonService.minutesToTime(activeSlot.end === 1440 ? 1439 : activeSlot.end)
119
101
  : dealWindowTo;
120
102
  const isItemExpanded = serviceItem.id === isFeatureDropDownExpand ||
121
103
  isFeatureDropDownExpand === true;
@@ -105,11 +105,11 @@ const FeatureServiceUi = ({ serviceItem, showTopLabel, getAnimationIcon, cityOri
105
105
  // The label shown on the dropdown button
106
106
  const departureRange = (activeSlot === null || activeSlot === void 0 ? void 0 : activeSlot.label) || `${dealWindowFrom} y ${dealWindowTo}`;
107
107
  // activeSlot?.label || `Entre ${dealWindowFrom} y ${dealWindowTo}`;
108
- const currentWindowFrom = (activeSlot === null || activeSlot === void 0 ? void 0 : activeSlot.label)
109
- ? activeSlot.label.split(" - ")[0]
108
+ const currentWindowFrom = activeSlot
109
+ ? commonService.minutesToTime(activeSlot.start)
110
110
  : dealWindowFrom;
111
- const currentWindowTo = (activeSlot === null || activeSlot === void 0 ? void 0 : activeSlot.label)
112
- ? activeSlot.label.split(" - ")[1]
111
+ const currentWindowTo = activeSlot
112
+ ? commonService.minutesToTime(activeSlot.end === 1440 ? 1439 : activeSlot.end)
113
113
  : dealWindowTo;
114
114
  if (expandedStateMap[serviceItem.id] === undefined) {
115
115
  expandedStateMap[serviceItem.id] = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kupos-ui-components-lib",
3
- "version": "10.4.72",
3
+ "version": "10.4.74",
4
4
  "description": "A reusable UI components package",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -197,7 +197,6 @@ class DiscountBannersDesktop extends React.Component<
197
197
  className = "",
198
198
  style,
199
199
  } = this.props;
200
- console.log("🚀 ~ DiscountBannersDesktop ~ render ~ services:", services)
201
200
 
202
201
  // Compute cards directly — no useMemo
203
202
  const cards = deriveDiscountCards(services, wowDealData, currencySign);
@@ -148,6 +148,18 @@ function addOperatorLogo(
148
148
  ];
149
149
  }
150
150
 
151
+ // savings_percent may be missing or sent as a string; fall back to the deal's prices so
152
+ // Remate still sorts by its real discount instead of dropping to 0%
153
+ function getWowDealPercent(wowDealData: WowDealData): number {
154
+ const savings = Number(wowDealData.savings_percent);
155
+ if (savings > 0) return savings;
156
+ const original = Number(wowDealData.original_price);
157
+ const final = Number(wowDealData.final_price);
158
+ return original > 0 && final >= 0 && final < original
159
+ ? ((original - final) / original) * 100
160
+ : 0;
161
+ }
162
+
151
163
  function toDiscountLabel(
152
164
  discount: ServiceDiscount,
153
165
  currencySign: string,
@@ -167,15 +179,16 @@ export function deriveDiscountCards(
167
179
  const cards = new Map<string, DiscountBannerCard>();
168
180
 
169
181
  const wowServices = wowDealData?.services;
182
+ const wowDealPercent = wowDealData ? getWowDealPercent(wowDealData) : 0;
170
183
  const hasWowDeal =
171
184
  !!wowDealData &&
172
185
  ((Array.isArray(wowServices) && wowServices.length > 0) ||
173
- !!wowDealData.savings_percent);
186
+ wowDealPercent > 0);
174
187
 
175
188
  if (hasWowDeal) {
176
189
  const remateDiscount: ServiceDiscount = {
177
190
  type: "percentage",
178
- amount: Math.round(wowDealData!.savings_percent || 0),
191
+ amount: Math.round(wowDealPercent),
179
192
  };
180
193
  cards.set(REMATE_KEY, {
181
194
  key: REMATE_KEY,
@@ -276,8 +289,9 @@ export function deriveDiscountCards(
276
289
  });
277
290
  }
278
291
 
279
- // Highest discount first. Percentages and fixed amounts can't be compared, so percentages
280
- // lead. The sort is stable, so on a tie Remate stays ahead and the rest keep service order.
292
+ // Highest discount first, Remate included — it takes its place by its percent rather than
293
+ // always leading. Percentages and fixed amounts can't be compared, so percentages lead.
294
+ // The sort is stable, so on a tie Remate stays ahead and the rest keep service order.
281
295
  return Array.from(cards.values()).sort((a, b) => {
282
296
  if (a.discountType !== b.discountType) {
283
297
  return a.discountType === "percentage" ? -1 : 1;
@@ -131,36 +131,17 @@ const FeatureServiceUiMobile = ({
131
131
  )
132
132
  : savingsPercent;
133
133
 
134
- // Convert "HH:MM" (24h) → "H:MM AM/PM"
135
- const formatTimeAmPm = (time: string): string => {
136
- const match = time.match(/(\d{1,2}):(\d{2})/);
137
- if (!match) return time;
138
- let h = parseInt(match[1], 10);
139
- const m = match[2];
140
- const period = h >= 12 ? "PM" : "AM";
141
- h = h % 12 || 12;
142
- return `${h}:${m} ${period}`;
143
- };
144
-
145
- // Convert all HH:MM occurrences in a label string to AM/PM
146
- const formatLabelAmPm = (label: string): string =>
147
- label.replace(/(\d{1,2}):(\d{2})/g, (_, hh, mm) => {
148
- let h = parseInt(hh, 10);
149
- const period = h >= 12 ? "PM" : "AM";
150
- h = h % 12 || 12;
151
- return `${h}:${mm} ${period}`;
152
- });
134
+ // The label shown on the dropdown button (24h format, e.g. "Entre 16:00 y 20:00")
135
+ const departureRange =
136
+ activeSlot?.label || `Entre ${dealWindowFrom} y ${dealWindowTo}`;
153
137
 
154
- // The label shown on the dropdown button
155
- const departureRange = formatLabelAmPm(
156
- activeSlot?.label || `Entre ${dealWindowFrom} y ${dealWindowTo}`,
157
- );
158
-
159
- const currentWindowFrom = activeSlot?.label
160
- ? activeSlot.label.split(" - ")[0]
138
+ const currentWindowFrom = activeSlot
139
+ ? commonService.minutesToTime(activeSlot.start)
161
140
  : dealWindowFrom;
162
- const currentWindowTo = activeSlot?.label
163
- ? activeSlot.label.split(" - ")[1]
141
+ const currentWindowTo = activeSlot
142
+ ? commonService.minutesToTime(
143
+ activeSlot.end === 1440 ? 1439 : activeSlot.end,
144
+ )
164
145
  : dealWindowTo;
165
146
 
166
147
  const isItemExpanded =
@@ -147,11 +147,13 @@ const FeatureServiceUi = ({
147
147
  activeSlot?.label || `${dealWindowFrom} y ${dealWindowTo}`;
148
148
  // activeSlot?.label || `Entre ${dealWindowFrom} y ${dealWindowTo}`;
149
149
 
150
- const currentWindowFrom = activeSlot?.label
151
- ? activeSlot.label.split(" - ")[0]
150
+ const currentWindowFrom = activeSlot
151
+ ? commonService.minutesToTime(activeSlot.start)
152
152
  : dealWindowFrom;
153
- const currentWindowTo = activeSlot?.label
154
- ? activeSlot.label.split(" - ")[1]
153
+ const currentWindowTo = activeSlot
154
+ ? commonService.minutesToTime(
155
+ activeSlot.end === 1440 ? 1439 : activeSlot.end,
156
+ )
155
157
  : dealWindowTo;
156
158
 
157
159
  if (expandedStateMap[serviceItem.id] === undefined) {