aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/website/ts/@next/components/modals/input.tsx29
-rw-r--r--packages/website/ts/@next/components/modals/modal_contact.tsx47
2 files changed, 69 insertions, 7 deletions
diff --git a/packages/website/ts/@next/components/modals/input.tsx b/packages/website/ts/@next/components/modals/input.tsx
index 61663d906..d4d9206a2 100644
--- a/packages/website/ts/@next/components/modals/input.tsx
+++ b/packages/website/ts/@next/components/modals/input.tsx
@@ -11,27 +11,37 @@ interface InputProps {
width?: InputWidth;
label: string;
type?: string;
+ errors?: ErrorProps;
+ isErrors?: boolean;
}
interface LabelProps {
string: boolean;
}
+interface ErrorProps {
+ [key: string]: string;
+}
+
export const Input = React.forwardRef((props: InputProps, ref?: React.Ref<HTMLInputElement>) => {
- const { name, label, type } = props;
+ const { name, label, type, errors } = props;
const id = `input-${name}`;
const componentType = type === 'textarea' ? 'textarea' : 'input';
+ const isErrors = errors.hasOwnProperty(name) && errors[name] !== null;
+ const errorMessage = isErrors ? errors[name] : null;
return (
<InputWrapper {...props}>
<Label htmlFor={id}>{label}</Label>
- <StyledInput as={componentType} ref={ref} id={id} placeholder={label} {...props} />
+ <StyledInput as={componentType} ref={ref} id={id} placeholder={label} isErrors={isErrors} {...props} />
+ {isErrors && <Error>{errorMessage}</Error>}
</InputWrapper>
);
});
Input.defaultProps = {
width: InputWidth.Full,
+ errors: {},
};
const StyledInput = styled.input`
@@ -45,6 +55,9 @@ const StyledInput = styled.input`
width: 100%;
min-height: ${props => props.type === 'textarea' && `120px`};
+ background-color: ${(props: InputProps) => props.isErrors && `#FDEDED`};
+ border-color: ${(props: InputProps) => props.isErrors && `#FD0000`};
+
&::placeholder {
color: #C3C3C3;
}
@@ -68,3 +81,15 @@ const Label = styled.label`
margin-bottom: 10px;
display: inline-block;
`;
+
+const Error = styled.span`
+ color: #FD0000;
+ font-size: .833333333rem;
+ line-height: 1em;
+ display: inline-block;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ transform: translateY(24px);
+`;
diff --git a/packages/website/ts/@next/components/modals/modal_contact.tsx b/packages/website/ts/@next/components/modals/modal_contact.tsx
index f107b9174..b595c236d 100644
--- a/packages/website/ts/@next/components/modals/modal_contact.tsx
+++ b/packages/website/ts/@next/components/modals/modal_contact.tsx
@@ -24,6 +24,20 @@ interface FormProps {
isSubmitting?: boolean;
}
+interface ErrorResponseProps {
+ param: string;
+ location: string;
+ msg: string;
+}
+
+interface ErrorResponse {
+ errors: ErrorResponseProps[];
+}
+
+interface ErrorProps {
+ [key: string]: string;
+}
+
export class ModalContact extends React.Component<Props> {
public state = {
isSubmitting: false,
@@ -40,7 +54,7 @@ export class ModalContact extends React.Component<Props> {
}
public render(): React.ReactNode {
const {isOpen, onDismiss} = this.props;
- const {isSuccessful} = this.state;
+ const {isSuccessful, errors} = this.state;
return (
<>
@@ -61,6 +75,7 @@ export class ModalContact extends React.Component<Props> {
width={InputWidth.Half}
ref={this.nameRef}
required={true}
+ errors={errors}
/>
<Input
name="email"
@@ -68,6 +83,7 @@ export class ModalContact extends React.Component<Props> {
type="email"
ref={this.emailRef}
required={true}
+ errors={errors}
width={InputWidth.Half}
/>
</InputRow>
@@ -78,6 +94,7 @@ export class ModalContact extends React.Component<Props> {
type="text"
ref={this.companyProjectRef}
required={true}
+ errors={errors}
/>
</InputRow>
<InputRow>
@@ -86,6 +103,7 @@ export class ModalContact extends React.Component<Props> {
label="Do you have any documentation or a website?"
type="text"
ref={this.linkRef}
+ errors={errors}
/>
</InputRow>
<InputRow>
@@ -94,6 +112,7 @@ export class ModalContact extends React.Component<Props> {
label="Anything else?"
type="textarea"
ref={this.commentsRef}
+ errors={errors}
/>
</InputRow>
<ButtonRow>
@@ -129,24 +148,42 @@ export class ModalContact extends React.Component<Props> {
const link = this.linkRef.current.value;
const comments = this.commentsRef.current.value;
- this.setState({ ...this.state, isSubmitting: true });
+ this.setState({ ...this.state, errors: [], isSubmitting: true });
try {
- await fetch('https://website-api.0x.org/leads', {
+ const response = await fetch('https://website-api.0x.org/leads', {
method: 'post',
mode: 'cors',
credentials: 'same-origin',
headers: {
'content-type': 'application/json; charset=utf-8',
},
- body: JSON.stringify({ name, email, projectOrCompany, link, comments }),
+ body: JSON.stringify(_.omitBy({ name, email, projectOrCompany, link, comments }, _.isEmpty)),
});
+ if (!response.ok) {
+ const errorResponse: ErrorResponse = await response.json();
+ const errors = this._parseErrors(errorResponse.errors);
+ this.setState({ ...this.state, isSubmitting: false, errors });
+
+ throw new Error('Request failed');
+ }
+
this.setState({ ...this.state, isSuccessful: true });
} catch (e) {
- this.setState({ ...this.state, errors: [] });
+ // Empty block
}
}
+ private _parseErrors(errors: ErrorResponseProps[]): ErrorProps {
+ return _
+ .reduce(errors, (hash: ErrorProps, error: ErrorResponseProps) => {
+ const { param, msg } = error;
+ const key = param;
+ hash[key] = msg;
+
+ return hash;
+ }, {});
+ }
}
// Handle errors: {"errors":[{"location":"body","param":"name","msg":"Invalid value"},{"location":"body","param":"email","msg":"Invalid value"}]}