aboutsummaryrefslogtreecommitdiff
path: root/src/routes/contact/+page.svelte
diff options
context:
space:
mode:
authorElizabeth Hunt <me@liz.coffee>2026-01-01 18:32:49 -0800
committerElizabeth Hunt <me@liz.coffee>2026-01-01 18:32:49 -0800
commit9af1854a7e35785a8e86426c4fb1edd465f164a3 (patch)
tree8a070c6a9498d952c9ef4ba045f2ebfb25f7b335 /src/routes/contact/+page.svelte
parent0248a3899ed910f005dccaeefc1d9dcb893e8154 (diff)
downloadmistymountainstherapy-9af1854a7e35785a8e86426c4fb1edd465f164a3.tar.gz
mistymountainstherapy-9af1854a7e35785a8e86426c4fb1edd465f164a3.zip
Massive refactor courtesy of 5 dollars of AI tokens
Diffstat (limited to 'src/routes/contact/+page.svelte')
-rw-r--r--src/routes/contact/+page.svelte325
1 files changed, 325 insertions, 0 deletions
diff --git a/src/routes/contact/+page.svelte b/src/routes/contact/+page.svelte
new file mode 100644
index 0000000..c66d9df
--- /dev/null
+++ b/src/routes/contact/+page.svelte
@@ -0,0 +1,325 @@
+<script>
+ import { browser } from '$app/environment';
+ import HCaptcha from 'svelte-hcaptcha';
+
+ const mapsUrl = 'https://maps.app.goo.gl/s1AFqfKvUKgXDCrq5';
+
+ let submission = {
+ name: '',
+ email: '',
+ message: '',
+ phone: '',
+ captchaToken: ''
+ };
+
+ let captcha;
+ let noticeType = 'info';
+ let noticeMessage = '';
+
+ function setNotice(type, message) {
+ noticeType = type;
+ noticeMessage = message;
+ }
+
+ function handleSubmit(e) {
+ e.preventDefault();
+
+ if (!browser) return;
+ if (!submission.captchaToken) {
+ setNotice('error', 'Please complete the captcha first.');
+ return;
+ }
+
+ setNotice('info', 'Sending...');
+ fetch('/contact/submit', {
+ method: 'POST',
+ body: JSON.stringify(submission)
+ })
+ .then((x) => x.json())
+ .then((x) => {
+ if (x.success) {
+ setNotice('success', 'Success! Reloading...');
+ setTimeout(() => window.location.reload(), 1000);
+ } else {
+ setNotice('error', x.error ?? 'Something went wrong. Please try again.');
+ }
+ })
+ .catch((err) => {
+ console.log(err);
+ setNotice('error', 'Network error. Please try again.');
+ });
+ }
+
+ function onCaptchaError() {
+ setNotice('error', 'Failed to verify captcha, try again.');
+ captcha?.reset();
+ submission.captchaToken = '';
+ }
+
+ function onCaptchaSuccess({ detail: { token } }) {
+ submission.captchaToken = token;
+ }
+</script>
+
+<div class="contact">
+ <header class="contact__header">
+ <h1>Contact</h1>
+ </header>
+
+ {#if noticeMessage}
+ <div
+ class={'notice notice--' + noticeType}
+ role={noticeType === 'error' ? 'alert' : 'status'}
+ aria-live={noticeType === 'error' ? 'assertive' : 'polite'}
+ >
+ {noticeMessage}
+ </div>
+ {/if}
+
+ <div class="contact__grid">
+ <div class="contact__sidebar">
+ <section class="card" aria-label="Contact details">
+ <h2>Details</h2>
+
+ <div class="contact__methods">
+ <a class="contact__method" href={mapsUrl} target="_blank" rel="noopener noreferrer">
+ <span class="contact__icon" aria-hidden="true"><i class="bi bi-pin-map"></i></span>
+ <span class="contact__methodBody">
+ <span class="contact__methodTitle">Office</span>
+ <span class="contact__methodText">
+ 534 Trejo Street, Suite 200F<br />Rexburg, ID 83440
+ </span>
+ </span>
+ </a>
+
+ <a class="contact__method" href="tel:12084994517">
+ <span class="contact__icon" aria-hidden="true"><i class="bi bi-telephone"></i></span>
+ <span class="contact__methodBody">
+ <span class="contact__methodTitle">Phone</span>
+ <span class="contact__methodText">(208) 499 - 4517</span>
+ </span>
+ </a>
+
+ <a class="contact__method" href="mailto:contact@mistymountainstherapy.com">
+ <span class="contact__icon" aria-hidden="true"><i class="bi bi-envelope"></i></span>
+ <span class="contact__methodBody">
+ <span class="contact__methodTitle">Email</span>
+ <span class="contact__methodText">contact@mistymountainstherapy.com</span>
+ </span>
+ </a>
+ </div>
+ </section>
+
+ <section class="card card--warn" aria-label="Crisis resources">
+ <h2>In a crisis?</h2>
+ <p style="margin: 0">
+ We do not have a crisis line. If you or someone you know is in danger please call 911, visit your
+ nearest emergency room, call the National Suicide Prevention Lifeline at
+ <a href="tel:18002738255">(800)273-TALK</a> (8255), or text HELLO to 741-741.
+ </p>
+ </section>
+ </div>
+
+ <section class="card" aria-label="Send a message">
+ <h2>Send a message</h2>
+ <form class="contact__form" on:submit|preventDefault={handleSubmit}>
+ <div class="contact__fields">
+ <label class="field">
+ <span class="field__label">Email *</span>
+ <input
+ type="email"
+ class="form-control"
+ bind:value={submission.email}
+ placeholder="johnnyappleseed@example.com"
+ required
+ />
+ </label>
+
+ <label class="field">
+ <span class="field__label">Name *</span>
+ <input
+ type="text"
+ class="form-control"
+ bind:value={submission.name}
+ placeholder="Johnny Appleseed"
+ required
+ />
+ </label>
+
+ <label class="field">
+ <span class="field__label">Phone</span>
+ <input
+ type="text"
+ class="form-control"
+ bind:value={submission.phone}
+ placeholder="(208) 123-4567"
+ />
+ </label>
+
+ <label class="field">
+ <span class="field__label">Message *</span>
+ <textarea
+ class="form-control"
+ bind:value={submission.message}
+ rows="6"
+ placeholder="Hello! I would like to schedule a free 15-minute consultation..."
+ required
+ ></textarea>
+ </label>
+ </div>
+
+ <div class="contact__captcha">
+ <HCaptcha
+ sitekey={import.meta.env.VITE_HCAPTCHA_KEY}
+ bind:this={captcha}
+ on:success={onCaptchaSuccess}
+ on:error={onCaptchaError}
+ />
+ </div>
+
+ <div class="contact__actions">
+ <button type="submit" class="button button--primary" disabled={!submission.captchaToken}>
+ Submit
+ </button>
+ <p class="text-muted" style="margin: 0">
+ Please watch spam for replies.
+ </p>
+ </div>
+ </form>
+ </section>
+ </div>
+</div>
+
+<style>
+ .contact {
+ display: grid;
+ gap: var(--space-5);
+ }
+
+ .contact__header {
+ display: grid;
+ gap: var(--space-2);
+ }
+
+ .contact__lede {
+ margin: 0;
+ color: var(--color-muted);
+ }
+
+ .contact__grid {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: var(--space-5);
+ align-items: start;
+ }
+
+ @media (min-width: 900px) {
+ .contact__grid {
+ grid-template-columns: 1fr minmax(0, 320px);
+ }
+
+ .contact__sidebar {
+ order: 2;
+ }
+ }
+
+ .contact__sidebar {
+ display: grid;
+ gap: var(--space-5);
+ min-width: 0;
+ }
+
+ .contact__methods {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: var(--space-3);
+ }
+
+ .contact__method {
+ display: grid;
+ grid-template-columns: 2.25rem 1fr;
+ gap: var(--space-3);
+ align-items: start;
+ padding: var(--space-3);
+ border-radius: var(--radius-sm);
+ border: 1px solid var(--color-border);
+ text-decoration: none;
+ background: rgba(255, 255, 255, 0.55);
+ }
+
+ .contact__method:hover {
+ border-color: var(--color-accent);
+ }
+
+ .contact__icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 2.25rem;
+ height: 2.25rem;
+ border-radius: 999px;
+ background: color-mix(in srgb, var(--color-accent) 10%, transparent);
+ color: var(--color-accent-strong);
+ }
+
+ .contact__icon i {
+ font-size: 1.1rem;
+ }
+
+ .contact__methodBody {
+ display: grid;
+ gap: 0.15rem;
+ }
+
+ .contact__methodTitle {
+ font-weight: 700;
+ }
+
+ .contact__methodText {
+ color: var(--color-muted);
+ line-height: 1.35;
+ word-break: break-word;
+ }
+
+ .contact__form {
+ display: grid;
+ gap: var(--space-4);
+ }
+
+ .contact__fields {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: var(--space-3);
+ }
+
+ @media (min-width: 700px) {
+ .contact__fields {
+ grid-template-columns: 1fr;
+ }
+
+ .field--full {
+ grid-column: 1 / -1;
+ }
+ }
+
+ .field {
+ display: grid;
+ gap: var(--space-2);
+ }
+
+ .field__label {
+ font-weight: 650;
+ }
+
+ .contact__captcha {
+ display: grid;
+ justify-content: start;
+ }
+
+ .contact__actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--space-3);
+ align-items: center;
+ }
+</style>