feat(contact): interrupt component with error message
This commit is contained in:
@@ -12,6 +12,7 @@ export { default as Heading } from "./heading";
|
|||||||
export { default as Icon } from "./icon";
|
export { default as Icon } from "./icon";
|
||||||
export { default as IconWithContent } from "./icon-with-content";
|
export { default as IconWithContent } from "./icon-with-content";
|
||||||
export { default as InputText } from "./input-text";
|
export { default as InputText } from "./input-text";
|
||||||
|
export { default as Interrupt } from "./interrupt";
|
||||||
export { default as Label } from "./label";
|
export { default as Label } from "./label";
|
||||||
export { default as Link } from "./link";
|
export { default as Link } from "./link";
|
||||||
export { default as Map } from "./map";
|
export { default as Map } from "./map";
|
||||||
|
|||||||
129
src/components/interrupt.js
Normal file
129
src/components/interrupt.js
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -24,12 +24,13 @@ const StyledText = styled.p`
|
|||||||
css`
|
css`
|
||||||
color: var(--color-${props.color});
|
color: var(--color-${props.color});
|
||||||
`}
|
`}
|
||||||
|
${props =>
|
||||||
|
props.weight &&
|
||||||
|
css`
|
||||||
|
font-weight: ${props.weight};
|
||||||
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default function Text({ children, ...props }) {
|
export default function Text({ children, ...props }) {
|
||||||
return (
|
return <StyledText {...props}>{children}</StyledText>;
|
||||||
<StyledText {...props}>
|
|
||||||
{children}
|
|
||||||
</StyledText>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
Icon,
|
Icon,
|
||||||
IconWithContent,
|
IconWithContent,
|
||||||
InputText,
|
InputText,
|
||||||
|
Interrupt,
|
||||||
Label,
|
Label,
|
||||||
Link,
|
Link,
|
||||||
Map,
|
Map,
|
||||||
@@ -32,7 +33,7 @@ const encode = data => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function Index({ data }) {
|
export default function Index({ data }) {
|
||||||
const [submitted, setSubmitted] = useState();
|
const [formState, setFormState] = useState();
|
||||||
const [uploadFiles, setUploadFiles] = useState();
|
const [uploadFiles, setUploadFiles] = useState();
|
||||||
const [files, setFiles] = useState({});
|
const [files, setFiles] = useState({});
|
||||||
|
|
||||||
@@ -43,6 +44,7 @@ export default function Index({ data }) {
|
|||||||
|
|
||||||
const handleSubmit = e => {
|
const handleSubmit = e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
setFormState("submitting");
|
||||||
const body = encode({
|
const body = encode({
|
||||||
"form-name": "contact",
|
"form-name": "contact",
|
||||||
name: e.target.name.value,
|
name: e.target.name.value,
|
||||||
@@ -55,16 +57,15 @@ export default function Index({ data }) {
|
|||||||
message: e.target.message.value,
|
message: e.target.message.value,
|
||||||
files
|
files
|
||||||
});
|
});
|
||||||
|
|
||||||
fetch("/contact", { method: "POST", body })
|
fetch("/contact", { method: "POST", body })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.status !== 200) {
|
if (res.status !== 200) {
|
||||||
console.log("error", res);
|
setFormState("error");
|
||||||
} else {
|
} else {
|
||||||
setSubmitted(true);
|
setFormState("success");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => console.log(error));
|
.catch(() => setFormState("error"));
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Layout location="/contact" title="Contact us">
|
<Layout location="/contact" title="Contact us">
|
||||||
@@ -151,8 +152,8 @@ export default function Index({ data }) {
|
|||||||
</Link>
|
</Link>
|
||||||
</IconWithContent>
|
</IconWithContent>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div style={{ position: "relative" }}>
|
||||||
{submitted ? (
|
{formState === "success" && (
|
||||||
<IconWithContent>
|
<IconWithContent>
|
||||||
<Icon color="dark" size="lg">
|
<Icon color="dark" size="lg">
|
||||||
<CheckCircle />
|
<CheckCircle />
|
||||||
@@ -166,8 +167,10 @@ export default function Index({ data }) {
|
|||||||
</Text>
|
</Text>
|
||||||
</>
|
</>
|
||||||
</IconWithContent>
|
</IconWithContent>
|
||||||
) : (
|
)}
|
||||||
|
{formState !== "success" && (
|
||||||
<>
|
<>
|
||||||
|
{formState === "submitting" && <Interrupt />}
|
||||||
<IconWithContent>
|
<IconWithContent>
|
||||||
<Icon color="dark" size="lg">
|
<Icon color="dark" size="lg">
|
||||||
<Envelope />
|
<Envelope />
|
||||||
@@ -176,11 +179,26 @@ export default function Index({ data }) {
|
|||||||
Contact us
|
Contact us
|
||||||
</Text>
|
</Text>
|
||||||
</IconWithContent>
|
</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
|
<form
|
||||||
name="contact"
|
name="contact"
|
||||||
method="POST"
|
method="POST"
|
||||||
action="/contact"
|
action="/contact"
|
||||||
onSubmit={handleSubmit}
|
onSubmit={e => handleSubmit(e, scroll)}
|
||||||
data-netlify="true"
|
data-netlify="true"
|
||||||
data-netlify-honeypot="bot-field"
|
data-netlify-honeypot="bot-field"
|
||||||
>
|
>
|
||||||
@@ -261,7 +279,9 @@ export default function Index({ data }) {
|
|||||||
</Label>
|
</Label>
|
||||||
<InputText id="contact-message" name="message" textArea />
|
<InputText id="contact-message" name="message" textArea />
|
||||||
<Button
|
<Button
|
||||||
style={{ display: uploadFiles ? "none" : "inline-block" }}
|
style={{
|
||||||
|
display: uploadFiles ? "none" : "inline-block"
|
||||||
|
}}
|
||||||
onClick={handleUploadClick}
|
onClick={handleUploadClick}
|
||||||
>
|
>
|
||||||
Upload images
|
Upload images
|
||||||
@@ -273,7 +293,7 @@ export default function Index({ data }) {
|
|||||||
setFiles={setFiles}
|
setFiles={setFiles}
|
||||||
/>
|
/>
|
||||||
<Button type="submit" float="right">
|
<Button type="submit" float="right">
|
||||||
Submit
|
{formState === "submitting" ? "Submitting..." : "Submit"}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
</>
|
</>
|
||||||
|
|||||||
Reference in New Issue
Block a user