Skip to content

Commit edc326f

Browse files
Merge pull request #291 from CivicActions/contact-form
Contact form Migration
2 parents 64447b5 + fd8df00 commit edc326f

2 files changed

Lines changed: 337 additions & 88 deletions

File tree

src/pages/contact.js

Lines changed: 164 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,198 @@
1-
import '../sass/styles.scss';
2-
import React from 'react';
3-
import RedLayout from '../layouts/red';
4-
import Hero from '../components/hero.js';
5-
import { useHubspotForm } from '@aaronhayes/react-use-hubspot-form';
6-
import emailIcon from '../files/icons/email.png';
7-
import mailIcon from '../files/icons/mail.png';
8-
import phoneIcon from '../files/icons/phone.png';
9-
import SEO from '../components/seo';
1+
import "../sass/styles.scss";
2+
import React, { useState, useEffect } from "react";
3+
import RedLayout from "../layouts/red";
4+
import Hero from "../components/hero.js";
5+
import emailIcon from "../files/icons/email.png";
6+
import mailIcon from "../files/icons/mail.png";
7+
import phoneIcon from "../files/icons/phone.png";
8+
import SEO from "../components/seo";
9+
10+
const WORKER_ENDPOINT =
11+
"https://worker.civicactions.com/api/contact";
12+
13+
const TURNSTILE_SITE_KEY = "0x4AAAAAACbPfzYoEubkjDMX";
1014

