| import PropType from 'prop-types'; | import PropType from 'prop-types'; | ||||
| import React from 'react'; | import React from 'react'; | ||||
| import { BASE_PAGE } from '../../../constants/pages'; | import { BASE_PAGE } from '../../../constants/pages'; | ||||
| import { postQuestion } from '../../../requests/question/postQuestionRequest'; | |||||
| import { contactPageSchema } from '../../../schemas/contactSchema'; | import { contactPageSchema } from '../../../schemas/contactSchema'; | ||||
| const ContactPageForm = () => { | const ContactPageForm = () => { | ||||
| //const [error] = useState({ hasError: false, errorMessage: '' }); | //const [error] = useState({ hasError: false, errorMessage: '' }); | ||||
| const handleSubmit = async (values) => { | const handleSubmit = async (values) => { | ||||
| console.log(values); | |||||
| try { | |||||
| postQuestion(values); | |||||
| } catch (error) { | |||||
| console.log(error); | |||||
| } | |||||
| }; | }; | ||||
| const formik = useFormik({ | const formik = useFormik({ |
| const mongoose = require('mongoose'); | |||||
| const validator = require('validator'); | |||||
| const QuestionSchema = new mongoose.Schema({ | |||||
| firstName: { | |||||
| type: String, | |||||
| required: [true, 'Please provide a name.'], | |||||
| maxlength: [60, 'Name cannot be more than 60 characters'], | |||||
| trim: true, | |||||
| }, | |||||
| lastName: { | |||||
| type: String, | |||||
| required: [true, 'Please provide a last name.'], | |||||
| maxlength: [60, 'Name cannot be more than 60 characters'], | |||||
| trim: true, | |||||
| }, | |||||
| email: { | |||||
| type: String, | |||||
| unique: [true, 'Email must be unique.'], | |||||
| required: [true, 'Please provide an email.'], | |||||
| trim: true, | |||||
| lowercase: true, | |||||
| validate(value) { | |||||
| if (!validator.isEmail(value)) { | |||||
| throw new Error('Email is invalid'); | |||||
| } | |||||
| }, | |||||
| }, | |||||
| message: { | |||||
| type: String, | |||||
| required: [true, 'Please provide a message/question.'], | |||||
| trim: true, | |||||
| }, | |||||
| }); | |||||
| const Question = | |||||
| mongoose.models.Question || | |||||
| mongoose.model('Question', QuestionSchema, 'Questions'); | |||||
| module.exports = Question; |
| NEXT_PUBLIC_STRIPE_PUBLIC_API_KEY: | NEXT_PUBLIC_STRIPE_PUBLIC_API_KEY: | ||||
| process.env.NEXT_PUBLIC_STRIPE_PUBLIC_API_KEY, | process.env.NEXT_PUBLIC_STRIPE_PUBLIC_API_KEY, | ||||
| NEXT_PUBLIC_MAP_KEY: process.env.NEXT_PUBLIC_NEXT_PUBLIC_MAP_KEY, | NEXT_PUBLIC_MAP_KEY: process.env.NEXT_PUBLIC_NEXT_PUBLIC_MAP_KEY, | ||||
| NEXT_PUBLIC_SEND_GRID: process.env.NEXT_PUBLIC_SEND_GRID, | |||||
| }, | }, | ||||
| reactStrictMode: true, | reactStrictMode: true, | ||||
| swcMinify: true, | swcMinify: true, |
| "@mui/icons-material": "^5.8.4", | "@mui/icons-material": "^5.8.4", | ||||
| "@mui/material": "^5.9.2", | "@mui/material": "^5.9.2", | ||||
| "@react-google-maps/api": "^2.12.2", | "@react-google-maps/api": "^2.12.2", | ||||
| "@sendgrid/mail": "^7.7.0", | |||||
| "@stripe/stripe-js": "^1.35.0", | "@stripe/stripe-js": "^1.35.0", | ||||
| "@tanstack/react-query": "^4.0.10", | "@tanstack/react-query": "^4.0.10", | ||||
| "bcryptjs": "^2.4.3", | "bcryptjs": "^2.4.3", |
| const Product = require('../../../models/product'); | const Product = require('../../../models/product'); | ||||
| import dbConnect from '../../../utils/helpers/dbHelpers'; | import dbConnect from '../../../utils/helpers/dbHelpers'; | ||||
| const shuffle = function (v) { | |||||
| //+ Jonas Raoni Soares Silva | |||||
| //@ http://jsfromhell.com/array/shuffle [rev. #1] | |||||
| for ( | |||||
| var j, x, i = v.length; | |||||
| i; | |||||
| j = parseInt(Math.random() * i), x = v[--i], v[i] = v[j], v[j] = x | |||||
| ); | |||||
| return v; | |||||
| }; | |||||
| async function handler(req, res) { | async function handler(req, res) { | ||||
| const { method } = req; | const { method } = req; | ||||
| throw new Error('The product with this id does not exist!'); | throw new Error('The product with this id does not exist!'); | ||||
| } | } | ||||
| const similarProducts = await Product.find({ | |||||
| category: product.category, | |||||
| customID: { $ne: product.customID }, | |||||
| }); | |||||
| const shuffled = similarProducts | |||||
| .sort(() => 0.5 - Math.random()) | |||||
| .slice(0, 3); | |||||
| res.status(200).json({ | res.status(200).json({ | ||||
| message: 'The product you requested was fetched successfully.', | message: 'The product you requested was fetched successfully.', | ||||
| product, | product, | ||||
| similarProducts: shuffled, | |||||
| }); | }); | ||||
| } catch (error) { | } catch (error) { | ||||
| res.status(400).json({ message: error.message }); | res.status(400).json({ message: error.message }); |
| const Question = require('../../../models/question'); | |||||
| import dbConnect from '../../../utils/helpers/dbHelpers'; | |||||
| const sgMail = require('@sendgrid/mail'); | |||||
| async function handler(req, res) { | |||||
| const { method } = req; | |||||
| await dbConnect(); | |||||
| switch (method) { | |||||
| case 'POST': { | |||||
| try { | |||||
| const question = await Question.create(req.body); | |||||
| sgMail.setApiKey(process.env.NEXT_PUBLIC_SEND_GRID); | |||||
| const msg = { | |||||
| to: 'nikola.tasic@dilig.net', //req.body.email, // Change to your recipient | |||||
| from: 'nikola.tasic@dilig.net', // Change to your verified sender | |||||
| subject: 'Question submitted', | |||||
| text: 'Your question was submitted successfully, we will contact you via email shortly. Thank you!', | |||||
| html: '<strong>Your question was submitted successfully, we will contact you via email shortly. Thank you!</strong>', | |||||
| }; | |||||
| sgMail | |||||
| .send(msg) | |||||
| .then(() => { | |||||
| console.log('Email sent'); | |||||
| }) | |||||
| .catch((error) => { | |||||
| res.status(400).json({ message: error }); | |||||
| }); | |||||
| res.status(201).json({ | |||||
| message: | |||||
| 'Your message/question was submitted successfully, check your mail for confirmation.', | |||||
| question, | |||||
| }); | |||||
| } catch (error) { | |||||
| res.status(400).json({ message: error }); | |||||
| } | |||||
| break; | |||||
| } | |||||
| default: | |||||
| res.status(405).json({ message: 'Method not allowed' }); | |||||
| break; | |||||
| } | |||||
| } | |||||
| export default handler; |
| featuredProducts: '/api/product/featured-products', | featuredProducts: '/api/product/featured-products', | ||||
| order: '/api/order', | order: '/api/order', | ||||
| userUpdate: '/api/user', | userUpdate: '/api/user', | ||||
| question: '/api/question', | |||||
| }; | }; |
| import apiEndpoints from '../apiEndpoints'; | |||||
| export const postQuestion = async (questionData) => { | |||||
| const response = await fetch(apiEndpoints.question, { | |||||
| method: 'POST', | |||||
| body: JSON.stringify(questionData), | |||||
| headers: { | |||||
| 'Content-Type': 'application/json', | |||||
| }, | |||||
| }); | |||||
| const data = await response.json(); | |||||
| if (!response.ok) { | |||||
| throw new Error(data.message || 'Something went wrong!'); | |||||
| } | |||||
| return data; | |||||
| }; |
| resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz" | resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz" | ||||
| integrity sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA== | integrity sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA== | ||||
| "@sendgrid/client@^7.7.0": | |||||
| version "7.7.0" | |||||
| resolved "https://registry.yarnpkg.com/@sendgrid/client/-/client-7.7.0.tgz#f8f67abd604205a0d0b1af091b61517ef465fdbf" | |||||
| integrity sha512-SxH+y8jeAQSnDavrTD0uGDXYIIkFylCo+eDofVmZLQ0f862nnqbC3Vd1ej6b7Le7lboyzQF6F7Fodv02rYspuA== | |||||
| dependencies: | |||||
| "@sendgrid/helpers" "^7.7.0" | |||||
| axios "^0.26.0" | |||||
| "@sendgrid/helpers@^7.7.0": | |||||
| version "7.7.0" | |||||
| resolved "https://registry.yarnpkg.com/@sendgrid/helpers/-/helpers-7.7.0.tgz#93fb4b6e2f0dc65080440d6a784cc93e8e148757" | |||||
| integrity sha512-3AsAxfN3GDBcXoZ/y1mzAAbKzTtUZ5+ZrHOmWQ279AuaFXUNCh9bPnRpN504bgveTqoW+11IzPg3I0WVgDINpw== | |||||
| dependencies: | |||||
| deepmerge "^4.2.2" | |||||
| "@sendgrid/mail@^7.7.0": | |||||
| version "7.7.0" | |||||
| resolved "https://registry.yarnpkg.com/@sendgrid/mail/-/mail-7.7.0.tgz#aba09f5ce2e9d8ceee92284c3ea8b4a90b0e38fe" | |||||
| integrity sha512-5+nApPE9wINBvHSUxwOxkkQqM/IAAaBYoP9hw7WwgDNQPxraruVqHizeTitVtKGiqWCKm2mnjh4XGN3fvFLqaw== | |||||
| dependencies: | |||||
| "@sendgrid/client" "^7.7.0" | |||||
| "@sendgrid/helpers" "^7.7.0" | |||||
| "@storybook/addon-actions@6.5.9", "@storybook/addon-actions@^6.5.9": | "@storybook/addon-actions@6.5.9", "@storybook/addon-actions@^6.5.9": | ||||
| version "6.5.9" | version "6.5.9" | ||||
| resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.5.9.tgz" | resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.5.9.tgz" | ||||
| resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz" | resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz" | ||||
| integrity sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w== | integrity sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w== | ||||
| axios@^0.26.0: | |||||
| version "0.26.1" | |||||
| resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" | |||||
| integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== | |||||
| dependencies: | |||||
| follow-redirects "^1.14.8" | |||||
| axobject-query@^2.2.0: | axobject-query@^2.2.0: | ||||
| version "2.2.0" | version "2.2.0" | ||||
| resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz" | resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz" | ||||
| dependencies: | dependencies: | ||||
| tslib "^1.9.3" | tslib "^1.9.3" | ||||
| follow-redirects@^1.14.8: | |||||
| version "1.15.2" | |||||
| resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" | |||||
| integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== | |||||
| for-in@^1.0.2: | for-in@^1.0.2: | ||||
| version "1.0.2" | version "1.0.2" | ||||
| resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" | resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" | ||||
| dependencies: | dependencies: | ||||
| minimist "^1.2.6" | minimist "^1.2.6" | ||||
| mkdirp@^1.0.3, mkdirp@^1.0.4: | |||||
| version "1.0.4" | |||||
| resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" | |||||
| integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== | |||||
| dependencies: | |||||
| yallist "^4.0.0" | |||||
| minizlib@^2.1.1: | |||||
| version "2.1.2" | |||||
| resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" | |||||
| integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== | |||||
| dependencies: | |||||
| minipass "^3.0.0" | |||||
| yallist "^4.0.0" | |||||
| mixin-deep@^1.2.0: | |||||
| version "1.3.2" | |||||
| resolved "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz" | |||||
| integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== | |||||
| dependencies: | |||||
| for-in "^1.0.2" | |||||
| is-extendable "^1.0.1" | |||||
| mkdirp@^0.5.1: | |||||
| version "0.5.6" | |||||
| resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" | |||||
| integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== | |||||
| dependencies: | |||||
| minimist "^1.2.6" | |||||
| mkdirp@^1.0.3, mkdirp@^1.0.4: | mkdirp@^1.0.3, mkdirp@^1.0.4: | ||||
| version "1.0.4" | version "1.0.4" | ||||
| resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" | resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" |