kupos-ui-components-lib 9.10.0 → 9.10.2
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/KuposUIComponent.d.ts +14 -1
- package/dist/KuposUIComponent.js +3 -0
- package/dist/components/ServiceItem/ServiceItemDesktop.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemDesktop.js +2 -20
- package/dist/components/ServiceItem/ServiceItemMobile.d.ts +1 -1
- package/dist/components/ServiceItem/ServiceItemMobile.js +2 -2
- package/dist/components/ServiceItem/mobileTypes.d.ts +0 -2
- package/dist/components/ServiceItem/types.d.ts +0 -7
- package/dist/components/Survey/SurveyDesktop.js +17 -16
- package/dist/components/Survey/SurveyMobile.js +17 -16
- package/dist/index.d.ts +5 -1
- package/dist/index.js +9 -1
- package/dist/styles.css +32 -6
- package/dist/ui/SeatSection/SeatSection.d.ts +1 -7
- package/dist/ui/SeatSection/SeatSection.js +9 -38
- package/dist/ui/mobileweb/DateTimeSectionMobile.d.ts +1 -2
- package/dist/ui/mobileweb/DateTimeSectionMobile.js +6 -12
- package/dist/ui/mobileweb/SeatSectionMobile.d.ts +1 -2
- package/dist/ui/mobileweb/SeatSectionMobile.js +14 -21
- package/dist/ui/mobileweb/ServiceBadgesMobile.js +2 -2
- package/dist/utils/CommonService.d.ts +1 -1
- package/dist/utils/CommonService.js +1 -5
- package/package.json +1 -1
- package/src/KuposUIComponent.tsx +22 -1
- package/src/assets/images/anims/service_list/succes_anim.json +1 -0
- package/src/components/ServiceItem/ServiceItemDesktop.tsx +0 -43
- package/src/components/ServiceItem/ServiceItemMobile.tsx +1 -3
- package/src/components/ServiceItem/mobileTypes.ts +26 -32
- package/src/components/ServiceItem/types.ts +0 -12
- package/src/components/Survey/ResponsiveSurvey.tsx +14 -0
- package/src/components/Survey/SurveyDesktop.tsx +121 -0
- package/src/components/Survey/SurveyMobile.tsx +125 -0
- package/src/components/Survey/index.ts +5 -0
- package/src/components/Survey/types.ts +22 -0
- package/src/index.ts +23 -0
- package/src/ui/BottomSheet/BottomSheet.tsx +131 -0
- package/src/ui/BottomSheet/index.ts +2 -0
- package/src/ui/Modal/Modal.tsx +92 -0
- package/src/ui/Modal/ModalHeader.tsx +58 -0
- package/src/ui/Modal/index.ts +4 -0
- package/src/ui/SeatSection/SeatSection.tsx +18 -86
- package/src/ui/Survey/FeedbackBanner.tsx +36 -0
- package/src/ui/Survey/FeedbackTextarea.tsx +84 -0
- package/src/ui/Survey/HeartIcon.tsx +18 -0
- package/src/ui/Survey/ScoreButtons.tsx +91 -0
- package/src/ui/Survey/SurveyFooter.tsx +145 -0
- package/src/ui/Survey/SurveyHeader.tsx +72 -0
- package/src/ui/Survey/ThankYouCard.tsx +100 -0
- package/src/ui/Survey/constants.ts +59 -0
- package/src/ui/Survey/index.ts +9 -0
- package/src/ui/mobileweb/DateTimeSectionMobile.tsx +35 -44
- package/src/ui/mobileweb/SeatSectionMobile.tsx +11 -26
- package/src/ui/mobileweb/ServiceBadgesMobile.tsx +2 -2
- package/src/utils/CommonService.ts +1 -7
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { FeedbackConfig, MAX_CHARS } from "./constants";
|
|
3
|
+
|
|
4
|
+
interface FeedbackTextareaProps {
|
|
5
|
+
config: FeedbackConfig | null;
|
|
6
|
+
feedback: string;
|
|
7
|
+
onFeedbackChange?: (text: string) => void;
|
|
8
|
+
colors?: {
|
|
9
|
+
primaryColor?: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const FeedbackTextarea = ({
|
|
14
|
+
config,
|
|
15
|
+
feedback,
|
|
16
|
+
onFeedbackChange,
|
|
17
|
+
colors,
|
|
18
|
+
}: FeedbackTextareaProps) => {
|
|
19
|
+
if (!config) return null;
|
|
20
|
+
return (
|
|
21
|
+
<div style={{ position: "relative", marginTop: 42 }}>
|
|
22
|
+
<span
|
|
23
|
+
style={{
|
|
24
|
+
position: "absolute",
|
|
25
|
+
left: 16,
|
|
26
|
+
top: -10,
|
|
27
|
+
background: "#FFFFFF",
|
|
28
|
+
padding: "0 8px",
|
|
29
|
+
fontSize: "13.33px",
|
|
30
|
+
fontWeight: 600,
|
|
31
|
+
color: colors?.primaryColor || "#374151",
|
|
32
|
+
zIndex: 1,
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
{config.question}
|
|
36
|
+
</span>
|
|
37
|
+
|
|
38
|
+
<div
|
|
39
|
+
style={{
|
|
40
|
+
border: "1.5px solid #E5E7EB",
|
|
41
|
+
borderRadius: 16,
|
|
42
|
+
overflow: "hidden",
|
|
43
|
+
position: "relative",
|
|
44
|
+
background: "transparent",
|
|
45
|
+
}}
|
|
46
|
+
>
|
|
47
|
+
<textarea
|
|
48
|
+
value={feedback}
|
|
49
|
+
onChange={(e) => {
|
|
50
|
+
if (e.target.value.length <= MAX_CHARS)
|
|
51
|
+
onFeedbackChange?.(e.target.value);
|
|
52
|
+
}}
|
|
53
|
+
placeholder="Déjanos tus comentarios (opcional)"
|
|
54
|
+
rows={4}
|
|
55
|
+
style={{
|
|
56
|
+
width: "100%",
|
|
57
|
+
padding: "16px 16px 28px",
|
|
58
|
+
background: "transparent",
|
|
59
|
+
color: "#374151",
|
|
60
|
+
fontSize: "13.33px",
|
|
61
|
+
resize: "none",
|
|
62
|
+
outline: "none",
|
|
63
|
+
border: "none",
|
|
64
|
+
boxSizing: "border-box" as const,
|
|
65
|
+
fontFamily: "inherit",
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
68
|
+
<div
|
|
69
|
+
style={{
|
|
70
|
+
position: "absolute",
|
|
71
|
+
bottom: 8,
|
|
72
|
+
right: 16,
|
|
73
|
+
fontSize: 12,
|
|
74
|
+
color: "#9CA3AF",
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
{feedback.length}/{MAX_CHARS}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export default FeedbackTextarea;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
const HeartIcon = () => (
|
|
4
|
+
<svg
|
|
5
|
+
width="28"
|
|
6
|
+
height="28"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="#22c55e"
|
|
10
|
+
strokeWidth="1.8"
|
|
11
|
+
strokeLinecap="round"
|
|
12
|
+
strokeLinejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
|
|
15
|
+
</svg>
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
export default HeartIcon;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { getZoneColor, getZoneShadow } from "./constants";
|
|
3
|
+
|
|
4
|
+
interface ScoreButtonsProps {
|
|
5
|
+
selectedScore?: number | null;
|
|
6
|
+
onScoreChange?: (score: number) => void;
|
|
7
|
+
buttonHeight?: number;
|
|
8
|
+
fontSize?: number;
|
|
9
|
+
gap?: number;
|
|
10
|
+
colors?: {
|
|
11
|
+
secondaryColor?: string;
|
|
12
|
+
primaryColor?: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const ScoreButtons = ({
|
|
17
|
+
selectedScore,
|
|
18
|
+
onScoreChange,
|
|
19
|
+
buttonHeight = 54,
|
|
20
|
+
fontSize = 15,
|
|
21
|
+
gap = 8,
|
|
22
|
+
colors,
|
|
23
|
+
}: ScoreButtonsProps) => (
|
|
24
|
+
<div style={{ marginBottom: 4 }}>
|
|
25
|
+
<div
|
|
26
|
+
style={{
|
|
27
|
+
display: "grid",
|
|
28
|
+
gridTemplateColumns: "repeat(10, 1fr)",
|
|
29
|
+
gap,
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
{Array.from({ length: 10 }, (_, i) => i + 1).map((num) => {
|
|
33
|
+
const isSelected = selectedScore === num;
|
|
34
|
+
const zoneColor = getZoneColor(num);
|
|
35
|
+
const activeColor = colors?.secondaryColor || zoneColor;
|
|
36
|
+
return (
|
|
37
|
+
<button
|
|
38
|
+
key={num}
|
|
39
|
+
onClick={() => onScoreChange?.(num)}
|
|
40
|
+
onMouseEnter={(e) => {
|
|
41
|
+
if (!isSelected) {
|
|
42
|
+
e.currentTarget.style.borderColor = activeColor;
|
|
43
|
+
e.currentTarget.style.color = activeColor;
|
|
44
|
+
}
|
|
45
|
+
}}
|
|
46
|
+
onMouseLeave={(e) => {
|
|
47
|
+
if (!isSelected) {
|
|
48
|
+
e.currentTarget.style.borderColor = "#E5E7EB";
|
|
49
|
+
e.currentTarget.style.color = "#111827";
|
|
50
|
+
}
|
|
51
|
+
}}
|
|
52
|
+
style={{
|
|
53
|
+
height: buttonHeight,
|
|
54
|
+
borderRadius: 10,
|
|
55
|
+
fontSize,
|
|
56
|
+
border: isSelected ? "none" : "1px solid #E5E7EB",
|
|
57
|
+
background: isSelected ? activeColor : "#FFFFFF",
|
|
58
|
+
color: isSelected ? "#FFFFFF" : "#111827",
|
|
59
|
+
cursor: "pointer",
|
|
60
|
+
transition: "border-color 0.15s, color 0.15s, background 0.15s",
|
|
61
|
+
boxShadow: isSelected
|
|
62
|
+
? colors?.secondaryColor
|
|
63
|
+
? `0 2px 8px ${colors.secondaryColor}58`
|
|
64
|
+
: getZoneShadow(num)
|
|
65
|
+
: "none",
|
|
66
|
+
display: "flex",
|
|
67
|
+
alignItems: "center",
|
|
68
|
+
justifyContent: "center",
|
|
69
|
+
boxSizing: "border-box" as const,
|
|
70
|
+
}}
|
|
71
|
+
>
|
|
72
|
+
{num}
|
|
73
|
+
</button>
|
|
74
|
+
);
|
|
75
|
+
})}
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<div
|
|
79
|
+
style={{
|
|
80
|
+
display: "flex",
|
|
81
|
+
justifyContent: "space-between",
|
|
82
|
+
marginTop: 8,
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
<span style={{ fontSize: 12, color: "#9CA3AF" }}>Poco probable</span>
|
|
86
|
+
<span style={{ fontSize: 12, color: "#9CA3AF" }}>Muy probable</span>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
export default ScoreButtons;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { BRAND } from "./constants";
|
|
3
|
+
|
|
4
|
+
interface SurveyFooterProps {
|
|
5
|
+
selectedScore?: number | null;
|
|
6
|
+
onSkip?: () => void;
|
|
7
|
+
onSubmit: () => void;
|
|
8
|
+
layout?: "inline" | "stacked";
|
|
9
|
+
colors?: {
|
|
10
|
+
secondaryColor?: string;
|
|
11
|
+
tertiaryColor?: string;
|
|
12
|
+
primaryColor?: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const SurveyFooter = ({
|
|
17
|
+
selectedScore,
|
|
18
|
+
onSkip,
|
|
19
|
+
onSubmit,
|
|
20
|
+
layout = "inline",
|
|
21
|
+
colors,
|
|
22
|
+
}: SurveyFooterProps) => {
|
|
23
|
+
if (layout === "stacked") {
|
|
24
|
+
return (
|
|
25
|
+
<div style={{ marginTop: 24 }}>
|
|
26
|
+
<button
|
|
27
|
+
onClick={onSkip}
|
|
28
|
+
style={{
|
|
29
|
+
display: "block",
|
|
30
|
+
width: "100%",
|
|
31
|
+
textAlign: "center",
|
|
32
|
+
fontSize: "13.33px",
|
|
33
|
+
color: "#6B7280",
|
|
34
|
+
background: "none",
|
|
35
|
+
border: "none",
|
|
36
|
+
cursor: "pointer",
|
|
37
|
+
padding: "0 0 14px",
|
|
38
|
+
}}
|
|
39
|
+
>
|
|
40
|
+
Saltar por ahora
|
|
41
|
+
</button>
|
|
42
|
+
|
|
43
|
+
<button
|
|
44
|
+
onClick={onSubmit}
|
|
45
|
+
disabled={selectedScore == null}
|
|
46
|
+
style={{
|
|
47
|
+
display: "flex",
|
|
48
|
+
alignItems: "center",
|
|
49
|
+
justifyContent: "center",
|
|
50
|
+
gap: 8,
|
|
51
|
+
width: "100%",
|
|
52
|
+
padding: "16px",
|
|
53
|
+
borderRadius: 999,
|
|
54
|
+
fontSize: "13.33px",
|
|
55
|
+
fontWeight: 700,
|
|
56
|
+
letterSpacing: "0.08em",
|
|
57
|
+
textTransform: "uppercase" as const,
|
|
58
|
+
border: "none",
|
|
59
|
+
cursor: selectedScore != null ? "pointer" : "not-allowed",
|
|
60
|
+
background:
|
|
61
|
+
selectedScore != null
|
|
62
|
+
? colors?.secondaryColor
|
|
63
|
+
: "rgba(232,76,13,0.28)",
|
|
64
|
+
color: "#FFFFFF",
|
|
65
|
+
transition: "background 0.15s",
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
Enviar comentarios <span>→</span>
|
|
69
|
+
</button>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<>
|
|
76
|
+
<div
|
|
77
|
+
style={{
|
|
78
|
+
display: "flex",
|
|
79
|
+
alignItems: "center",
|
|
80
|
+
justifyContent: "space-between",
|
|
81
|
+
marginTop: 24,
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
<button
|
|
85
|
+
onClick={onSkip}
|
|
86
|
+
style={{
|
|
87
|
+
fontSize: "13.33px",
|
|
88
|
+
color: "#6B7280",
|
|
89
|
+
background: "none",
|
|
90
|
+
border: "none",
|
|
91
|
+
cursor: "pointer",
|
|
92
|
+
padding: 0,
|
|
93
|
+
}}
|
|
94
|
+
>
|
|
95
|
+
Saltar por ahora
|
|
96
|
+
</button>
|
|
97
|
+
|
|
98
|
+
<button
|
|
99
|
+
onClick={onSubmit}
|
|
100
|
+
disabled={selectedScore == null}
|
|
101
|
+
style={{
|
|
102
|
+
display: "flex",
|
|
103
|
+
alignItems: "center",
|
|
104
|
+
gap: 8,
|
|
105
|
+
padding: "14px 28px",
|
|
106
|
+
borderRadius: 999,
|
|
107
|
+
fontSize: "13.33px",
|
|
108
|
+
fontWeight: 700,
|
|
109
|
+
letterSpacing: "0.08em",
|
|
110
|
+
textTransform: "uppercase" as const,
|
|
111
|
+
border: "none",
|
|
112
|
+
cursor: selectedScore != null ? "pointer" : "not-allowed",
|
|
113
|
+
background:
|
|
114
|
+
selectedScore != null
|
|
115
|
+
? colors?.secondaryColor
|
|
116
|
+
: "rgba(232,76,13,0.28)",
|
|
117
|
+
color: "#FFFFFF",
|
|
118
|
+
transition: "background 0.15s",
|
|
119
|
+
minWidth: 160,
|
|
120
|
+
justifyContent: "center",
|
|
121
|
+
}}
|
|
122
|
+
>
|
|
123
|
+
Enviar comentarios <span>→</span>
|
|
124
|
+
</button>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<div
|
|
128
|
+
style={{
|
|
129
|
+
display: "flex",
|
|
130
|
+
alignItems: "center",
|
|
131
|
+
justifyContent: "center",
|
|
132
|
+
gap: 6,
|
|
133
|
+
marginTop: 14,
|
|
134
|
+
fontSize: 12,
|
|
135
|
+
color: "#9CA3AF",
|
|
136
|
+
}}
|
|
137
|
+
>
|
|
138
|
+
<span>🔒</span>
|
|
139
|
+
<span>Anónimo · solo se usa para mejorar el servicio</span>
|
|
140
|
+
</div>
|
|
141
|
+
</>
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export default SurveyFooter;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { BRAND } from "./constants";
|
|
3
|
+
|
|
4
|
+
interface SurveyHeaderProps {
|
|
5
|
+
onClose?: () => void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const SurveyHeader = ({ onClose }: SurveyHeaderProps) => (
|
|
9
|
+
<div
|
|
10
|
+
style={{
|
|
11
|
+
display: "flex",
|
|
12
|
+
alignItems: "center",
|
|
13
|
+
justifyContent: "space-between",
|
|
14
|
+
}}
|
|
15
|
+
>
|
|
16
|
+
<div style={{ display: "flex", alignItems: "center", gap: 6 }}>
|
|
17
|
+
<span
|
|
18
|
+
style={{
|
|
19
|
+
width: 8,
|
|
20
|
+
height: 8,
|
|
21
|
+
borderRadius: "50%",
|
|
22
|
+
backgroundColor: BRAND,
|
|
23
|
+
display: "inline-block",
|
|
24
|
+
flexShrink: 0,
|
|
25
|
+
}}
|
|
26
|
+
/>
|
|
27
|
+
<span
|
|
28
|
+
style={{
|
|
29
|
+
color: BRAND,
|
|
30
|
+
fontSize: 11,
|
|
31
|
+
fontWeight: 700,
|
|
32
|
+
letterSpacing: "0.1em",
|
|
33
|
+
textTransform: "uppercase",
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
Comentarios rápidos
|
|
37
|
+
</span>
|
|
38
|
+
<span
|
|
39
|
+
style={{
|
|
40
|
+
color: "#9CA3AF",
|
|
41
|
+
fontSize: 11,
|
|
42
|
+
letterSpacing: "0.06em",
|
|
43
|
+
textTransform: "uppercase",
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
· Tarda 20 segundos
|
|
47
|
+
</span>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<button
|
|
51
|
+
onClick={onClose}
|
|
52
|
+
style={{
|
|
53
|
+
width: 36,
|
|
54
|
+
height: 36,
|
|
55
|
+
borderRadius: "50%",
|
|
56
|
+
background: "#F3F4F6",
|
|
57
|
+
border: "none",
|
|
58
|
+
cursor: "pointer",
|
|
59
|
+
fontSize: 14,
|
|
60
|
+
color: "#6B7280",
|
|
61
|
+
display: "flex",
|
|
62
|
+
alignItems: "center",
|
|
63
|
+
justifyContent: "center",
|
|
64
|
+
flexShrink: 0,
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
✕
|
|
68
|
+
</button>
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
export default SurveyHeader;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import HeartIcon from "./HeartIcon";
|
|
3
|
+
import { BRAND } from "./constants";
|
|
4
|
+
|
|
5
|
+
import succes_anim from "../../assets/images/anims/service_list/succes_anim.json";
|
|
6
|
+
import LottiePlayer from "../../assets/LottiePlayer";
|
|
7
|
+
|
|
8
|
+
interface ThankYouCardProps {
|
|
9
|
+
onClose?: () => void;
|
|
10
|
+
titleFontSize?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const ThankYouCard = ({
|
|
14
|
+
onClose,
|
|
15
|
+
titleFontSize = "1.5rem",
|
|
16
|
+
}: ThankYouCardProps) => (
|
|
17
|
+
<div
|
|
18
|
+
style={{
|
|
19
|
+
display: "flex",
|
|
20
|
+
flexDirection: "column",
|
|
21
|
+
alignItems: "center",
|
|
22
|
+
justifyContent: "center",
|
|
23
|
+
padding: "48px 40px 40px",
|
|
24
|
+
position: "relative",
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
<button
|
|
28
|
+
onClick={onClose}
|
|
29
|
+
style={{
|
|
30
|
+
position: "absolute",
|
|
31
|
+
top: 16,
|
|
32
|
+
right: 16,
|
|
33
|
+
width: 34,
|
|
34
|
+
height: 34,
|
|
35
|
+
borderRadius: "50%",
|
|
36
|
+
border: "none",
|
|
37
|
+
background: "#F3F4F6",
|
|
38
|
+
color: "#6B7280",
|
|
39
|
+
fontSize: 14,
|
|
40
|
+
cursor: "pointer",
|
|
41
|
+
display: "flex",
|
|
42
|
+
alignItems: "center",
|
|
43
|
+
justifyContent: "center",
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
✕
|
|
47
|
+
</button>
|
|
48
|
+
|
|
49
|
+
<div
|
|
50
|
+
style={{
|
|
51
|
+
width: 64,
|
|
52
|
+
height: 64,
|
|
53
|
+
borderRadius: "50%",
|
|
54
|
+
backgroundColor: "#DCFCE7",
|
|
55
|
+
display: "flex",
|
|
56
|
+
alignItems: "center",
|
|
57
|
+
justifyContent: "center",
|
|
58
|
+
marginBottom: 20,
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
<LottiePlayer
|
|
62
|
+
animationData={succes_anim}
|
|
63
|
+
loop={true}
|
|
64
|
+
autoplay={true}
|
|
65
|
+
width="70px"
|
|
66
|
+
height="70px"
|
|
67
|
+
/>
|
|
68
|
+
{/* <HeartIcon /> */}
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<h2
|
|
72
|
+
style={{
|
|
73
|
+
fontSize: titleFontSize,
|
|
74
|
+
fontWeight: 700,
|
|
75
|
+
color: "#111827",
|
|
76
|
+
textAlign: "center",
|
|
77
|
+
marginBottom: 10,
|
|
78
|
+
lineHeight: 1.3,
|
|
79
|
+
}}
|
|
80
|
+
>
|
|
81
|
+
Gracias por tu{" "}
|
|
82
|
+
<em
|
|
83
|
+
style={{
|
|
84
|
+
color: BRAND,
|
|
85
|
+
fontFamily: "Georgia, 'Times New Roman', serif",
|
|
86
|
+
fontStyle: "italic",
|
|
87
|
+
fontWeight: "bold",
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
comentario
|
|
91
|
+
</em>
|
|
92
|
+
</h2>
|
|
93
|
+
|
|
94
|
+
<p style={{ fontSize: "13.33px", color: "#6B7280", textAlign: "center" }}>
|
|
95
|
+
Hemos leído todas las respuestas. ¡Que tengas un buen viaje!
|
|
96
|
+
</p>
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
export default ThankYouCard;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export const BRAND = "#E84C0D";
|
|
2
|
+
export const MAX_CHARS = 250;
|
|
3
|
+
|
|
4
|
+
export type FeedbackConfig = {
|
|
5
|
+
emoji: string;
|
|
6
|
+
message: string;
|
|
7
|
+
bannerBg: string;
|
|
8
|
+
bannerText: string;
|
|
9
|
+
question: string;
|
|
10
|
+
placeholder: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const getZoneColor = (num: number): string => {
|
|
14
|
+
if (num <= 6) return "#E84C0D";
|
|
15
|
+
if (num <= 8) return "#F59E0B";
|
|
16
|
+
return "#22C55E";
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const getZoneShadow = (num: number): string => {
|
|
20
|
+
if (num <= 6) return "0 2px 8px rgba(232,76,13,0.35)";
|
|
21
|
+
if (num <= 8) return "0 2px 8px rgba(245,158,11,0.35)";
|
|
22
|
+
return "0 2px 8px rgba(34,197,94,0.35)";
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const getFeedbackConfig = (
|
|
26
|
+
score: number | null | undefined,
|
|
27
|
+
): FeedbackConfig | null => {
|
|
28
|
+
if (score == null) return null;
|
|
29
|
+
if (score <= 6)
|
|
30
|
+
return {
|
|
31
|
+
emoji: "😔",
|
|
32
|
+
message: "Lo sentimos, no cumplimos tus expectativas.",
|
|
33
|
+
bannerBg: "#FFF0EE",
|
|
34
|
+
bannerText: BRAND,
|
|
35
|
+
question: "¿Qué salió mal?",
|
|
36
|
+
placeholder:
|
|
37
|
+
"Cuéntanos qué podríamos haber hecho mejor — cada detalle nos ayuda.",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
if (score <= 8)
|
|
41
|
+
return {
|
|
42
|
+
emoji: "🤔",
|
|
43
|
+
message: "Gracias — apreciamos tu sinceridad.",
|
|
44
|
+
bannerBg: "#FFFBEB",
|
|
45
|
+
bannerText: "#92400E",
|
|
46
|
+
question: "¿Qué podría mejorar?",
|
|
47
|
+
placeholder:
|
|
48
|
+
"Cuéntanos qué podría hacer que la experiencia sea aún mejor.",
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
emoji: "🎉",
|
|
53
|
+
message: "¡Nos acabas de alegrar el día!",
|
|
54
|
+
bannerBg: "#F0FDF4",
|
|
55
|
+
bannerText: "#166534",
|
|
56
|
+
question: "¿Qué hicimos bien?",
|
|
57
|
+
placeholder: "¡Nos encantaría saber qué fue lo que más te gustó!",
|
|
58
|
+
};
|
|
59
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { default as HeartIcon } from "./HeartIcon";
|
|
2
|
+
export { default as ThankYouCard } from "./ThankYouCard";
|
|
3
|
+
export { default as SurveyHeader } from "./SurveyHeader";
|
|
4
|
+
export { default as ScoreButtons } from "./ScoreButtons";
|
|
5
|
+
export { default as FeedbackBanner } from "./FeedbackBanner";
|
|
6
|
+
export { default as FeedbackTextarea } from "./FeedbackTextarea";
|
|
7
|
+
export { default as SurveyFooter } from "./SurveyFooter";
|
|
8
|
+
export { BRAND, MAX_CHARS, getZoneColor, getZoneShadow, getFeedbackConfig } from "./constants";
|
|
9
|
+
export type { FeedbackConfig } from "./constants";
|
|
@@ -25,7 +25,6 @@ interface DateTimeSectionMobileProps {
|
|
|
25
25
|
tooltipBgColor?: string;
|
|
26
26
|
showLastSeats?: boolean;
|
|
27
27
|
discountSeatPriceColor?: string;
|
|
28
|
-
isTrain?: boolean;
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
const pad = (n: number) => (n < 10 ? "0" + n : String(n));
|
|
@@ -68,43 +67,41 @@ const TimeRow: React.FC<TimeRowProps> = ({
|
|
|
68
67
|
isSoldOut,
|
|
69
68
|
}) => {
|
|
70
69
|
const formattedDate = DateService.getServiceItemDate(date);
|
|
71
|
-
const dotPositionClass = formattedDate.includes("dom")
|
|
72
|
-
|
|
73
|
-
:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<div className="font-[900] relative black-text">{timeContent}</div>
|
|
104
|
-
</div>
|
|
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
|
+
/>
|
|
90
|
+
</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>
|
|
105
102
|
</div>
|
|
106
103
|
</div>
|
|
107
|
-
|
|
104
|
+
</div>;
|
|
108
105
|
};
|
|
109
106
|
|
|
110
107
|
function DateTimeSectionMobile({
|
|
@@ -130,7 +127,6 @@ function DateTimeSectionMobile({
|
|
|
130
127
|
tooltipBgColor,
|
|
131
128
|
showLastSeats,
|
|
132
129
|
discountSeatPriceColor,
|
|
133
|
-
isTrain,
|
|
134
130
|
}: DateTimeSectionMobileProps): React.ReactElement {
|
|
135
131
|
const { cleaned: cleanedDepTime, hasAM, hasPM } = getCleanedDepTime(depTime);
|
|
136
132
|
|
|
@@ -157,12 +153,8 @@ function DateTimeSectionMobile({
|
|
|
157
153
|
>
|
|
158
154
|
{/* DATE AND TIME */}
|
|
159
155
|
<div
|
|
160
|
-
className=
|
|
161
|
-
style={{
|
|
162
|
-
justifyContent: isCiva && "center",
|
|
163
|
-
minHeight: isTrain ? undefined : "2.5rem",
|
|
164
|
-
alignSelf: isTrain ? "stretch" : undefined,
|
|
165
|
-
}}
|
|
156
|
+
className="min-h-[2.5rem] flex flex-col justify-between gap-[4px] w-[50%] "
|
|
157
|
+
style={{ justifyContent: isCiva && "center" }}
|
|
166
158
|
>
|
|
167
159
|
<TimeRow
|
|
168
160
|
label={orignLabel}
|
|
@@ -206,7 +198,6 @@ function DateTimeSectionMobile({
|
|
|
206
198
|
tooltipBgColor={tooltipBgColor}
|
|
207
199
|
showLastSeats={showLastSeats}
|
|
208
200
|
discountSeatPriceColor={discountSeatPriceColor}
|
|
209
|
-
isTrain={isTrain}
|
|
210
201
|
/>
|
|
211
202
|
</div>
|
|
212
203
|
);
|