feat(contact): interrupt component with error message

This commit is contained in:
2021-02-03 17:30:29 +00:00
parent f972c61673
commit e91732ad88
4 changed files with 167 additions and 16 deletions

View File

@@ -12,6 +12,7 @@ export { default as Heading } from "./heading";
export { default as Icon } from "./icon";
export { default as IconWithContent } from "./icon-with-content";
export { default as InputText } from "./input-text";
export { default as Interrupt } from "./interrupt";
export { default as Label } from "./label";
export { default as Link } from "./link";
export { default as Map } from "./map";

129
src/components/interrupt.js Normal file
View File

@@ -0,0 +1,129 @@
import React from "react";
import styled from "@emotion/styled";
import { keyframes } from "@emotion/react";
const Keyframes = keyframes`
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
`;
const Container = styled.div`
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 10;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(255, 255, 255, 0.75);
`;
const Spinner = styled.div`
display: inline-block;
position: relative;
width: 80px;
height: 80px;
`;
const Ball = styled.div`
animation: ${Keyframes} 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
transform-origin: 40px 40px;
&:after {
content: "";
display: block;
position: absolute;
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--color-dark);
margin: -4px 0 0 -4px;
}
`;
const BallA = styled(Ball)`
animation-delay: -0.036s;
&:after {
top: 63px;
left: 63px;
}
`;
const BallB = styled(Ball)`
animation-delay: -0.072s;
&:after {
top: 68px;
left: 56px;
}
`;
const BallC = styled(Ball)`
animation-delay: -0.108s;
&:after {
top: 71px;
left: 48px;
}
`;
const BallD = styled(Ball)`
animation-delay: -0.144s;
&:after {
top: 72px;
left: 40px;
}
`;
const BallE = styled(Ball)`
animation-delay: -0.18s;
&:after {
top: 71px;
left: 32px;
}
`;
const BallF = styled(Ball)`
animation-delay: -0.216s;
&:after {
top: 68px;
left: 24px;
}
`;
const BallG = styled(Ball)`
animation-delay: -0.252s;
&:after {
top: 63px;
left: 17px;
}
`;
const BallH = styled(Ball)`
animation-delay: -0.288s;
&:after {
top: 56px;
left: 12px;
}
`;
export default function Interrupt() {
return (
<Container>
<Spinner>
<BallA />
<BallB />
<BallC />
<BallD />
<BallE />
<BallF />
<BallG />
<BallH />
</Spinner>
</Container>
);
}

View File

@@ -24,12 +24,13 @@ const StyledText = styled.p`
css`
color: var(--color-${props.color});
`}
${props =>
props.weight &&
css`
font-weight: ${props.weight};
`}
`;
export default function Text({ children, ...props }) {
return (
<StyledText {...props}>
{children}
</StyledText>
);
return <StyledText {...props}>{children}</StyledText>;
}

View File

@@ -11,6 +11,7 @@ import {
Icon,
IconWithContent,
InputText,
Interrupt,
Label,
Link,
Map,
@@ -32,7 +33,7 @@ const encode = data => {
};
export default function Index({ data }) {
const [submitted, setSubmitted] = useState();
const [formState, setFormState] = useState();
const [uploadFiles, setUploadFiles] = useState();
const [files, setFiles] = useState({});
@@ -43,6 +44,7 @@ export default function Index({ data }) {
const handleSubmit = e => {
e.preventDefault();
setFormState("submitting");
const body = encode({
"form-name": "contact",
name: e.target.name.value,
@@ -55,16 +57,15 @@ export default function Index({ data }) {
message: e.target.message.value,
files
});
fetch("/contact", { method: "POST", body })
.then(res => {
if (res.status !== 200) {
console.log("error", res);
setFormState("error");
} else {
setSubmitted(true);
setFormState("success");
}
})
.catch(error => console.log(error));
.catch(() => setFormState("error"));
};
return (
<Layout location="/contact" title="Contact us">
@@ -151,8 +152,8 @@ export default function Index({ data }) {
</Link>
</IconWithContent>
</div>
<div>
{submitted ? (
<div style={{ position: "relative" }}>
{formState === "success" && (
<IconWithContent>
<Icon color="dark" size="lg">
<CheckCircle />
@@ -166,8 +167,10 @@ export default function Index({ data }) {
</Text>
</>
</IconWithContent>
) : (
)}
{formState !== "success" && (
<>
{formState === "submitting" && <Interrupt />}
<IconWithContent>
<Icon color="dark" size="lg">
<Envelope />
@@ -176,11 +179,26 @@ export default function Index({ data }) {
Contact us
</Text>
</IconWithContent>
{formState === "error" && (
<>
<Text size="lg" color="primary" weight="bold">
There was an error submitting the form, please try again
later.
</Text>
<Text color="primary">
Alternatively, please feel free to email us at{" "}
<Link to="mailto:quotations@abcprojectdesign.com">
quotations@abcprojectdesign.com
</Link>
.
</Text>
</>
)}
<form
name="contact"
method="POST"
action="/contact"
onSubmit={handleSubmit}
onSubmit={e => handleSubmit(e, scroll)}
data-netlify="true"
data-netlify-honeypot="bot-field"
>
@@ -261,7 +279,9 @@ export default function Index({ data }) {
</Label>
<InputText id="contact-message" name="message" textArea />
<Button
style={{ display: uploadFiles ? "none" : "inline-block" }}
style={{
display: uploadFiles ? "none" : "inline-block"
}}
onClick={handleUploadClick}
>
Upload images
@@ -273,7 +293,7 @@ export default function Index({ data }) {
setFiles={setFiles}
/>
<Button type="submit" float="right">
Submit
{formState === "submitting" ? "Submitting..." : "Submit"}
</Button>
</form>
</>