@windstream/react-shared-components 0.2.45 → 0.2.47
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/contentful/index.d.ts +2 -1
- package/dist/contentful/index.esm.js +3 -3
- package/dist/contentful/index.esm.js.map +1 -1
- package/dist/contentful/index.js +2 -2
- package/dist/contentful/index.js.map +1 -1
- package/dist/core.d.ts +151 -3
- package/dist/index.d.ts +152 -4
- package/dist/index.esm.js +6 -6
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/next/index.esm.js +2 -2
- package/dist/next/index.esm.js.map +1 -1
- package/dist/next/index.js +2 -2
- package/dist/next/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.esm.js +1 -1
- package/dist/utils/index.esm.js.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +4 -2
- package/src/components/brand-button/index.tsx +2 -2
- package/src/components/video-link/index.test.tsx +1 -1
- package/src/components/video-link/index.tsx +6 -6
- package/src/contentful/blocks/email-input-block/index.test.tsx +189 -161
- package/src/contentful/blocks/fiber-form/constants.ts +81 -0
- package/src/contentful/blocks/fiber-form/index.tsx +557 -0
- package/src/contentful/blocks/fiber-form/types.ts +92 -0
- package/src/contentful/blocks/primary-hero/index.tsx +1 -1
- package/src/hooks/contentful/use-contentful-rich-text.test.tsx +118 -0
- package/src/hooks/contentful/use-contentful-rich-text.tsx +72 -13
- package/src/index.ts +20 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@windstream/react-shared-components",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.47",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shared React components for Kinetic applications",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -110,12 +110,14 @@
|
|
|
110
110
|
"@types/react-modal": "3.16.3",
|
|
111
111
|
"@types/react-transition-group": "4.4.12",
|
|
112
112
|
"clsx": "2.1.1",
|
|
113
|
+
"formik": "^2.4.6",
|
|
113
114
|
"framer-motion": "10.12.16",
|
|
114
115
|
"js-base64": "^3.7.7",
|
|
115
116
|
"js-cookie": "^3.0.5",
|
|
116
117
|
"react-modal": "3.16.3",
|
|
117
118
|
"react-select": "5.10.2",
|
|
118
|
-
"react-transition-group": "4.4.5"
|
|
119
|
+
"react-transition-group": "4.4.5",
|
|
120
|
+
"yup": "^1.7.0"
|
|
119
121
|
},
|
|
120
122
|
"optionalDependencies": {
|
|
121
123
|
"@types/js-cookie": "^3.0.6"
|
|
@@ -48,8 +48,8 @@ export const BrandButton = forwardRef<
|
|
|
48
48
|
const getVariantClasses = () => {
|
|
49
49
|
const baseClasses = cx(
|
|
50
50
|
sizeToClassNames(size),
|
|
51
|
-
"rounded-button
|
|
52
|
-
fullWidth ? "w-full" : "w-
|
|
51
|
+
"rounded-button pl-15 pr-15 inline-flex gap-2 items-center justify-center outline-none focus:outline focus:outline-2 focus:outline-offset-2 cursor-pointer transition-colors duration-200 align-top sm:whitespace-nowrap",
|
|
52
|
+
fullWidth ? "w-full" : "w-auto"
|
|
53
53
|
);
|
|
54
54
|
|
|
55
55
|
const variantClasses: Record<ButtonVariantsT, string> = {
|
|
@@ -20,10 +20,10 @@ export const VideoLink: React.FC<VideoLinkComponentProps> = ({
|
|
|
20
20
|
const [isHovered, setIsHovered] = useState(false);
|
|
21
21
|
|
|
22
22
|
const videoSourceType = videoLink?.videoSourceType;
|
|
23
|
+
const usingContentfulAsset =
|
|
24
|
+
videoSourceType === "contentful" && !!videoLink?.videoAssetUrl;
|
|
23
25
|
const videoHref =
|
|
24
|
-
(
|
|
25
|
-
? videoLink?.videoAssetUrl
|
|
26
|
-
: videoLink?.link) ?? "";
|
|
26
|
+
(usingContentfulAsset ? videoLink?.videoAssetUrl : videoLink?.link) ?? "";
|
|
27
27
|
|
|
28
28
|
// The video's own poster - never the promo bar's plain image field.
|
|
29
29
|
const posterImage = videoLink?.image;
|
|
@@ -69,7 +69,7 @@ export const VideoLink: React.FC<VideoLinkComponentProps> = ({
|
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
const embedSelector = () => {
|
|
72
|
-
if (
|
|
72
|
+
if (usingContentfulAsset) {
|
|
73
73
|
return (
|
|
74
74
|
<ContentfulVideoEmbed
|
|
75
75
|
videoAssetUrl={videoLink?.videoAssetUrl}
|
|
@@ -92,7 +92,7 @@ export const VideoLink: React.FC<VideoLinkComponentProps> = ({
|
|
|
92
92
|
<>
|
|
93
93
|
<div
|
|
94
94
|
className={cx(
|
|
95
|
-
"video-section relative w-full cursor-pointer rounded-image transition-all duration-300 lg:w-[486px]",
|
|
95
|
+
"video-section relative mx-auto w-full cursor-pointer rounded-image transition-all duration-300 lg:w-[486px]",
|
|
96
96
|
!isPlaying && "hover:ring-2 hover:ring-border-focus"
|
|
97
97
|
)}
|
|
98
98
|
onClick={handlePlayClick}
|
|
@@ -167,4 +167,4 @@ export type {
|
|
|
167
167
|
VideoEmbedProps,
|
|
168
168
|
VideoLinkComponentProps,
|
|
169
169
|
VideoLinkProps,
|
|
170
|
-
} from "./types";
|
|
170
|
+
} from "./types";
|
|
@@ -1,204 +1,232 @@
|
|
|
1
|
+
/// <reference types="jest" />
|
|
2
|
+
/// <reference types="@testing-library/jest-dom" />
|
|
3
|
+
|
|
1
4
|
import { EmailInputBlock } from "./index";
|
|
5
|
+
import { EmailInputBlockProps } from "./types";
|
|
2
6
|
|
|
3
7
|
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
};
|
|
9
|
+
const defaultProps: EmailInputBlockProps = {
|
|
10
|
+
onSubmit: jest.fn(),
|
|
11
|
+
};
|
|
9
12
|
|
|
13
|
+
describe("EmailInputBlock", () => {
|
|
10
14
|
beforeEach(() => {
|
|
11
15
|
jest.clearAllMocks();
|
|
12
16
|
});
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
describe("Rendering", () => {
|
|
19
|
+
it("renders with default props", () => {
|
|
20
|
+
const { container } = render(<EmailInputBlock {...defaultProps} />);
|
|
21
|
+
expect(container.querySelector("#email-input")).toBeInTheDocument();
|
|
22
|
+
});
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
it("renders custom anchorId", () => {
|
|
25
|
+
const { container } = render(
|
|
26
|
+
<EmailInputBlock {...defaultProps} anchorId="custom-anchor" />
|
|
27
|
+
);
|
|
28
|
+
expect(container.querySelector("#custom-anchor")).toBeInTheDocument();
|
|
29
|
+
});
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
it("renders title when provided", () => {
|
|
32
|
+
render(<EmailInputBlock {...defaultProps} title="Join us" />);
|
|
33
|
+
const title = screen.getByText("Join us");
|
|
34
|
+
expect(title).toBeInTheDocument();
|
|
35
|
+
expect(title.tagName).toBe("H1");
|
|
36
|
+
});
|
|
31
37
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
it("does not render title when not provided", () => {
|
|
39
|
+
const { container } = render(<EmailInputBlock {...defaultProps} />);
|
|
40
|
+
expect(container.querySelector("h1")).not.toBeInTheDocument();
|
|
41
|
+
});
|
|
36
42
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
it("renders subTitle when provided", () => {
|
|
44
|
+
render(<EmailInputBlock {...defaultProps} subTitle="Stay updated" />);
|
|
45
|
+
const subtitle = screen.getByText("Stay updated");
|
|
46
|
+
expect(subtitle).toBeInTheDocument();
|
|
47
|
+
expect(subtitle.tagName).toBe("H2");
|
|
48
|
+
});
|
|
42
49
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
it("does not render subTitle when not provided", () => {
|
|
51
|
+
const { container } = render(<EmailInputBlock {...defaultProps} />);
|
|
52
|
+
expect(container.querySelector("h2")).not.toBeInTheDocument();
|
|
53
|
+
});
|
|
47
54
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
it("renders emailInputDescription when provided", () => {
|
|
56
|
+
render(
|
|
57
|
+
<EmailInputBlock
|
|
58
|
+
{...defaultProps}
|
|
59
|
+
emailInputDescription="Sign up now"
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
expect(screen.getByText("Sign up now")).toBeInTheDocument();
|
|
63
|
+
});
|
|
54
64
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
it("renders caption when provided", () => {
|
|
66
|
+
render(<EmailInputBlock {...defaultProps} caption="No spam" />);
|
|
67
|
+
expect(screen.getByText("No spam")).toBeInTheDocument();
|
|
68
|
+
});
|
|
59
69
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
70
|
+
it("does not render caption when not provided", () => {
|
|
71
|
+
render(<EmailInputBlock {...defaultProps} />);
|
|
72
|
+
expect(screen.queryByText("No spam")).not.toBeInTheDocument();
|
|
73
|
+
});
|
|
64
74
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
it("uses default placeholder text", () => {
|
|
76
|
+
render(<EmailInputBlock {...defaultProps} />);
|
|
77
|
+
expect(
|
|
78
|
+
screen.getByPlaceholderText("Enter your email here")
|
|
79
|
+
).toBeInTheDocument();
|
|
80
|
+
});
|
|
71
81
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
82
|
+
it("uses custom placeholder text", () => {
|
|
83
|
+
render(
|
|
84
|
+
<EmailInputBlock {...defaultProps} inputPlaceholder="Your email" />
|
|
85
|
+
);
|
|
86
|
+
expect(screen.getByPlaceholderText("Your email")).toBeInTheDocument();
|
|
87
|
+
});
|
|
75
88
|
});
|
|
76
89
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
describe("Form submission", () => {
|
|
91
|
+
it("calls onSubmit with email on valid submission", () => {
|
|
92
|
+
render(<EmailInputBlock {...defaultProps} />);
|
|
93
|
+
const input = screen.getByPlaceholderText("Enter your email here");
|
|
94
|
+
fireEvent.change(input, { target: { value: "test@example.com" } });
|
|
95
|
+
fireEvent.click(screen.getByText("Sign me up"));
|
|
96
|
+
expect(defaultProps.onSubmit).toHaveBeenCalledWith({
|
|
97
|
+
email: "test@example.com",
|
|
98
|
+
});
|
|
84
99
|
});
|
|
85
|
-
});
|
|
86
100
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
101
|
+
it("clears email after successful submission", () => {
|
|
102
|
+
render(<EmailInputBlock {...defaultProps} />);
|
|
103
|
+
const input = screen.getByPlaceholderText(
|
|
104
|
+
"Enter your email here"
|
|
105
|
+
) as HTMLInputElement;
|
|
106
|
+
fireEvent.change(input, { target: { value: "test@example.com" } });
|
|
107
|
+
fireEvent.click(screen.getByText("Sign me up"));
|
|
108
|
+
expect(input.value).toBe("");
|
|
109
|
+
});
|
|
95
110
|
});
|
|
96
111
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
112
|
+
describe("Validation", () => {
|
|
113
|
+
it("shows error for invalid email", () => {
|
|
114
|
+
render(<EmailInputBlock {...defaultProps} />);
|
|
115
|
+
const input = screen.getByPlaceholderText("Enter your email here");
|
|
116
|
+
fireEvent.change(input, { target: { value: "invalid" } });
|
|
117
|
+
fireEvent.click(screen.getByText("Sign me up"));
|
|
118
|
+
expect(screen.getByText("Invalid email address")).toBeInTheDocument();
|
|
119
|
+
expect(defaultProps.onSubmit).not.toHaveBeenCalled();
|
|
120
|
+
});
|
|
105
121
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
122
|
+
it("shows required error for empty email", () => {
|
|
123
|
+
render(<EmailInputBlock {...defaultProps} />);
|
|
124
|
+
fireEvent.click(screen.getByText("Sign me up"));
|
|
125
|
+
expect(screen.getByText("Email is required")).toBeInTheDocument();
|
|
126
|
+
expect(defaultProps.onSubmit).not.toHaveBeenCalled();
|
|
127
|
+
});
|
|
112
128
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
129
|
+
it("clears error when user types a valid email after error", () => {
|
|
130
|
+
render(<EmailInputBlock {...defaultProps} />);
|
|
131
|
+
const input = screen.getByPlaceholderText("Enter your email here");
|
|
132
|
+
fireEvent.change(input, { target: { value: "invalid" } });
|
|
133
|
+
fireEvent.click(screen.getByText("Sign me up"));
|
|
134
|
+
expect(screen.getByText("Invalid email address")).toBeInTheDocument();
|
|
135
|
+
|
|
136
|
+
fireEvent.change(input, { target: { value: "user@test.com" } });
|
|
137
|
+
expect(
|
|
138
|
+
screen.queryByText("Invalid email address")
|
|
139
|
+
).not.toBeInTheDocument();
|
|
140
|
+
});
|
|
124
141
|
});
|
|
125
142
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
143
|
+
describe("Success feedback", () => {
|
|
144
|
+
it("shows success feedback after valid submission", () => {
|
|
145
|
+
render(<EmailInputBlock {...defaultProps} successFeedback="Thanks!" />);
|
|
146
|
+
const input = screen.getByPlaceholderText("Enter your email here");
|
|
147
|
+
fireEvent.change(input, { target: { value: "user@test.com" } });
|
|
148
|
+
fireEvent.click(screen.getByText("Sign me up"));
|
|
149
|
+
expect(screen.getByText("Thanks!")).toBeInTheDocument();
|
|
150
|
+
});
|
|
133
151
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
152
|
+
it("hides success feedback when user types again", () => {
|
|
153
|
+
render(<EmailInputBlock {...defaultProps} successFeedback="Thanks!" />);
|
|
154
|
+
const input = screen.getByPlaceholderText("Enter your email here");
|
|
155
|
+
fireEvent.change(input, { target: { value: "user@test.com" } });
|
|
156
|
+
fireEvent.click(screen.getByText("Sign me up"));
|
|
157
|
+
expect(screen.getByText("Thanks!")).toBeInTheDocument();
|
|
140
158
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
159
|
+
fireEvent.change(input, { target: { value: "x" } });
|
|
160
|
+
expect(screen.queryByText("Thanks!")).not.toBeInTheDocument();
|
|
161
|
+
});
|
|
144
162
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
163
|
+
it("does not show success feedback without successFeedback prop", () => {
|
|
164
|
+
render(<EmailInputBlock {...defaultProps} />);
|
|
165
|
+
const input = screen.getByPlaceholderText("Enter your email here");
|
|
166
|
+
fireEvent.change(input, { target: { value: "user@test.com" } });
|
|
167
|
+
fireEvent.click(screen.getByText("Sign me up"));
|
|
168
|
+
expect(screen.queryByText("Thanks!")).not.toBeInTheDocument();
|
|
169
|
+
});
|
|
152
170
|
});
|
|
153
171
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
172
|
+
describe("Themes", () => {
|
|
173
|
+
it("applies green theme background by default", () => {
|
|
174
|
+
const { container } = render(<EmailInputBlock {...defaultProps} />);
|
|
175
|
+
expect(
|
|
176
|
+
container.querySelector(".bg-bg-fill-brand")
|
|
177
|
+
).toBeInTheDocument();
|
|
178
|
+
});
|
|
158
179
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
180
|
+
it("applies blue theme background class", () => {
|
|
181
|
+
const { container } = render(
|
|
182
|
+
<EmailInputBlock {...defaultProps} themeColor="blue" />
|
|
183
|
+
);
|
|
184
|
+
expect(
|
|
185
|
+
container.querySelector(".bg-bg-fill-brand-supporting")
|
|
186
|
+
).toBeInTheDocument();
|
|
187
|
+
});
|
|
167
188
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
189
|
+
it("applies purple theme background class", () => {
|
|
190
|
+
const { container } = render(
|
|
191
|
+
<EmailInputBlock {...defaultProps} themeColor="purple" />
|
|
192
|
+
);
|
|
193
|
+
expect(
|
|
194
|
+
container.querySelector(".bg-bg-fill-brand-tertiary")
|
|
195
|
+
).toBeInTheDocument();
|
|
196
|
+
});
|
|
176
197
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
198
|
+
it("applies white outer background class by default", () => {
|
|
199
|
+
const { container } = render(<EmailInputBlock {...defaultProps} />);
|
|
200
|
+
expect(container.querySelector("section")).toHaveClass("bg-bg");
|
|
201
|
+
});
|
|
181
202
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
203
|
+
it("uses white text for dark themes", () => {
|
|
204
|
+
render(
|
|
205
|
+
<EmailInputBlock
|
|
206
|
+
{...defaultProps}
|
|
207
|
+
themeColor="blue"
|
|
208
|
+
title="Blue title"
|
|
209
|
+
/>
|
|
210
|
+
);
|
|
211
|
+
expect(screen.getByText("Blue title")).toHaveClass("text-white");
|
|
212
|
+
});
|
|
188
213
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
214
|
+
it("uses dark text for the white theme", () => {
|
|
215
|
+
render(
|
|
216
|
+
<EmailInputBlock
|
|
217
|
+
{...defaultProps}
|
|
218
|
+
themeColor="white"
|
|
219
|
+
title="White title"
|
|
220
|
+
/>
|
|
221
|
+
);
|
|
222
|
+
expect(screen.getByText("White title")).toHaveClass("text-text");
|
|
223
|
+
});
|
|
198
224
|
});
|
|
199
225
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
226
|
+
describe("Call to action", () => {
|
|
227
|
+
it("uses custom ctaText", () => {
|
|
228
|
+
render(<EmailInputBlock {...defaultProps} ctaText="Subscribe" />);
|
|
229
|
+
expect(screen.getByText("Subscribe")).toBeInTheDocument();
|
|
230
|
+
});
|
|
203
231
|
});
|
|
204
232
|
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { FiberFormInputList, FiberFormValues } from "../../blocks/fiber-form/types";
|
|
2
|
+
import * as Yup from "yup";
|
|
3
|
+
|
|
4
|
+
export const fiberFormInputInitialValues: FiberFormValues = {
|
|
5
|
+
firstName: "",
|
|
6
|
+
lastName: "",
|
|
7
|
+
address: "",
|
|
8
|
+
phone: "",
|
|
9
|
+
email: "",
|
|
10
|
+
unit: "",
|
|
11
|
+
zip: "",
|
|
12
|
+
isManualAddress: false,
|
|
13
|
+
isMarketingCom: false,
|
|
14
|
+
addressToSend: {},
|
|
15
|
+
notes: "",
|
|
16
|
+
referralCode: "",
|
|
17
|
+
hasUnits: false,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const fiberFormInputList: FiberFormInputList = {
|
|
21
|
+
firstName: { placeholder: "John" },
|
|
22
|
+
lastName: { placeholder: "Doe" },
|
|
23
|
+
address: { placeholder: "Street address" },
|
|
24
|
+
phoneNumber: { placeholder: "Phone number" },
|
|
25
|
+
emailAddress: { placeholder: "Email address" },
|
|
26
|
+
unit: { placeholder: "Unit (optional)" },
|
|
27
|
+
zip: { placeholder: "Zip" },
|
|
28
|
+
notes: { placeholder: "Notes or Comments" },
|
|
29
|
+
referralCode: { placeholder: "Referral Code" },
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const fiberFormAddressCollectionFormSchema = Yup.object({
|
|
33
|
+
firstName: Yup.string()
|
|
34
|
+
.required("First name is required")
|
|
35
|
+
.min(2, "Enter a valid First name")
|
|
36
|
+
.matches(/^[a-zA-Z\s]*$/, "Enter a valid First name"),
|
|
37
|
+
lastName: Yup.string()
|
|
38
|
+
.required("Last name is required")
|
|
39
|
+
.min(2, "Enter a valid Last name")
|
|
40
|
+
.matches(/^[a-zA-Z\s]*$/, "Enter a valid Last name"),
|
|
41
|
+
isManualAddress: Yup.boolean(),
|
|
42
|
+
isMarketingCom: Yup.boolean(),
|
|
43
|
+
hasUnits: Yup.boolean(),
|
|
44
|
+
unit: Yup.string().when("hasUnits", {
|
|
45
|
+
is: true,
|
|
46
|
+
then: schema => schema.required("Unit is required"),
|
|
47
|
+
otherwise: schema =>
|
|
48
|
+
schema.matches(/^[a-zA-Z0-9\s#]*$/, "Enter a valid Unit"),
|
|
49
|
+
}),
|
|
50
|
+
zip: Yup.string().when("isManualAddress", {
|
|
51
|
+
is: true,
|
|
52
|
+
then: schema =>
|
|
53
|
+
schema
|
|
54
|
+
.required("Zip is required")
|
|
55
|
+
.matches(/^\d{5}$/, "Enter a valid Zip"),
|
|
56
|
+
}),
|
|
57
|
+
address: Yup.string()
|
|
58
|
+
.required("Enter your home address (street, city, state, and ZIP below)")
|
|
59
|
+
.when("isManualAddress", {
|
|
60
|
+
is: true,
|
|
61
|
+
then: schema =>
|
|
62
|
+
schema.matches(
|
|
63
|
+
/^(\d{1,}) [a-zA-Z0-9\s]+(\,)? [a-zA-Z\s]+(\,)? [A-Z]{2}( [0-9]{5,6})?$/,
|
|
64
|
+
"Enter your home address (street, city, state, and ZIP below)"
|
|
65
|
+
),
|
|
66
|
+
}),
|
|
67
|
+
phone: Yup.string()
|
|
68
|
+
.required("Phone is required")
|
|
69
|
+
.matches(
|
|
70
|
+
/^\([0-9]{3}\)\s[0-9]{3}-[0-9]{4}$/,
|
|
71
|
+
"Please enter a valid phone number"
|
|
72
|
+
),
|
|
73
|
+
email: Yup.string()
|
|
74
|
+
.email("Invalid email")
|
|
75
|
+
.matches(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, "Invalid email")
|
|
76
|
+
.required("Email is required"),
|
|
77
|
+
notes: Yup.string(),
|
|
78
|
+
referralCode: Yup.string()
|
|
79
|
+
.max(50, "Referral code must not exceed 50 characters")
|
|
80
|
+
.matches(/^\S*$/, "Referral code must not contain spaces"),
|
|
81
|
+
});
|