diff --git a/package-lock.json b/package-lock.json index 7159765..15c7abe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,17 @@ "name": "mistymountains-frontend", "version": "0.0.1", "dependencies": { - "@supabase/supabase-js": "^1.33.3" + "@sendgrid/mail": "^7.6.2", + "@supabase/supabase-js": "^1.33.3", + "dotenv": "^16.0.0" }, "devDependencies": { "@sveltejs/adapter-auto": "next", + "@sveltejs/adapter-node": "^1.0.0-next.73", "@sveltejs/kit": "next", "@typescript-eslint/eslint-plugin": "^5.10.1", "@typescript-eslint/parser": "^5.10.1", + "@zerodevx/svelte-toast": "^0.7.1", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-svelte3": "^3.2.1", @@ -22,6 +26,7 @@ "prettier-plugin-svelte": "^2.5.0", "svelte": "^3.44.0", "svelte-check": "^2.2.6", + "svelte-hcaptcha": "^0.1.1", "svelte-preprocess": "^4.10.1", "tslib": "^2.3.1", "typescript": "~4.6.2" @@ -233,6 +238,41 @@ "node": ">= 8.0.0" } }, + "node_modules/@sendgrid/client": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-7.6.2.tgz", + "integrity": "sha512-Yw3i3vPBBwfiIi+4i7+1f1rwQoLlLsu3qW16d1UuRp6RgX6H6yHYb2/PfqwNyCC0qzqIWGUKPWwYe5ggcr5Guw==", + "dependencies": { + "@sendgrid/helpers": "^7.6.2", + "axios": "^0.26.0" + }, + "engines": { + "node": "6.* || 8.* || >=10.*" + } + }, + "node_modules/@sendgrid/helpers": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-7.6.2.tgz", + "integrity": "sha512-kGW0kM2AOHfXjcvB6Lgwa/nMv8IALu0KyNY9X4HSa3MtLohymuhbG9HgjrOh66+BkbsfA03H3bcT0+sPVJ0GKQ==", + "dependencies": { + "deepmerge": "^4.2.2" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@sendgrid/mail": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-7.6.2.tgz", + "integrity": "sha512-IHHZFvgU95aqb11AevQvAfautj2pb8iW8UCiUJ2ae9pRF37e6EkBmU9NgdFjbQ/8Xhhm+KDVDzn/JLxDN/GiBw==", + "dependencies": { + "@sendgrid/client": "^7.6.2", + "@sendgrid/helpers": "^7.6.2" + }, + "engines": { + "node": "6.* || 8.* || >=10.*" + } + }, "node_modules/@supabase/functions-js": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-1.3.3.tgz", @@ -318,6 +358,15 @@ "tiny-glob": "^0.2.9" } }, + "node_modules/@sveltejs/adapter-node": { + "version": "1.0.0-next.73", + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.73.tgz", + "integrity": "sha512-eidd7u1dPHIaBKMjRePrxazUt+Mm/JpnaiKLzZJBdamhBiiYIb+epkPLLqfG5Oo346/0HLKwFRAM/FXn3u3BHQ==", + "dev": true, + "dependencies": { + "tiny-glob": "^0.2.9" + } + }, "node_modules/@sveltejs/adapter-vercel": { "version": "1.0.0-next.47", "resolved": "https://registry.npmjs.org/@sveltejs/adapter-vercel/-/adapter-vercel-1.0.0-next.47.tgz", @@ -589,6 +638,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@zerodevx/svelte-toast": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@zerodevx/svelte-toast/-/svelte-toast-0.7.1.tgz", + "integrity": "sha512-JxyjPlpc3IzwyHLGbU5pDPW68HM1o7FjiSWmm9SIig7NuuBFIqoJkVt9CYr6toAXzi5sLBgu27hT1NntKbKcmA==", + "dev": true + }, "node_modules/acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -699,6 +754,14 @@ "node": ">=8" } }, + "node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -887,6 +950,14 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/detect-indent": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", @@ -920,6 +991,14 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", + "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==", + "engines": { + "node": ">=12" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -1718,6 +1797,25 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2776,6 +2874,12 @@ "svelte": "^3.24.0" } }, + "node_modules/svelte-hcaptcha": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/svelte-hcaptcha/-/svelte-hcaptcha-0.1.1.tgz", + "integrity": "sha512-iFF3HwfrCRciJnDs4Y9/rpP/BM2U/5zt+vh+9d4tALPAHVkcANiJIKqYuS835pIaTm6gt+xOzjfFI3cgiRI29A==", + "dev": true + }, "node_modules/svelte-hmr": { "version": "0.14.11", "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.11.tgz", @@ -3339,6 +3443,32 @@ "picomatch": "^2.2.2" } }, + "@sendgrid/client": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-7.6.2.tgz", + "integrity": "sha512-Yw3i3vPBBwfiIi+4i7+1f1rwQoLlLsu3qW16d1UuRp6RgX6H6yHYb2/PfqwNyCC0qzqIWGUKPWwYe5ggcr5Guw==", + "requires": { + "@sendgrid/helpers": "^7.6.2", + "axios": "^0.26.0" + } + }, + "@sendgrid/helpers": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-7.6.2.tgz", + "integrity": "sha512-kGW0kM2AOHfXjcvB6Lgwa/nMv8IALu0KyNY9X4HSa3MtLohymuhbG9HgjrOh66+BkbsfA03H3bcT0+sPVJ0GKQ==", + "requires": { + "deepmerge": "^4.2.2" + } + }, + "@sendgrid/mail": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-7.6.2.tgz", + "integrity": "sha512-IHHZFvgU95aqb11AevQvAfautj2pb8iW8UCiUJ2ae9pRF37e6EkBmU9NgdFjbQ/8Xhhm+KDVDzn/JLxDN/GiBw==", + "requires": { + "@sendgrid/client": "^7.6.2", + "@sendgrid/helpers": "^7.6.2" + } + }, "@supabase/functions-js": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-1.3.3.tgz", @@ -3424,6 +3554,15 @@ "tiny-glob": "^0.2.9" } }, + "@sveltejs/adapter-node": { + "version": "1.0.0-next.73", + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.73.tgz", + "integrity": "sha512-eidd7u1dPHIaBKMjRePrxazUt+Mm/JpnaiKLzZJBdamhBiiYIb+epkPLLqfG5Oo346/0HLKwFRAM/FXn3u3BHQ==", + "dev": true, + "requires": { + "tiny-glob": "^0.2.9" + } + }, "@sveltejs/adapter-vercel": { "version": "1.0.0-next.47", "resolved": "https://registry.npmjs.org/@sveltejs/adapter-vercel/-/adapter-vercel-1.0.0-next.47.tgz", @@ -3584,6 +3723,12 @@ "eslint-visitor-keys": "^3.0.0" } }, + "@zerodevx/svelte-toast": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@zerodevx/svelte-toast/-/svelte-toast-0.7.1.tgz", + "integrity": "sha512-JxyjPlpc3IzwyHLGbU5pDPW68HM1o7FjiSWmm9SIig7NuuBFIqoJkVt9CYr6toAXzi5sLBgu27hT1NntKbKcmA==", + "dev": true + }, "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -3661,6 +3806,14 @@ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3802,6 +3955,11 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + }, "detect-indent": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", @@ -3826,6 +3984,11 @@ "esutils": "^2.0.2" } }, + "dotenv": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", + "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==" + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -4342,6 +4505,11 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5085,6 +5253,12 @@ "typescript": "*" } }, + "svelte-hcaptcha": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/svelte-hcaptcha/-/svelte-hcaptcha-0.1.1.tgz", + "integrity": "sha512-iFF3HwfrCRciJnDs4Y9/rpP/BM2U/5zt+vh+9d4tALPAHVkcANiJIKqYuS835pIaTm6gt+xOzjfFI3cgiRI29A==", + "dev": true + }, "svelte-hmr": { "version": "0.14.11", "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.11.tgz", diff --git a/package.json b/package.json index 52aa431..6bb3453 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,11 @@ }, "devDependencies": { "@sveltejs/adapter-auto": "next", + "@sveltejs/adapter-node": "^1.0.0-next.73", "@sveltejs/kit": "next", "@typescript-eslint/eslint-plugin": "^5.10.1", "@typescript-eslint/parser": "^5.10.1", + "@zerodevx/svelte-toast": "^0.7.1", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-svelte3": "^3.2.1", @@ -24,12 +26,15 @@ "prettier-plugin-svelte": "^2.5.0", "svelte": "^3.44.0", "svelte-check": "^2.2.6", + "svelte-hcaptcha": "^0.1.1", "svelte-preprocess": "^4.10.1", "tslib": "^2.3.1", "typescript": "~4.6.2" }, "type": "module", "dependencies": { - "@supabase/supabase-js": "^1.33.3" + "@sendgrid/mail": "^7.6.2", + "@supabase/supabase-js": "^1.33.3", + "dotenv": "^16.0.0" } } diff --git a/src/components/DirectionCard.svelte b/src/components/DirectionCard.svelte index 39d2260..71c9aba 100644 --- a/src/components/DirectionCard.svelte +++ b/src/components/DirectionCard.svelte @@ -24,9 +24,3 @@ {/if} - - diff --git a/src/components/Footer.svelte b/src/components/Footer.svelte index f99dc43..e6a829e 100644 --- a/src/components/Footer.svelte +++ b/src/components/Footer.svelte @@ -7,7 +7,7 @@
- (530) 638 - 3546 (call or text) + (530) 638 - 3546
diff --git a/src/routes/__layout.svelte b/src/routes/__layout.svelte index aa8d8d8..ccb2fd5 100644 --- a/src/routes/__layout.svelte +++ b/src/routes/__layout.svelte @@ -2,8 +2,10 @@ import NavBar from '../components/NavBar.svelte'; import Footer from '../components/Footer.svelte'; import '../app.css'; + import { SvelteToast } from '@zerodevx/svelte-toast'; +
diff --git a/src/routes/approach/index.svelte b/src/routes/approach/index.svelte index f72b3e1..2dbe1df 100644 --- a/src/routes/approach/index.svelte +++ b/src/routes/approach/index.svelte @@ -4,7 +4,7 @@
- + boats in water

I meet each client where they are at and customize their therapeutic journey to best fit their personality and issues. The approaches I use most are listed below:

diff --git a/src/routes/contact/index.svelte b/src/routes/contact/index.svelte index cbedec9..84d9621 100644 --- a/src/routes/contact/index.svelte +++ b/src/routes/contact/index.svelte @@ -1,8 +1,128 @@ + +
-
- - - +

Let's get in touch

+
+ +
+

+

+ Call or text +
+ (530) 638 - 3546 +

+
+
+

+

+ Email +
+ jeffer@mistymountainstherapy.com +

+
+
+
+

Or send us a message

+
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ +
+ +
+
- diff --git a/src/routes/contact/submit.js b/src/routes/contact/submit.js new file mode 100644 index 0000000..cf0d65c --- /dev/null +++ b/src/routes/contact/submit.js @@ -0,0 +1,69 @@ +import 'dotenv/config'; +import sgMail from '@sendgrid/mail'; +sgMail.setApiKey(process.env.SENDGRID_API_KEY); + +export async function get() { + const items = [ + {a: 1, b: 2}, + {a: 3, b: 4}, + {a: 5, b: 6}, + ]; + return { + body: items + }; +} + +export async function post({ request }) { + const body = await request.json(); + const { HCAPTCHA_SECRET, FORM_FROM_EMAIL, FORM_TO_EMAIL } = process.env; + + const captchaVerified = await fetch(`https://hcaptcha.com/siteverify?response=${body.captchaToken}&secret=${HCAPTCHA_SECRET}`, { + method: 'POST', + }) + .then((res) => res.json()) + .then((json) => json.success) + .catch(() => false); + + if (!captchaVerified) { + return { + statusCode: 400, + body: { + error: 'Captcha verification failed', + }, + }; + } + + const msg = { + to: FORM_TO_EMAIL, + from: FORM_FROM_EMAIL, + subject: `Form Submission from ${body.name}`, + text: ` + Name: ${body.name} + Email: ${body.email} + Message: ${body.message} + `, + }; + + const messageSent = await sgMail + .send(msg) + .then(() => true) + .catch((error) => { + console.error(error); + return false; + }); + + if (!messageSent) { + return { + statusCode: 500, + body: { + error: 'Message could not be sent', + }, + }; + } + + return { + body: { + success: true, + }, + }; +} diff --git a/src/routes/index.svelte b/src/routes/index.svelte index 199014a..97d6566 100644 --- a/src/routes/index.svelte +++ b/src/routes/index.svelte @@ -20,7 +20,7 @@ Misty Mountains Therapy is a privately owned, high quality, specialty therapy clinic, founded in January 2020 by Jefferson Hunt. We are dedicated to providing comprehensive therapy evaluation and treatment services to children and adults for a wide variety of disorders in the most efficient and effective manner possible in the Rexburg area. We believe that therapy should be fun, engaging, and most importantly, useful to our clients.

- We are currently accepting new clients and offer a variety of services to help you live the life you desire. To find the right fit for you, schedule a free 15-minute consultation. + We are currently accepting new clients and offer a variety of services to help you live the life you desire. To find the right fit for you, schedule a free 15-minute consultation.

diff --git a/src/routes/team/index.svelte b/src/routes/team/index.svelte index 3d27c0e..52c97ee 100644 --- a/src/routes/team/index.svelte +++ b/src/routes/team/index.svelte @@ -38,7 +38,7 @@

{person.name}, {person.position}

-

{person.bio}

+

{person.bio}

{person.email}

diff --git a/svelte.config.js b/svelte.config.js index 892f0c4..3f578a3 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,4 +1,4 @@ -import adapter from '@sveltejs/adapter-auto'; +import adapter from '@sveltejs/adapter-node'; import preprocess from 'svelte-preprocess'; /** @type {import('@sveltejs/kit').Config} */ @@ -9,7 +9,17 @@ const config = { kit: { adapter: adapter() - } + }, + + csp: { + mode: 'auto', + directives: { + 'script-src': ['self', 'https://hcaptcha.com', 'https://*.hcaptcha.com'], + 'frame-src': ['self', 'https://hcaptcha.com', 'https://*.hcaptcha.com'], + 'style-src': ['self', 'https://hcaptcha.com', 'https://*.hcaptcha.com'], + 'connect-src': ['self', 'https://hcaptcha.com', 'https://*.hcaptcha.com'], + } + }, }; export default config;