|
1 | 1 | <script> |
2 | 2 | import { Section } from '$lib/utils'; |
3 | | - import { IconMailFilled, IconPhoneFilled, IconMapPinFilled } from '@tabler/icons-svelte'; |
4 | | - import { dev } from '$app/environment'; |
| 3 | + import { getToastStore } from '@skeletonlabs/skeleton'; |
| 4 | + import { IconMailFilled, IconMapPinFilled } from '@tabler/icons-svelte'; |
5 | 5 |
|
6 | | - const formSpree = import.meta.env.VITE_FORMSPREE; |
| 6 | + const env = import.meta.env.VITE_ENV ?? 'development'; |
| 7 | + const formSpree = import.meta.env.VITE_FORMSPREE ?? '#'; |
| 8 | + const toast = getToastStore(); |
7 | 9 |
|
8 | 10 | let firstname = ''; |
9 | 11 | let lastname = ''; |
10 | 12 | let email = ''; |
11 | 13 | let phone = ''; |
12 | 14 | let message = ''; |
13 | | - let status = ''; |
14 | 15 |
|
15 | | - async function handleSubmit(event) { |
16 | | - const data = new FormData(event.target); |
17 | | - if (dev) { |
18 | | - status = 'Thanks for your submission!'; |
| 16 | + function clearForm() { |
| 17 | + firstname = ''; |
| 18 | + lastname = ''; |
| 19 | + email = ''; |
| 20 | + phone = ''; |
| 21 | + message = ''; |
| 22 | + } |
| 23 | +
|
| 24 | + function validateEmail(email) { |
| 25 | + const re = /\S+@\S+\.\S+/; |
| 26 | + return re.test(email); |
| 27 | + } |
| 28 | +
|
| 29 | + function triggerToast(message, type = 'success') { |
| 30 | + let background; |
| 31 | + switch (type) { |
| 32 | + case 'success': |
| 33 | + background = 'variant-filled-success'; |
| 34 | + break; |
| 35 | + case 'error': |
| 36 | + background = 'variant-filled-error'; |
| 37 | + break; |
| 38 | + default: |
| 39 | + background = 'variant-filled-success'; |
| 40 | + } |
| 41 | + const t = { |
| 42 | + message, |
| 43 | + background, |
| 44 | + timeout: 2500 |
| 45 | + }; |
| 46 | + toast.trigger(t); |
| 47 | + } |
| 48 | +
|
| 49 | + async function handleSubmit(_event) { |
| 50 | + if (env === 'development') { |
| 51 | + triggerToast('Thanks for your submission!', 'success'); |
| 52 | + clearForm(); |
19 | 53 | return; |
20 | 54 | } |
21 | 55 | try { |
22 | | - const response = await fetch(event.target.action, { |
| 56 | + if (!validateEmail(email)) { |
| 57 | + triggerToast('Please enter a valid email address', 'error'); |
| 58 | + return; |
| 59 | + } |
| 60 | + const response = await fetch(formSpree, { |
23 | 61 | method: 'POST', |
24 | | - body: data, |
| 62 | + body: { |
| 63 | + firstname, |
| 64 | + lastname, |
| 65 | + email, |
| 66 | + phone, |
| 67 | + message |
| 68 | + }, |
25 | 69 | headers: { |
26 | 70 | Accept: 'application/json' |
27 | 71 | } |
28 | 72 | }); |
29 | 73 | if (response.ok) { |
30 | | - status = 'Thanks for your submission!'; |
31 | | - firstname = ''; |
32 | | - lastname = ''; |
33 | | - email = ''; |
34 | | - phone = ''; |
35 | | - message = ''; |
| 74 | + triggerToast('Thanks for your submission!', 'success'); |
| 75 | + clearForm(); |
36 | 76 | } else { |
37 | 77 | const data = await response.json(); |
38 | 78 | if (Object.hasOwn(data, 'errors')) { |
39 | | - status = data['errors'].map((error) => error['message']).join(', '); |
| 79 | + const errorMessages = data['errors'].map((error) => error['message']).join(', '); |
| 80 | + triggerToast(errorMessages, 'error'); |
40 | 81 | } else { |
41 | | - status = 'Oops! There was a problem submitting your form'; |
| 82 | + triggerToast('Oops! There was a problem submitting your form', 'error'); |
42 | 83 | } |
43 | 84 | } |
44 | 85 | } catch (error) { |
45 | | - status = 'Oops! There was a problem submitting your form'; |
| 86 | + triggerToast('Oops! There was a problem submitting your form', 'error'); |
46 | 87 | } |
47 | 88 | } |
48 | 89 | </script> |
|
55 | 96 | <div |
56 | 97 | class="w-auto gap-4 mx-auto border-transparent rounded-md sm:p-1 lg:w-3/5 opacity-95 bg-slate-100 md:flex md:grid-cols-2" |
57 | 98 | > |
58 | | - <div class="p-6 text-white rounded-t-md sm:rounded-md bg-surface-600 lg:w-1/3"> |
| 99 | + <div class="p-6 text-white rounded-t-md text-wrap sm:rounded-md bg-surface-600 lg:w-1/3"> |
59 | 100 | <header class="font-medium card-header h3">Contact Information</header> |
60 | 101 | <section class="grid gap-5 mt-8 lg:mt-10 lg:gap-10"> |
61 | | - <div class="flex gap-5"> |
62 | | - <IconPhoneFilled /> |
63 | | - <span>+685 1234567</span> |
64 | | - </div> |
65 | 102 | <div class="flex gap-5"> |
66 | 103 | <IconMailFilled /> |
67 | | - <span>admin@sch.com</span> |
| 104 | + <span class="break-normal">samoastackoverflow@gmail.com</span> |
68 | 105 | </div> |
69 | 106 | <div class="flex gap-5"> |
70 | 107 | <IconMapPinFilled /> |
|
143 | 180 | <div class="mx-2 mt-2 mb-6 text-white bg-blue-500 rounded-xl md:justify-self-end btn"> |
144 | 181 | <button type="submit"> Send message </button> |
145 | 182 | </div> |
146 | | - <p class="text-blue-600">{status}</p> |
147 | 183 | </form> |
148 | 184 | </div> |
149 | 185 | </section> |
0 commit comments