1115
const Contact = () => {
12-
const { loaded, error, formCreated } = useHubspotForm({
13-
portalId: '9391823',
14-
formId: '38c64225-614c-4786-876f-12d3174cb330',
15-
target: '#contact-hubspot-form',
16-
});
17-
const fontStyles = {
18-
color: 'white',
19-
};
16+
17+
const [status, setStatus] = useState("idle");
18+
const [errorMsg, setErrorMsg] = useState("");
19+
20+
/*
21+
* LOAD TURNSTILE ONLY ONCE
22+
*/
23+
useEffect(() => {
24+
25+
if (!document.querySelector('script[src*="turnstile"]')) {
26+
const script = document.createElement("script");
27+
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js";
28+
script.async = true;
29+
script.defer = true;
30+
document.body.appendChild(script);
31+
}
32+
33+
}, []);
34+
35+
async function handleSubmit(e) {
36+
e.preventDefault();
37+
38+
setStatus("submitting");
39+
setErrorMsg("");
40+
41+
const token = window.turnstile?.getResponse();
42+
43+
if (!token) {
44+
setStatus("error");
45+
setErrorMsg("Please complete verification.");
46+
return;
47+
}
48+
49+
const formData = new FormData(e.target);
50+
51+
const payload = {
52+
name: formData.get("name"),
53+
email: formData.get("email"),
54+
company: formData.get("organization"),
55+
message: formData.get("message"),
56+
"cf-turnstile-response": token
57+
};
58+
59+
try {
60+
61+
const res = await fetch(WORKER_ENDPOINT, {
62+
method: "POST",
63+
headers: { "Content-Type": "application/json" },
64+
body: JSON.stringify(payload)
65+
});
66+
67+
if (!res.ok) {
68+
throw new Error(await res.text());
69+
}
70+
71+
setStatus("success");
72+
e.target.reset();
73+
window.turnstile?.reset();
74+
75+
} catch (err) {
76+
console.error(err);
77+
setStatus("error");
78+
setErrorMsg("Something went wrong. Please try again.");
79+
}
80+
}
81+
82+
const fontStyles = { color: "white" };
2083

2184
return (
2285
<RedLayout>
86+
2387
<Hero
24-
title='Put us to work'
25-
description='We love solving hard problems. Tell us about your challenge or idea, and we’ll get in touch to discuss a plan of action.'
88+
title="Put us to work"
89+
description="We love solving hard problems. Tell us about your challenge or idea, and we’ll get in touch."
2690
/>
2791

28-
<section className='contact--form'>
29-
<div className='inner'>
30-
<h2 className='visually-hidden'>Contact form by Hubspot</h2>
31-
<div id='contact-hubspot-form'></div>
92+
<section className="contact--form">
93+
<div className="inner">
94+
95+
<h2>Contact Us</h2>
96+
97+
<form onSubmit={handleSubmit} noValidate>
98+
99+
<div className="form-group">
100+
<label htmlFor="name">Name</label>
101+
<input id="name" name="name" type="text" required autoComplete="name"/>
102+
</div>
103+
104+
<div className="form-group">
105+
<label htmlFor="email">Email</label>
106+
<input id="email" name="email" type="email" required autoComplete="email"/>
107+
</div>
108+
109+
<div className="form-group">
110+
<label htmlFor="organization">Organization (optional)</label>
111+
<input id="organization" name="organization" type="text" autoComplete="organization"/>
112+
</div>
113+
114+
<div className="form-group">
115+
<label htmlFor="message">Message</label>
116+
<textarea id="message" name="message" required rows={6}/>
117+
</div>
118+
119+
<div
120+
className="cf-turnstile"
121+
data-sitekey={TURNSTILE_SITE_KEY}
122+
/>
123+
124+
{status === "error" && (
125+
<p role="alert">{errorMsg}</p>
126+
)}
127+
128+
{status === "success" && (
129+
<p role="status">
130+
Thanks — your message has been sent!
131+
</p>
132+
)}
133+
134+
<button
135+
type="submit"
136+
disabled={status === "submitting"}
137+
>
138+
{status === "submitting"
139+
? "Sending..."
140+
: "Send Message"}
141+
</button>
142+
143+
</form>
144+
32145
</div>
33146
</section>
34147

35-
<section className='contact--ways-to-contact--section'>
36-
<div className='inner'>
37-
<h2 className='h3' style={fontStyles}>
148+
<section className="contact--ways-to-contact--section">
149+
<div className="inner">
150+
151+
<h2 className="h3" style={fontStyles}>
38152
More ways to reach us
39153
</h2>
40-
<p className='body' style={fontStyles}>
41-
Feel free to connect with us about work opportunities, speaking
42-
engagements, potential partnerships, or just to say hi.
154+
155+
<p className="body" style={fontStyles}>
156+
Feel free to connect with us about work opportunities,
157+
speaking engagements, partnerships, or just to say hi.
43158
</p>
44-
<div className='contact-grid'>
45-
<div className='grid'>
46-
<img src={emailIcon} alt='email icon'></img>
47-
<p className='label body' style={fontStyles}>
48-
EMAIL
49-
</p>
50-
<a
51-
style={fontStyles}
52-
href='mailto:contact@civicactions.com'
53-
className='link body'>
159+
160+
<div className="contact-grid">
161+
162+
<div className="grid">
163+
<img src={emailIcon} alt="" />
164+
<p className="label body" style={fontStyles}>EMAIL</p>
165+
<a href="mailto:contact@civicactions.com" className="link body" style={fontStyles}>
54166
contact@civicactions.com
55167
</a>
56168
</div>
57-
<div className='grid'>
58-
<img src={mailIcon} alt='mail icon'></img>
59-
<p style={fontStyles} className='label body'>
60-
MAIL
61-
</p>
62-
<a
63-
style={fontStyles}
64-
href='https://www.google.com/maps/place/3527+Mt+Diablo+Blvd+%23269,+Lafayette,+CA+94549,+USA/data=!4m2!3m1!1s0x8085625abdbe2b5d:0x1ab127226da2131c?sa=X&ved=2ahUKEwjvoPTJ7cTwAhVGT6wKHRJAAssQ8gEwAHoECAUQAQ'
65-
className='link body'>
169+
170+
<div className="grid">
171+
<img src={mailIcon} alt="" />
172+
<p className="label body" style={fontStyles}>MAIL</p>
173+
<a href="https://www.google.com/maps/place/3527+Mt+Diablo+Blvd+%23269,+Lafayette,+CA+94549" className="link body" style={fontStyles}>
66174
3527 Mt Diablo Blvd #269 Lafayette, CA 94549
67175
</a>
68176
</div>
69-
<div className='grid'>
70-
<img src={phoneIcon} alt='phone icon'></img>
71-
<p style={fontStyles} className='label body'>
72-
PHONE
73-
</p>
74-
<a
75-
style={fontStyles}
76-
href='tel:510-408-7510'
77-
className='link body'>
177+
178+
<div className="grid">
179+
<img src={phoneIcon} alt="" />
180+
<p className="label body" style={fontStyles}>PHONE</p>
181+
<a href="tel:510-408-7510" className="link body" style={fontStyles}>
78182
(510) 408-7510
79183
</a>
80184
</div>
185+
81186
</div>
82187
</div>
83188
</section>
84189

85-
86190
</RedLayout>
87191
);
88192
};
89193

90194
export default Contact;
91195

92196
export const Head = () => (
93-
<SEO title='Contact' description='Get in touch.' />
94-
);
197+
<SEO title="Contact" description="Get in touch." />
198+
);

0 commit comments

Comments
 (0)