You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ClientForm.jsx 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. import React, { useRef } from 'react';
  2. import TagInput from '../TagInput';
  3. import img from '../../assets/images/Inqueries.png';
  4. import * as Yup from 'yup';
  5. import { Formik, Form, ErrorMessage } from 'formik';
  6. import { ClientFormContext } from '../../context';
  7. import { useContext, useState } from 'react';
  8. import * as emailjs from 'emailjs-com';
  9. import { motion } from 'framer-motion';
  10. import ReactGA from 'react-ga4';
  11. import ReCAPTCHA from 'react-google-recaptcha';
  12. import axios from 'axios';
  13. export default function ClientForm() {
  14. //search context for prevous entry TODO
  15. const { clientForm, setClientForm } = useContext(ClientFormContext);
  16. const [sucMsg, setSucMsg] = useState(false);
  17. const captchaRef = useRef(null);
  18. const [msgText, setMsgText] = useState('');
  19. const changeFormHandler = event => {
  20. const { name, value } = event.target;
  21. setClientForm({
  22. ...clientForm,
  23. [name]: value,
  24. });
  25. };
  26. const validationSchema = Yup.object({
  27. subject: Yup.string()
  28. .min(2, 'Subject too short')
  29. .max(50, 'Subject too long')
  30. .required('Subject is Required'),
  31. email: Yup.string().email('Invalid email format').required('Email is Required'),
  32. firstName: Yup.string()
  33. .min(2, 'First name too short')
  34. .max(50, 'First name too long')
  35. .required('First Name is Required'),
  36. lastName: Yup.string()
  37. .min(2, 'Last name too short')
  38. .max(50, 'Last name too long')
  39. .required('Last Name is Required'),
  40. description: Yup.string()
  41. .trim()
  42. .min(2, 'Description too short')
  43. .required('Description is Required'),
  44. });
  45. return (
  46. <div className="mt-10 sm:mt-0 mx-auto">
  47. <div className="md:grid md:grid-cols-2 md:gap-6">
  48. <motion.div
  49. className="mt-5 md:mt-0 md:col-span-1"
  50. initial={{ x: -60, opacity: 0 }}
  51. animate={{ x: 0, opacity: 1 }}
  52. exit={{ x: -60, opacity: 0 }}
  53. transition={{ duration: 0.3, ease: 'easeOut' }}
  54. >
  55. <Formik
  56. initialValues={clientForm}
  57. validationSchema={validationSchema}
  58. onSubmit={async values => {
  59. const data = {
  60. Tag: values.tag,
  61. Subject: values.subject,
  62. Email: values.email,
  63. Firstname: values.firstName,
  64. Lastname: values.lastName,
  65. Description: values.description,
  66. };
  67. const token = captchaRef.current.getValue();
  68. captchaRef.current.reset();
  69. if (token.length === 0) {
  70. setSucMsg(true);
  71. setMsgText('Please fill reCAPTCHA and try again. Thank you!');
  72. } else {
  73. await axios
  74. .post(`${process.env.REACT_APP_CAPTCHA_API}/verify-token`, { token })
  75. .then(res => {
  76. setSucMsg(true);
  77. if (res.data.data.success) {
  78. setMsgText('Submission Succesful! Thank you!');
  79. // mg.messages.create('dilig.net', {
  80. // from: `${values.firstName} ${values.lastName} <${values.email}>`,
  81. // to: ['nikola.tasic@dilig.net'],
  82. // subject: `${values.subject}`,
  83. // text: `${values.description}`,
  84. // html: `<p>${values.description}</p>`,
  85. // });
  86. emailjs
  87. .send(
  88. process.env.REACT_APP_SERVICE_ID,
  89. process.env.REACT_APP_CLIENT_TEMPLATE_ID,
  90. data,
  91. process.env.REACT_APP_USER_ID,
  92. )
  93. .then(
  94. result => {
  95. console.log(result.text);
  96. setSucMsg(true);
  97. },
  98. error => {
  99. console.log(error.text);
  100. },
  101. );
  102. } else setMsgText('Please fill reCAPTCHA and try again. Thank you!');
  103. })
  104. .catch(error => {
  105. console.log(error);
  106. });
  107. }
  108. ReactGA.event('contact', {
  109. category: 'Contact',
  110. action: 'Business Inquiry',
  111. });
  112. }}
  113. >
  114. {props => (
  115. <Form onSubmit={props.handleSubmit}>
  116. <div className=" sm:rounded-md">
  117. <div className="py-2 sm:py-6">
  118. <div className="">
  119. <div className="col-span-1 sm:col-span-1">
  120. <div className="py-1">
  121. <TagInput changeFormHandler={changeFormHandler} props={props} />
  122. </div>
  123. <div className="py-1">
  124. <label
  125. htmlFor="first-name"
  126. className="block text-sm font-medium text-gray-700 dark:text-gray-400"
  127. >
  128. First name
  129. </label>
  130. <input
  131. type="text"
  132. name="firstName"
  133. id="firstName"
  134. onBlur={changeFormHandler}
  135. value={props.values.firstName}
  136. onChange={props.handleChange}
  137. autoComplete="given-name"
  138. className="mt-1 focus:ring-dg-primary-600 focus:border-dg-primary-900 dark:bg-dg-primary-1500 dark:text-white block w-full shadow-sm sm:text-sm border-dg-primary-600 rounded-md transition duration-200"
  139. />
  140. <div className="h-4">
  141. <ErrorMessage
  142. name="firstName"
  143. component="div"
  144. className="text-sm text-right text-red-600"
  145. />
  146. </div>
  147. </div>
  148. <div className="py-1">
  149. <label
  150. htmlFor="last-name"
  151. className="block text-sm font-medium text-gray-700 dark:text-gray-400"
  152. >
  153. Last name
  154. </label>
  155. <input
  156. onBlur={changeFormHandler}
  157. type="text"
  158. name="lastName"
  159. id="lastName"
  160. value={props.values.lastName}
  161. onChange={props.handleChange}
  162. autoComplete="family-name"
  163. className="mt-1 focus:ring-dg-primary-900 focus:border-dg-primary-900 dark:bg-dg-primary-1500 dark:text-white block w-full shadow-sm sm:text-sm border-dg-primary-600 rounded-md transition duration-200"
  164. />
  165. <div className="h-4">
  166. <ErrorMessage
  167. name="lastName"
  168. component="div"
  169. className="text-sm text-right text-red-600"
  170. />
  171. </div>
  172. </div>
  173. <div className="py-1">
  174. <label
  175. htmlFor="email"
  176. className="block text-sm font-medium text-gray-700 dark:text-gray-400"
  177. >
  178. Email
  179. </label>
  180. <input
  181. onBlur={changeFormHandler}
  182. type="email"
  183. name="email"
  184. id="email"
  185. value={props.values.email}
  186. onChange={props.handleChange}
  187. autoComplete="email"
  188. className="mt-1 focus:ring-dg-primary-900 focus:border-dg-primary-900 dark:bg-dg-primary-1500 dark:text-white dark:autofill:text-white dark:autofill:bg-dg-primary-1500 block w-full shadow-sm sm:text-sm border-dg-primary-600 rounded-md transition duration-200"
  189. />
  190. <div className="h-4">
  191. <ErrorMessage
  192. name="email"
  193. component="div"
  194. className="text-sm text-right text-red-600"
  195. />
  196. </div>
  197. </div>
  198. {/* <div className="form-check py-2">
  199. <input
  200. className="form-check-input appearance-none h-6 w-6 border text-dg-primary-900 border-dg-primary-600 rounded-sm bg-white checked:dg-primary-900 checked:border-dg-primary-900 focus:outline-none transition duration-200 align-top bg-no-repeat bg-center bg-contain float-left cursor-pointer focus:ring-dg-primary-900"
  201. type="checkbox"
  202. value=""
  203. id="meeting"
  204. />
  205. <label
  206. className="ml-3 form-check-label inline-block text-gray-800"
  207. htmlFor="meeting"
  208. >
  209. Schedule a meeting right away
  210. </label>
  211. </div> */}
  212. <div className="py-1">
  213. <label
  214. htmlFor="Description"
  215. className="block text-sm font-medium text-gray-700 dark:text-gray-400"
  216. >
  217. Description
  218. </label>
  219. <textarea
  220. onBlur={changeFormHandler}
  221. type="text"
  222. placeholder="Describe your question or proposition..."
  223. className="resize-y min-h-12 h-32 rounded-md mt-1 text-base focus:ring-dg-primary-900 focus:border-dg-primary-900 dark:bg-dg-primary-1500 dark:text-white sm:text-sm border-dg-primary-600 block w-full shadow-sm transition duration-200"
  224. name="description"
  225. id="description"
  226. value={props.values.description}
  227. onChange={props.handleChange}
  228. ></textarea>
  229. <div className="h-4">
  230. <ErrorMessage
  231. name="description"
  232. component="div"
  233. className="text-sm text-right text-red-600"
  234. />
  235. </div>
  236. </div>
  237. <div className="items-center justify-end flex">
  238. <ReCAPTCHA
  239. sitekey={process.env.REACT_APP_SITE_KEY}
  240. ref={captchaRef}
  241. />
  242. </div>
  243. <div className=" py-3 text-right">
  244. <button
  245. type="submit"
  246. className="btn btn_primary transition-all inline-flex justify-center py-4 px-14 border border-transparent shadow-md text-sm font-semibold rounded-xl text-white bg-dg-primary-600 hover:bg-dg-primary-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-dg-primary-600"
  247. >
  248. Submit
  249. </button>
  250. </div>
  251. {sucMsg && (
  252. <div className={'text-sm text-right text-dg-primary-900'}>
  253. {msgText}
  254. </div>
  255. )}
  256. </div>
  257. <div className="col-span-1 sm:col-span-1 lg:col-span-1"></div>
  258. </div>
  259. </div>
  260. </div>
  261. </Form>
  262. )}
  263. </Formik>
  264. </motion.div>
  265. <motion.div
  266. className="mt-5 md:mt-0 md:col-span-1 flex items-center"
  267. initial={{ x: 60, opacity: 0 }}
  268. animate={{ x: 0, opacity: 1 }}
  269. exit={{ x: 60, opacity: 0 }}
  270. transition={{ duration: 0.3, ease: 'easeOut' }}
  271. >
  272. <img src={img} alt="Our Team's image" />
  273. </motion.div>
  274. </div>
  275. </div>
  276. );
  277. }