Skip to content

Commit 3f929b0

Browse files
Larissa Whitney CoxLarissa Whitney Cox
authored andcommitted
Merge Power Automate form integration
2 parents 995071d + cd28758 commit 3f929b0

5 files changed

Lines changed: 146 additions & 12 deletions

File tree

public/scripts/contact-form.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
(function () {
2+
const endpoint =
3+
'https://defaultb5687cc343ce40ed91fd6a67198489.81.environment.api.powerplatform.com:443/powerautomate/automations/direct/workflows/67f7bf7e639044d8a78de32f1691dfa1/triggers/manual/paths/invoke?api-version=1&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=U8kmHBuwfedGCM7VufLr_6FtbDcgLhgwSTbeE26hdQs';
4+
5+
const forms = document.querySelectorAll('[data-contact-form]');
6+
7+
if (!forms.length) {
8+
return;
9+
}
10+
11+
const setStatus = (form, message, state) => {
12+
const status = form.querySelector('[data-contact-status]');
13+
14+
if (!status) {
15+
return;
16+
}
17+
18+
status.textContent = message;
19+
status.dataset.state = state;
20+
};
21+
22+
const getValue = (formData, key) => String(formData.get(key) || '').trim();
23+
24+
forms.forEach((form) => {
25+
form.addEventListener('submit', async (event) => {
26+
event.preventDefault();
27+
28+
if (!form.reportValidity()) {
29+
return;
30+
}
31+
32+
const formData = new FormData(form);
33+
const honeypot = getValue(formData, 'company');
34+
35+
if (honeypot) {
36+
form.reset();
37+
setStatus(form, 'Thanks, your message has been sent.', 'success');
38+
return;
39+
}
40+
41+
const submitButton = form.querySelector('button[type="submit"]');
42+
const originalButtonText = submitButton ? submitButton.textContent : '';
43+
const payload = {
44+
firstName: getValue(formData, 'firstName'),
45+
lastName: getValue(formData, 'lastName'),
46+
email: getValue(formData, 'email'),
47+
message: getValue(formData, 'message'),
48+
sourcePage: window.location.href,
49+
formSource: form.dataset.formSource || 'Website',
50+
siteName: 'collabor8 Architecture + Design (BC)',
51+
submittedAt: new Date().toISOString(),
52+
};
53+
54+
setStatus(form, 'Sending...', 'pending');
55+
56+
if (submitButton) {
57+
submitButton.disabled = true;
58+
submitButton.textContent = 'Sending';
59+
}
60+
61+
try {
62+
const response = await fetch(endpoint, {
63+
method: 'POST',
64+
headers: {
65+
'Content-Type': 'application/json',
66+
},
67+
body: JSON.stringify(payload),
68+
});
69+
70+
if (!response.ok) {
71+
throw new Error(`Power Automate returned ${response.status}`);
72+
}
73+
74+
form.reset();
75+
setStatus(form, 'Thanks, your message has been sent.', 'success');
76+
} catch (error) {
77+
console.error('Contact form submission failed:', error);
78+
setStatus(
79+
form,
80+
'Sorry, something went wrong. Please email info@c8bc.ca directly.',
81+
'error',
82+
);
83+
} finally {
84+
if (submitButton) {
85+
submitButton.disabled = false;
86+
submitButton.textContent = originalButtonText || 'Submit';
87+
}
88+
}
89+
});
90+
});
91+
})();

src/components/ContactSplitSection.astro

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,29 @@ const { id = 'how-to-connect' } = Astro.props;
1515
</h2>
1616
</div>
1717

