kupos-ui-components-lib 9.11.7 → 9.11.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemDesktop.js +25 -7
- package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemMobile.js +1 -1
- package/dist/components/ServiceItem/mobileTypes.d.ts +1 -0
- package/dist/components/ServiceItem/types.d.ts +7 -0
- package/dist/styles.css +6 -0
- package/dist/ui/BottomAmenities/BottomAmenities.d.ts +2 -1
- package/dist/ui/BottomAmenities/BottomAmenities.js +4 -2
- package/dist/ui/DateTimeSection/DateTimeSection.js +4 -4
- package/dist/ui/OfferBanner.d.ts +1 -0
- package/dist/ui/OfferBanner.js +6 -2
- package/dist/ui/SeatSection/SeatSection.d.ts +7 -1
- package/dist/ui/SeatSection/SeatSection.js +43 -12
- package/dist/ui/mobileweb/DateTimeSectionMobile.d.ts +2 -1
- package/dist/ui/mobileweb/DateTimeSectionMobile.js +13 -7
- package/dist/ui/mobileweb/SeatSectionMobile.d.ts +2 -1
- package/dist/ui/mobileweb/SeatSectionMobile.js +22 -15
- package/dist/utils/CommonService.d.ts +1 -1
- package/dist/utils/CommonService.js +5 -1
- package/package.json +1 -1
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +51 -5
- package/src/components/ServiceItem/ServiceItemMobile.tsx +2 -1
- package/src/components/ServiceItem/mobileTypes.ts +31 -26
- package/src/components/ServiceItem/types.ts +12 -0
- package/src/ui/BottomAmenities/BottomAmenities.tsx +5 -1
- package/src/ui/DateTimeSection/DateTimeSection.tsx +4 -4
- package/src/ui/OfferBanner.tsx +7 -1
- package/src/ui/SeatSection/SeatSection.tsx +90 -21
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +47 -34
- package/src/ui/mobileweb/SeatSectionMobile.tsx +27 -12
- package/src/utils/CommonService.ts +7 -1
|
@@ -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")
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
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=
|
|
157
|
-
style={{
|
|
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
|
);
|
|
@@ -31,6 +31,7 @@ interface SeatSectionMobileProps {
|
|
|
31
31
|
tooltipBgColor?: string;
|
|
32
32
|
showLastSeats?: boolean;
|
|
33
33
|
discountSeatPriceColor?: string;
|
|
34
|
+
isTrain?: boolean;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
interface SeatRowProps {
|
|
@@ -42,6 +43,7 @@ interface SeatRowProps {
|
|
|
42
43
|
seatPriceColor: string;
|
|
43
44
|
hasMultipleTypes: boolean;
|
|
44
45
|
textSize: string;
|
|
46
|
+
isTrain?: boolean;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
const SeatRow: React.FC<SeatRowProps> = ({
|
|
@@ -53,6 +55,7 @@ const SeatRow: React.FC<SeatRowProps> = ({
|
|
|
53
55
|
seatPriceColor,
|
|
54
56
|
hasMultipleTypes,
|
|
55
57
|
textSize,
|
|
58
|
+
isTrain,
|
|
56
59
|
}) => {
|
|
57
60
|
if (EXCEPTIONS.includes(type.label)) return null;
|
|
58
61
|
|
|
@@ -69,7 +72,12 @@ const SeatRow: React.FC<SeatRowProps> = ({
|
|
|
69
72
|
className={`min-[420]:text-[13px] ${textSize} `}
|
|
70
73
|
style={{ color: labelColor }}
|
|
71
74
|
>
|
|
72
|
-
{
|
|
75
|
+
{isTrain
|
|
76
|
+
? commonService.truncateSeatLabel(
|
|
77
|
+
commonService.capitalize(displayLabel),
|
|
78
|
+
8,
|
|
79
|
+
)
|
|
80
|
+
: displayLabel}
|
|
73
81
|
</span>
|
|
74
82
|
<span
|
|
75
83
|
className={`min-[420]:text-[13px] ${textSize} bold-text`}
|
|
@@ -118,6 +126,7 @@ function SeatSectionMobile({
|
|
|
118
126
|
tooltipBgColor,
|
|
119
127
|
showLastSeats,
|
|
120
128
|
discountSeatPriceColor,
|
|
129
|
+
isTrain,
|
|
121
130
|
}: SeatSectionMobileProps): React.ReactElement {
|
|
122
131
|
const hasMultipleTypes = (seatTypesData?.length ?? 0) > 2;
|
|
123
132
|
|
|
@@ -171,7 +180,7 @@ function SeatSectionMobile({
|
|
|
171
180
|
className="w-[100%] flex flex-row justify-between items-center"
|
|
172
181
|
>
|
|
173
182
|
<span
|
|
174
|
-
className="min-[420]:text-[13px] text-[12px] bold-text"
|
|
183
|
+
className="min-[420]:text-[13px] text-[12px] bold-text whitespace-nowrap"
|
|
175
184
|
style={{ color: isSoldOut ? "#bbb" : "#464647" }}
|
|
176
185
|
>
|
|
177
186
|
{commonService.truncateSeatLabel(seat.label)}
|
|
@@ -324,15 +333,17 @@ function SeatSectionMobile({
|
|
|
324
333
|
seatPriceColor={seatPriceColor}
|
|
325
334
|
hasMultipleTypes={hasMultipleTypes}
|
|
326
335
|
textSize="text-[11px]"
|
|
336
|
+
isTrain={isTrain}
|
|
327
337
|
/>
|
|
328
338
|
));
|
|
329
339
|
}
|
|
330
340
|
|
|
331
|
-
|
|
341
|
+
const filteredSeats = seatTypesData
|
|
332
342
|
?.filter((item) => getFilteredSeats(item.label))
|
|
333
|
-
?.sort((a, b) => a.fare - b.fare)
|
|
334
|
-
|
|
335
|
-
|
|
343
|
+
?.sort((a, b) => a.fare - b.fare);
|
|
344
|
+
|
|
345
|
+
return (isTrain ? filteredSeats : filteredSeats?.slice(0, 2))?.map(
|
|
346
|
+
(type, i) => (
|
|
336
347
|
<SeatRow
|
|
337
348
|
key={i}
|
|
338
349
|
type={type}
|
|
@@ -343,16 +354,20 @@ function SeatSectionMobile({
|
|
|
343
354
|
seatPriceColor={seatPriceColor}
|
|
344
355
|
hasMultipleTypes={hasMultipleTypes}
|
|
345
356
|
textSize="text-[12px]"
|
|
357
|
+
isTrain={isTrain}
|
|
346
358
|
/>
|
|
347
|
-
)
|
|
359
|
+
),
|
|
360
|
+
);
|
|
348
361
|
};
|
|
349
362
|
|
|
350
363
|
const seats = removeDuplicateSeats
|
|
351
364
|
? getUniqueSeats(seatTypesData, 3)
|
|
352
|
-
:
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
365
|
+
: (() => {
|
|
366
|
+
const filtered = seatTypesData
|
|
367
|
+
?.filter((item) => getFilteredSeats(item.label))
|
|
368
|
+
?.sort((a, b) => a.fare - b.fare);
|
|
369
|
+
return isTrain ? filtered : filtered?.slice(0, 2);
|
|
370
|
+
})();
|
|
356
371
|
|
|
357
372
|
const discountedSeats = seats?.map((seat) => ({
|
|
358
373
|
...seat,
|
|
@@ -604,7 +619,7 @@ function SeatSectionMobile({
|
|
|
604
619
|
</div>
|
|
605
620
|
) : (
|
|
606
621
|
<div
|
|
607
|
-
className=
|
|
622
|
+
className={`flex flex-col justify-between ${isTrain ? "" : "h-[2.5rem]"} `}
|
|
608
623
|
style={{
|
|
609
624
|
gap: isSoldOut ? "0px" : "5px",
|
|
610
625
|
justifyContent: hasMultipleTypes ? "space-between" : "center",
|
|
@@ -39,9 +39,15 @@ const commonService = {
|
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
|
|
42
|
-
truncateSeatLabel: (label: string | number): string => {
|
|
42
|
+
truncateSeatLabel: (label: string | number, maxLength?: number): string => {
|
|
43
43
|
if (typeof label !== "string") return String(label);
|
|
44
44
|
if (label.includes("(")) return label;
|
|
45
|
+
|
|
46
|
+
// If maxLength provided, hard-truncate regardless of word count
|
|
47
|
+
if (maxLength != null && label.length > maxLength) {
|
|
48
|
+
return label.slice(0, maxLength) + "...";
|
|
49
|
+
}
|
|
50
|
+
|
|
45
51
|
const words = label.trim().split(/\s+/);
|
|
46
52
|
|
|
47
53
|
const truncateWord = (word: string) =>
|