diff --git a/assets/styles/_animations.scss b/assets/styles/_animations.scss index decbe3e..b70f493 100644 --- a/assets/styles/_animations.scss +++ b/assets/styles/_animations.scss @@ -50,3 +50,12 @@ transform: translateY(0); } } + +@keyframes rotate-360 { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/assets/styles/main.scss b/assets/styles/main.scss index acd7e00..23fe008 100644 --- a/assets/styles/main.scss +++ b/assets/styles/main.scss @@ -27,8 +27,8 @@ // Dimensions - --content-width: Min(100%, 120rem); - --text-width: Min(100%, 60rem); + --regular-content-max-width: Min(100%, 80rem); + --small-content-max-width: Min(100%, 60rem); --regular-icon-size: 2rem; --small-icon-size: calc(var(--text-font-size) * var(--line-height)); --button-gap: 0.5rem; @@ -42,6 +42,7 @@ --emerald: #72C080; --granny-smith-apple: #A3F3B0; --middle-green: #428F53; + --rajah: #F9B262; --primary-color: var(--eerie-black); --primary-color-light: var(--sonic-silver); @@ -64,12 +65,13 @@ hsl(130deg 69% 77%) 83%, hsl(130deg 77% 80%) 100% ); + --error-color: var(--rajah); } // Media queries -$tablet-media-query: 48rem; -$desktop-media-query: 62rem; +$tablet-media-query: 48rem; // 768px +$desktop-media-query: 62rem; // 992px // -------------------------------------------------- // FONTS AND COLORS @@ -209,42 +211,52 @@ button { // FORM STYLE // -------------------------------------------------- -div:has(label) { // Not yet supported in Firefox - position: relative; -} +form { -label { - position: absolute; - top: calc(-1 * (var(--text-font-size) / 2)); - left: 1rem; - display: inline-block; - padding: 0 0.5rem; - font-family: var(--title-font-family); - background-color: var(--primary-color); -} + div { + position: relative; + + label { + position: absolute; + top: calc(-1 * (var(--text-font-size) / 2)); + left: 1rem; + display: inline-block; + padding: 0 0.5rem; + font-family: var(--title-font-family); + background-color: var(--primary-color); + } -input, -textarea { - font-family: var(--text-font-family); - font-size: var(--text-font-size); - font-weight: var(--light-font-weight); - line-height: var(--line-height); - width: 100%; - padding: 1rem; - color: var(--secondary-color); - background-color: var(--primary-color); - border: 1px solid var( --primary-color-light); - border-radius: 10px; - transition: border 200ms ease-in-out; + input, + textarea { + font-family: var(--text-font-family); + font-size: var(--text-font-size); + font-weight: var(--light-font-weight); + line-height: var(--line-height); + width: 100%; + padding: 1rem; + color: var(--secondary-color); + background-color: var(--primary-color); + border: 1px solid var( --primary-color-light); + border-radius: 10px; + transition: border 200ms ease-in-out; - &:hover, - &:focus, - &:active { - border: 1px solid var(--accent-color); - outline: none; + &:hover, + &:focus, + &:active { + border: 1px solid var(--accent-color); + outline: none; + } + } + + p { + font-size: var(--caption-font-size); + color: var(--accent-color); + } } + } + textarea { resize: vertical; min-height: 15rem; diff --git a/components/ContactForm.vue b/components/ContactForm.vue index 2f5cdac..e0a9309 100644 --- a/components/ContactForm.vue +++ b/components/ContactForm.vue @@ -1,30 +1,51 @@ @@ -34,37 +55,66 @@ // DATA // -------------------------------------------------- - // const contactName = ref(''); - // const contactEmailAddress = ref(''); - // const contactSubject = ref(''); - // const contactMessage = ref(''); + // Yup schema builder - const contactName = 'Saint Victeur'; - const contactEmailAddress = 'saint.victeur@email.com'; - const contactSubject = 'Test - API Mailjet'; - const contactMessage = `Saint Victeur vous bénit !`; + const yupObject = useNuxtApp().$yupObject; + const yupString = useNuxtApp().$yupString; + + const contactFormSchema = yupObject({ + name: yupString() + .min(2, 'Votre nom doit comprendre au moins ${min} caractères.') + .required('Veuillez saisir votre nom.'), + email: yupString() + .email('Veuillez saisir une adresse e-mail valide.') + .required('Veuillez saisir votre adresse e-mail.'), + subject: yupString() + .min(2, 'Le sujet de votre message doit comprendre au moins ${min} caractères.') + .required('Veuillez saisir le sujet de votre message.'), + message: yupString() + .min(10, 'Votre message doit comprendre au moins ${min} caractères.') + .required('Veuillez saisir votre message.') + }); + + // Form validation + + const isValidated = ref(false); + const isSuccessful = ref(undefined); + + // Loader + + const isLoading = ref(false); + const loader = ref(null); // -------------------------------------------------- // LOGIC // -------------------------------------------------- - const sendEmail = async () => { + const sendEmail = async (values) => { + isLoading.value = true; try { - $fetch('/api/mailjet', { + const response = await $fetch('/api/contact', { method: 'post', body: { - name: contactName, - emailAddress: contactEmailAddress, - subject: contactSubject, - message: contactMessage + name: values.name, + emailAddress: values.email, + subject: values.subject, + message: values.message } }); - console.log('Success!'); - } catch(err) { - console.log('Failure!'); + isSuccessful.value = true; + } catch { + isSuccessful.value = false; + } finally { + loader.value.addEventListener('animationiteration', function hideLoader(event) { + event.currentTarget.removeEventListener('animationiteration', hideLoader); + isLoading.value = false; + isValidated.value = true; + }); } } + const hideValidationMessage = () => isValidated.value = false; + diff --git a/components/ContactHeader.vue b/components/ContactHeader.vue index 782c57d..4a6992b 100644 --- a/components/ContactHeader.vue +++ b/components/ContactHeader.vue @@ -41,7 +41,7 @@ // -------------------------------------------------- .contact-header { - width: var(--text-width); + max-width: var(--small-content-max-width); display: grid; place-content: start; place-items: start; diff --git a/components/ContactSection.vue b/components/ContactSection.vue index a23c141..c05ca7a 100644 --- a/components/ContactSection.vue +++ b/components/ContactSection.vue @@ -18,7 +18,7 @@ // -------------------------------------------------- .contact { - width: var(--content-width); + max-width: var(--regular-content-max-width); display: grid; grid: 'decoration header' auto diff --git a/package-lock.json b/package-lock.json index 4f79a56..ab068eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,10 @@ "hasInstallScript": true, "dependencies": { "@funken-studio/sitemap-nuxt-3": "^4.0.4", - "node-mailjet": "^6.0.1" + "click-outside-vue3": "^4.0.1", + "node-mailjet": "^6.0.1", + "vee-validate": "^4.7.3", + "yup": "^0.32.11" }, "devDependencies": { "minireset.css": "^0.0.7", @@ -459,6 +462,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", + "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/standalone": { "version": "7.20.6", "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.20.6.tgz", @@ -1227,6 +1241,11 @@ "dev": true, "peer": true }, + "node_modules/@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + }, "node_modules/@types/node": { "version": "18.11.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz", @@ -1443,7 +1462,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.45.tgz", "integrity": "sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==", - "dev": true, "dependencies": { "@babel/parser": "^7.16.4", "@vue/shared": "3.2.45", @@ -1454,14 +1472,12 @@ "node_modules/@vue/compiler-core/node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/@vue/compiler-core/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -1470,7 +1486,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.45.tgz", "integrity": "sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==", - "dev": true, "dependencies": { "@vue/compiler-core": "3.2.45", "@vue/shared": "3.2.45" @@ -1480,7 +1495,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.45.tgz", "integrity": "sha512-1jXDuWah1ggsnSAOGsec8cFjT/K6TMZ0sPL3o3d84Ft2AYZi2jWJgRMjw4iaK0rBfA89L5gw427H4n1RZQBu6Q==", - "dev": true, "dependencies": { "@babel/parser": "^7.16.4", "@vue/compiler-core": "3.2.45", @@ -1497,14 +1511,12 @@ "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/@vue/compiler-sfc/node_modules/magic-string": { "version": "0.25.9", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, "dependencies": { "sourcemap-codec": "^1.4.8" } @@ -1513,7 +1525,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -1522,7 +1533,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.45.tgz", "integrity": "sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==", - "dev": true, "dependencies": { "@vue/compiler-dom": "3.2.45", "@vue/shared": "3.2.45" @@ -1531,14 +1541,12 @@ "node_modules/@vue/devtools-api": { "version": "6.4.5", "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.4.5.tgz", - "integrity": "sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==", - "dev": true + "integrity": "sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==" }, "node_modules/@vue/reactivity": { "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.45.tgz", "integrity": "sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==", - "dev": true, "dependencies": { "@vue/shared": "3.2.45" } @@ -1547,7 +1555,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.45.tgz", "integrity": "sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==", - "dev": true, "dependencies": { "@babel/parser": "^7.16.4", "@vue/compiler-core": "3.2.45", @@ -1559,14 +1566,12 @@ "node_modules/@vue/reactivity-transform/node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/@vue/reactivity-transform/node_modules/magic-string": { "version": "0.25.9", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, "dependencies": { "sourcemap-codec": "^1.4.8" } @@ -1575,7 +1580,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.45.tgz", "integrity": "sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==", - "dev": true, "dependencies": { "@vue/reactivity": "3.2.45", "@vue/shared": "3.2.45" @@ -1585,7 +1589,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz", "integrity": "sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==", - "dev": true, "dependencies": { "@vue/runtime-core": "3.2.45", "@vue/shared": "3.2.45", @@ -1596,7 +1599,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.45.tgz", "integrity": "sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==", - "dev": true, "dependencies": { "@vue/compiler-ssr": "3.2.45", "@vue/shared": "3.2.45" @@ -1608,8 +1610,7 @@ "node_modules/@vue/shared": { "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.45.tgz", - "integrity": "sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==", - "dev": true + "integrity": "sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==" }, "node_modules/@vueuse/head": { "version": "1.0.20", @@ -2499,6 +2500,14 @@ "node": ">= 12" } }, + "node_modules/click-outside-vue3": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/click-outside-vue3/-/click-outside-vue3-4.0.1.tgz", + "integrity": "sha512-sbplNecrup5oGqA3o4bo8XmvHRT6q9fvw21Z67aDbTqB9M6LF7CuYLTlLvNtOgKU6W3zst5H5zJuEh4auqA34g==", + "engines": { + "node": ">=6" + } + }, "node_modules/clipboardy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", @@ -2955,8 +2964,7 @@ "node_modules/csstype": { "version": "2.6.21", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", - "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==", - "dev": true + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" }, "node_modules/cuint": { "version": "0.2.2", @@ -4875,8 +4883,12 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, "node_modules/lodash._reinterpolate": { "version": "3.0.0", @@ -5237,6 +5249,11 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "node_modules/nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, "node_modules/nanoid": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.0.tgz", @@ -5836,7 +5853,6 @@ "version": "8.4.19", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz", "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -6382,7 +6398,6 @@ "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -6407,6 +6422,11 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "node_modules/property-expr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", + "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" + }, "node_modules/protocols": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", @@ -6550,6 +6570,11 @@ "node": ">=4" } }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -7069,7 +7094,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -7497,6 +7521,11 @@ "node": ">=0.6" } }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -7694,6 +7723,17 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/vee-validate": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.7.3.tgz", + "integrity": "sha512-1MwHLOzCrabSeChySZVVMamWStcucM1hHxapoebY9mJ7KWOvncMG19a7AlPl38zpE9pcD+G3CHKLvviGmTl5BQ==", + "dependencies": { + "@vue/devtools-api": "^6.1.4" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, "node_modules/vite": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz", @@ -8023,7 +8063,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.45.tgz", "integrity": "sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==", - "dev": true, "dependencies": { "@vue/compiler-dom": "3.2.45", "@vue/compiler-sfc": "3.2.45", @@ -8395,6 +8434,23 @@ "node": ">=8" } }, + "node_modules/yup": { + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/zip-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", @@ -8731,6 +8787,14 @@ "@babel/plugin-syntax-typescript": "^7.20.0" } }, + "@babel/runtime": { + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", + "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", + "requires": { + "regenerator-runtime": "^0.13.11" + } + }, "@babel/standalone": { "version": "7.20.6", "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.20.6.tgz", @@ -9304,6 +9368,11 @@ "dev": true, "peer": true }, + "@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + }, "@types/node": { "version": "18.11.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz", @@ -9476,7 +9545,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.45.tgz", "integrity": "sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==", - "dev": true, "requires": { "@babel/parser": "^7.16.4", "@vue/shared": "3.2.45", @@ -9487,14 +9555,12 @@ "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -9502,7 +9568,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.45.tgz", "integrity": "sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==", - "dev": true, "requires": { "@vue/compiler-core": "3.2.45", "@vue/shared": "3.2.45" @@ -9512,7 +9577,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.45.tgz", "integrity": "sha512-1jXDuWah1ggsnSAOGsec8cFjT/K6TMZ0sPL3o3d84Ft2AYZi2jWJgRMjw4iaK0rBfA89L5gw427H4n1RZQBu6Q==", - "dev": true, "requires": { "@babel/parser": "^7.16.4", "@vue/compiler-core": "3.2.45", @@ -9529,14 +9593,12 @@ "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "magic-string": { "version": "0.25.9", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, "requires": { "sourcemap-codec": "^1.4.8" } @@ -9544,8 +9606,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -9553,7 +9614,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.45.tgz", "integrity": "sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==", - "dev": true, "requires": { "@vue/compiler-dom": "3.2.45", "@vue/shared": "3.2.45" @@ -9562,14 +9622,12 @@ "@vue/devtools-api": { "version": "6.4.5", "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.4.5.tgz", - "integrity": "sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==", - "dev": true + "integrity": "sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==" }, "@vue/reactivity": { "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.45.tgz", "integrity": "sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==", - "dev": true, "requires": { "@vue/shared": "3.2.45" } @@ -9578,7 +9636,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.45.tgz", "integrity": "sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==", - "dev": true, "requires": { "@babel/parser": "^7.16.4", "@vue/compiler-core": "3.2.45", @@ -9590,14 +9647,12 @@ "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "magic-string": { "version": "0.25.9", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, "requires": { "sourcemap-codec": "^1.4.8" } @@ -9608,7 +9663,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.45.tgz", "integrity": "sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==", - "dev": true, "requires": { "@vue/reactivity": "3.2.45", "@vue/shared": "3.2.45" @@ -9618,7 +9672,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz", "integrity": "sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==", - "dev": true, "requires": { "@vue/runtime-core": "3.2.45", "@vue/shared": "3.2.45", @@ -9629,7 +9682,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.45.tgz", "integrity": "sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==", - "dev": true, "requires": { "@vue/compiler-ssr": "3.2.45", "@vue/shared": "3.2.45" @@ -9638,8 +9690,7 @@ "@vue/shared": { "version": "3.2.45", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.45.tgz", - "integrity": "sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==", - "dev": true + "integrity": "sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==" }, "@vueuse/head": { "version": "1.0.20", @@ -10318,6 +10369,11 @@ "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==", "dev": true }, + "click-outside-vue3": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/click-outside-vue3/-/click-outside-vue3-4.0.1.tgz", + "integrity": "sha512-sbplNecrup5oGqA3o4bo8XmvHRT6q9fvw21Z67aDbTqB9M6LF7CuYLTlLvNtOgKU6W3zst5H5zJuEh4auqA34g==" + }, "clipboardy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", @@ -10665,8 +10721,7 @@ "csstype": { "version": "2.6.21", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", - "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==", - "dev": true + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" }, "cuint": { "version": "0.2.2", @@ -11998,8 +12053,12 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, "lodash._reinterpolate": { "version": "3.0.0", @@ -12306,6 +12365,11 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, "nanoid": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.0.tgz", @@ -12767,7 +12831,6 @@ "version": "8.4.19", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz", "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==", - "dev": true, "requires": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -12777,8 +12840,7 @@ "nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" } } }, @@ -13135,6 +13197,11 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "property-expr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", + "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" + }, "protocols": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", @@ -13246,6 +13313,11 @@ "redis-errors": "^1.0.0" } }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -13599,8 +13671,7 @@ "source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, "source-map-support": { "version": "0.5.21", @@ -13914,6 +13985,11 @@ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true }, + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" + }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -14080,6 +14156,14 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "vee-validate": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.7.3.tgz", + "integrity": "sha512-1MwHLOzCrabSeChySZVVMamWStcucM1hHxapoebY9mJ7KWOvncMG19a7AlPl38zpE9pcD+G3CHKLvviGmTl5BQ==", + "requires": { + "@vue/devtools-api": "^6.1.4" + } + }, "vite": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz", @@ -14295,7 +14379,6 @@ "version": "3.2.45", "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.45.tgz", "integrity": "sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==", - "dev": true, "requires": { "@vue/compiler-dom": "3.2.45", "@vue/compiler-sfc": "3.2.45", @@ -14584,6 +14667,20 @@ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true }, + "yup": { + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "requires": { + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + } + }, "zip-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", diff --git a/package.json b/package.json index a9fa91a..cbd161e 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,9 @@ }, "dependencies": { "@funken-studio/sitemap-nuxt-3": "^4.0.4", - "node-mailjet": "^6.0.1" + "click-outside-vue3": "^4.0.1", + "node-mailjet": "^6.0.1", + "vee-validate": "^4.7.3", + "yup": "^0.32.11" } } diff --git a/plugins/click-outside-vue3.js b/plugins/click-outside-vue3.js new file mode 100644 index 0000000..4d48ec9 --- /dev/null +++ b/plugins/click-outside-vue3.js @@ -0,0 +1,5 @@ +import vClickOutside from 'click-outside-vue3'; + +export default defineNuxtPlugin((nuxtApp) => { + nuxtApp.vueApp.use(vClickOutside); +}); diff --git a/plugins/vee-validate.js b/plugins/vee-validate.js new file mode 100644 index 0000000..4828a08 --- /dev/null +++ b/plugins/vee-validate.js @@ -0,0 +1,7 @@ +import { ErrorMessage, Field, Form } from 'vee-validate'; + +export default defineNuxtPlugin((nuxtApp) => { + nuxtApp.vueApp.component('VeeError', ErrorMessage); + nuxtApp.vueApp.component('VeeField', Field); + nuxtApp.vueApp.component('VeeForm', Form); +}); diff --git a/plugins/yup.js b/plugins/yup.js new file mode 100644 index 0000000..f9eea8b --- /dev/null +++ b/plugins/yup.js @@ -0,0 +1,6 @@ +import { object, string } from 'yup'; + +export default defineNuxtPlugin((nuxtApp) => { + nuxtApp.provide('yupObject', object); + nuxtApp.provide('yupString', string); +}); diff --git a/server/api/contact.post.js b/server/api/contact.post.js new file mode 100644 index 0000000..bc4b5bf --- /dev/null +++ b/server/api/contact.post.js @@ -0,0 +1,43 @@ +import Mailjet from 'node-mailjet'; + +export default defineEventHandler(async (event) => { + + // Handle request + const body = await readBody(event); + + // Instantiate and setup Mailjet + const mailjet = new Mailjet({ + apiKey: useRuntimeConfig().mailjetApiPublic, + apiSecret: useRuntimeConfig().mailjetApiPrivate + }); + + // Send email + try { + const response = await mailjet + .post('send', { version: 'v3.1' }) + .request({ + Messages: [ + { + From: { + Email: 'contact@paulnicoue.com', + Name: body.name, + }, + To: [ + { + Email: 'contact@paulnicoue.com', + Name: 'Paul Nicoué', + }, + ], + Subject: body.subject, + TextPart: body.message + } + ] + }); + console.log(response.body); + } catch (error) { + console.log(error.statusCode); + } + + // End response without providing data + event.node.res.end(); +}); diff --git a/server/api/mailjet.post.js b/server/api/mailjet.post.js deleted file mode 100644 index ba062b8..0000000 --- a/server/api/mailjet.post.js +++ /dev/null @@ -1,65 +0,0 @@ -import Mailjet from 'node-mailjet'; - -export default defineEventHandler(async (event) => { - - const body = await readBody(event); - - // const mailjet = new Mailjet({ - // apiKey: useRuntimeConfig().mailjetApiPublic, - // apiSecret: useRuntimeConfig().mailjetApiPrivate - // }); - - // const request = mailjet - // .post('send', { version: 'v3.1' }) - // .request({ - // Messages: [ - // { - // From: { - // Email: 'contact@paulnicoue.com', - // Name: body.name, - // }, - // To: [ - // { - // Email: 'contact@paulnicoue.com', - // Name: 'Paul Nicoué', - // }, - // ], - // Subject: body.subject, - // TextPart: body.message - // } - // ] - // }); - - // request - // .then(result => {console.log(result.body)}) - // .catch(err => {console.log(err.statusCode)}); - - Mailjet - .apiConnect( - useRuntimeConfig().mailjetApiPublic, - useRuntimeConfig().mailjetApiPrivate - ) - .post('send', { version: 'v3.1' }) - .request({ - Messages: [ - { - From: { - Email: 'contact@paulnicoue.com', - Name: body.name, - }, - To: [ - { - Email: 'contact@paulnicoue.com', - Name: 'Paul Nicoué', - }, - ], - Subject: body.subject, - TextPart: body.message - } - ] - }) - .then((result) => console.log(result.body)) - .catch((err) => console.log(err.statusCode)); - - return event.node.res.end(); -});