18-
<form class="contact-form">
18+
<form class="contact-form" data-contact-form data-form-source="Recent Projects">
1919
<label>
2020
<span>First Name*</span>
21-
<input type="text" name="first-name" placeholder="First Name*" />
21+
<input type="text" name="firstName" placeholder="First Name*" autocomplete="given-name" required />
2222
</label>
2323
<label>
2424
<span>Last Name</span>
25-
<input type="text" name="last-name" placeholder="Last Name" />
25+
<input type="text" name="lastName" placeholder="Last Name" autocomplete="family-name" />
2626
</label>
2727
<label class="contact-form__full">
2828
<span>Email*</span>
29-
<input type="email" name="email" placeholder="Email*" />
29+
<input type="email" name="email" placeholder="Email*" autocomplete="email" required />
3030
</label>
3131
<label class="contact-form__full contact-form__message">
3232
<span>Message*</span>
33-
<textarea name="message" placeholder="Message*"></textarea>
33+
<textarea name="message" placeholder="Message*" required></textarea>
3434
</label>
35-
<button type="button">Submit</button>
35+
<label class="contact-form__honeypot" aria-hidden="true" tabindex="-1">
36+
<span>Company</span>
37+
<input type="text" name="company" autocomplete="off" tabindex="-1" />
38+
</label>
39+
<button type="submit">Submit</button>
40+
<p class="contact-form__status" data-contact-status aria-live="polite"></p>
3641
</form>
3742
</div>
3843
</div>

src/layouts/Layout.astro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@ const base = import.meta.env.BASE_URL.endsWith('/')
3030
</head>
3131
<body class="site-shell">
3232
<slot />
33+
<script src={`${base}scripts/contact-form.js`} defer></script>
3334
</body>
3435
</html>

src/pages/index.astro

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -316,24 +316,29 @@ const leadership = [
316316
</h2>
317317
</div>
318318

319-
<form class="contact-form">
319+
<form class="contact-form" data-contact-form data-form-source="Homepage">
320320
<label>
321321
<span>First Name*</span>
322-
<input type="text" name="first-name" placeholder="First Name*" />
322+
<input type="text" name="firstName" placeholder="First Name*" autocomplete="given-name" required />
323323
</label>
324324
<label>
325325
<span>Last Name</span>
326-
<input type="text" name="last-name" placeholder="Last Name" />
326+
<input type="text" name="lastName" placeholder="Last Name" autocomplete="family-name" />
327327
</label>
328328
<label class="contact-form__full">
329329
<span>Email*</span>
330-
<input type="email" name="email" placeholder="Email*" />
330+
<input type="email" name="email" placeholder="Email*" autocomplete="email" required />
331331
</label>
332332
<label class="contact-form__full contact-form__message">
333333
<span>Message*</span>
334-
<textarea name="message" placeholder="Message*"></textarea>
334+
<textarea name="message" placeholder="Message*" required></textarea>
335335
</label>
336-
<button type="button">Submit</button>
336+
<label class="contact-form__honeypot" aria-hidden="true" tabindex="-1">
337+
<span>Company</span>
338+
<input type="text" name="company" autocomplete="off" tabindex="-1" />
339+
</label>
340+
<button type="submit">Submit</button>
341+
<p class="contact-form__status" data-contact-status aria-live="polite"></p>
337342
</form>
338343
</div>
339344
</div>

src/styles/global.css

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,14 @@ nav {
913913
grid-column: 1 / -1;
914914
}
915915

916+
.contact-form__honeypot {
917+
position: absolute;
918+
left: -9999px;
919+
width: 1px;
920+
height: 1px;
921+
overflow: hidden;
922+
}
923+
916924
.contact-form button {
917925
grid-column: 1 / -1;
918926
justify-self: center;
@@ -927,10 +935,34 @@ nav {
927935
cursor: pointer;
928936
}
929937

938+
.contact-form button:disabled {
939+
cursor: wait;
940+
opacity: 0.72;
941+
}
942+
930943
.contact-form button:hover {
931944
background: var(--brand-orange);
932945
}
933946

947+
.contact-form__status {
948+
grid-column: 1 / -1;
949+
justify-self: center;
950+
margin: 0;
951+
min-height: 1.2em;
952+
color: var(--color-muted);
953+
font-size: 0.84rem;
954+
line-height: 1.35;
955+
text-align: center;
956+
}
957+
958+
.contact-form__status[data-state="success"] {
959+
color: var(--brand-orange);
960+
}
961+
962+
.contact-form__status[data-state="error"] {
963+
color: #9d2e1c;
964+
}
965+
934966
.section-link {
935967
display: inline-flex;
936968
align-items: center;

0 commit comments

Comments
 (0)