VerifyEmail.tsx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. import React, { ChangeEvent, Component } from "react";
  2. import styled from "styled-components";
  3. import logo from "assets/logo.png";
  4. import api from "shared/api";
  5. import { emailRegex } from "shared/regex";
  6. import { Context } from "shared/Context";
  7. type PropsType = {
  8. handleLogout: () => void;
  9. };
  10. type StateType = {
  11. submitted: boolean;
  12. };
  13. export default class VerifyEmail extends Component<PropsType, StateType> {
  14. state = {
  15. submitted: false
  16. };
  17. handleSendEmail = (): void => {
  18. api
  19. .createEmailVerification("", {}, {})
  20. .then(res => {
  21. this.setState({ submitted: true });
  22. })
  23. .catch(err => this.context.setCurrentError(err.response.data.errors[0]));
  24. };
  25. render() {
  26. let { submitted } = this.state;
  27. let formSection = (
  28. <div>
  29. <InputWrapper>
  30. <StatusText>A verification email will be sent to</StatusText>
  31. <Email>{this.context.user?.email}</Email>
  32. </InputWrapper>
  33. <StatusText>
  34. Proceed below to verify your email and finish setting up your profile
  35. </StatusText>
  36. <Button onClick={this.handleSendEmail}>Send Verification Email</Button>
  37. </div>
  38. );
  39. if (submitted) {
  40. formSection = (
  41. <>
  42. <Buffer />
  43. <StatusText lessPadding={true}>
  44. A verification email was sent to{" "}
  45. <White>{this.context.user?.email}</White>
  46. </StatusText>
  47. <StatusText lessPadding={true}>
  48. Check your inbox for a verification email. Don't forget to check
  49. your spam folder
  50. </StatusText>
  51. <StatusText lessPadding={true}>
  52. Need help?
  53. <Link href="mailto:contact@getporter.dev">Contact us</Link>
  54. </StatusText>
  55. </>
  56. );
  57. }
  58. return (
  59. <StyledLogin>
  60. <LoginPanel>
  61. <OverflowWrapper>
  62. <GradientBg />
  63. </OverflowWrapper>
  64. <FormWrapper>
  65. <Logo src={logo} />
  66. <Prompt>Verify Your Email</Prompt>
  67. <DarkMatter />
  68. {formSection}
  69. <Helper>
  70. Want to use a different email?
  71. <Link onClick={this.props.handleLogout}>Log out</Link>
  72. </Helper>
  73. </FormWrapper>
  74. </LoginPanel>
  75. <Footer>
  76. © 2021 Porter Technologies Inc. •
  77. <Link
  78. href="https://docs.getporter.dev/docs/terms-of-service"
  79. target="_blank"
  80. >
  81. Terms & Privacy
  82. </Link>
  83. </Footer>
  84. </StyledLogin>
  85. );
  86. }
  87. }
  88. VerifyEmail.contextType = Context;
  89. const Buffer = styled.div`
  90. width: 100%;
  91. height: 20px;
  92. `;
  93. const White = styled.div`
  94. color: white;
  95. `;
  96. const Email = styled.div`
  97. background: #ffffff11;
  98. border: 1px solid #ffffff44;
  99. border-radius: 3px;
  100. font-size: 14px;
  101. color: #aaaabb;
  102. height: 30px;
  103. margin: 0 60px;
  104. display: flex;
  105. align-items: center;
  106. justify-content: center;
  107. `;
  108. const Footer = styled.div`
  109. position: absolute;
  110. bottom: 0;
  111. left: 0;
  112. margin-bottom: 30px;
  113. width: 100vw;
  114. text-align: center;
  115. color: #aaaabb;
  116. font-size: 13px;
  117. padding-right: 8px;
  118. font: Work Sans, sans-serif;
  119. `;
  120. const DarkMatter = styled.div`
  121. margin-top: -20px;
  122. `;
  123. const Or = styled.div`
  124. position: absolute;
  125. width: 30px;
  126. text-align: center;
  127. background: #111114;
  128. z-index: 999;
  129. left: calc(50% - 15px);
  130. margin-top: -1px;
  131. `;
  132. const OrWrapper = styled.div`
  133. display: flex;
  134. align-items: center;
  135. color: #ffffff44;
  136. font-size: 14px;
  137. position: relative;
  138. `;
  139. const IconWrapper = styled.div`
  140. display: flex;
  141. align-items: center;
  142. justify-content: center;
  143. padding: 0 10px;
  144. height: 100%;
  145. `;
  146. const Icon = styled.img`
  147. height: 18px;
  148. margin-right: 20px;
  149. `;
  150. const OAuthButton = styled.div`
  151. width: 200px;
  152. height: 30px;
  153. display: flex;
  154. background: #ffffff;
  155. align-items: center;
  156. border-radius: 3px;
  157. color: #000000;
  158. cursor: pointer;
  159. user-select: none;
  160. font-weight: 500;
  161. font-size: 13px;
  162. :hover {
  163. background: #ffffffdd;
  164. }
  165. `;
  166. const Link = styled.a`
  167. margin-left: 5px;
  168. color: #819bfd;
  169. cursor: pointer;
  170. `;
  171. const Helper = styled.div`
  172. position: absolute;
  173. bottom: 30px;
  174. width: 100%;
  175. text-align: center;
  176. font-size: 13px;
  177. font-family: "Work Sans", sans-serif;
  178. color: #ffffff44;
  179. `;
  180. const OverflowWrapper = styled.div`
  181. position: absolute;
  182. top: 0;
  183. left: 0;
  184. width: 100%;
  185. height: 100%;
  186. overflow: hidden;
  187. border-radius: 10px;
  188. `;
  189. const ErrorHelper = styled.div`
  190. position: absolute;
  191. right: -185px;
  192. top: 8px;
  193. height: 30px;
  194. width: 170px;
  195. user-select: none;
  196. background: #272731;
  197. font-family: "Work Sans", sans-serif;
  198. font-size: 12px;
  199. display: flex;
  200. align-items: center;
  201. justify-content: center;
  202. color: #ff3b62;
  203. border-radius: 3px;
  204. > div {
  205. background: #272731;
  206. height: 15px;
  207. width: 15px;
  208. position: absolute;
  209. left: -3px;
  210. top: 7px;
  211. transform: rotate(45deg);
  212. z-index: -1;
  213. }
  214. `;
  215. const Line = styled.div`
  216. min-height: 3px;
  217. width: 100px;
  218. z-index: 999;
  219. background: #ffffff22;
  220. margin: 30px 0px 30px;
  221. `;
  222. const Button = styled.button`
  223. width: 200px;
  224. min-height: 30px;
  225. display: flex;
  226. justify-content: center;
  227. align-items: center;
  228. font-family: "Work Sans", sans-serif;
  229. cursor: pointer;
  230. margin: 9px auto;
  231. border-radius: 2px;
  232. border: 0;
  233. background: #819bfd;
  234. color: white;
  235. font-weight: 500;
  236. font-size: 14px;
  237. `;
  238. const InputWrapper = styled.div`
  239. position: relative;
  240. `;
  241. const Input = styled.input`
  242. width: 200px;
  243. font-family: "Work Sans", sans-serif;
  244. margin: 8px 0px;
  245. height: 30px;
  246. padding: 8px;
  247. background: #ffffff12;
  248. color: #ffffff;
  249. border: ${(props: { valid?: boolean }) =>
  250. props.valid ? "0" : "1px solid #ff3b62"};
  251. border-radius: 2px;
  252. font-size: 14px;
  253. `;
  254. const Prompt = styled.div`
  255. font-family: "Work Sans", sans-serif;
  256. font-weight: 500;
  257. font-size: 15px;
  258. margin-bottom: 18px;
  259. `;
  260. const Logo = styled.img`
  261. width: 140px;
  262. margin-top: 50px;
  263. margin-bottom: 60px;
  264. user-select: none;
  265. `;
  266. const StatusText = styled.div<{ lessPadding?: boolean }>`
  267. padding: ${props => (props.lessPadding ? "10px" : "18px")} 40px;
  268. font-family: "Work Sans", sans-serif;
  269. font-size: 14px;
  270. line-height: 160%;
  271. color: #aaaabb;
  272. text-align: center;
  273. `;
  274. const FormWrapper = styled.div`
  275. width: calc(100% - 8px);
  276. height: calc(100% - 8px);
  277. background: #111114;
  278. z-index: 1;
  279. border-radius: 10px;
  280. display: flex;
  281. flex-direction: column;
  282. align-items: center;
  283. `;
  284. const GradientBg = styled.div`
  285. background: linear-gradient(#8ce1ff, #a59eff, #fba8ff);
  286. width: 180%;
  287. height: 180%;
  288. position: absolute;
  289. top: -40%;
  290. left: -40%;
  291. animation: flip 6s infinite linear;
  292. @keyframes flip {
  293. from {
  294. transform: rotate(0deg);
  295. }
  296. to {
  297. transform: rotate(360deg);
  298. }
  299. }
  300. `;
  301. const LoginPanel = styled.div`
  302. width: 330px;
  303. height: 470px;
  304. background: white;
  305. margin-top: -20px;
  306. border-radius: 10px;
  307. display: flex;
  308. justify-content: center;
  309. position: relative;
  310. align-items: center;
  311. `;
  312. const StyledLogin = styled.div`
  313. display: flex;
  314. align-items: center;
  315. justify-content: center;
  316. width: 100vw;
  317. height: 100vh;
  318. position: fixed;
  319. top: 0;
  320. left: 0;
  321. background: #111114;
  322. `;