| 
									
										
										
										
											2021-06-24 15:59:11 +00:00
										 |  |  | import Head from "next/head"; | 
					
						
							| 
									
										
										
										
											2021-06-29 08:45:54 +00:00
										 |  |  | import Link from "next/link"; | 
					
						
							| 
									
										
										
										
											2021-06-24 15:59:11 +00:00
										 |  |  | import React from "react"; | 
					
						
							|  |  |  | import { getCsrfToken } from "next-auth/client"; | 
					
						
							|  |  |  | import debounce from "lodash.debounce"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default function Page({ csrfToken }) { | 
					
						
							|  |  |  |   const [loading, setLoading] = React.useState(false); | 
					
						
							|  |  |  |   const [error, setError] = React.useState(null); | 
					
						
							|  |  |  |   const [success, setSuccess] = React.useState(false); | 
					
						
							|  |  |  |   const [email, setEmail] = React.useState(""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleChange = (e) => { | 
					
						
							|  |  |  |     setEmail(e.target.value); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const submitForgotPasswordRequest = async ({ email }) => { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       const res = await fetch("/api/auth/forgot-password", { | 
					
						
							|  |  |  |         method: "POST", | 
					
						
							|  |  |  |         body: JSON.stringify({ email: email }), | 
					
						
							|  |  |  |         headers: { | 
					
						
							|  |  |  |           "Content-Type": "application/json", | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const json = await res.json(); | 
					
						
							|  |  |  |       if (!res.ok) { | 
					
						
							|  |  |  |         setError(json); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         setSuccess(true); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return json; | 
					
						
							|  |  |  |     } catch (reason) { | 
					
						
							|  |  |  |       setError({ message: "An unexpected error occurred. Try again." }); | 
					
						
							|  |  |  |     } finally { | 
					
						
							|  |  |  |       setLoading(false); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const debouncedHandleSubmitPasswordRequest = debounce(submitForgotPasswordRequest, 250); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleSubmit = async (e) => { | 
					
						
							|  |  |  |     e.preventDefault(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!email) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (loading) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setLoading(true); | 
					
						
							|  |  |  |     setError(null); | 
					
						
							|  |  |  |     setSuccess(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await debouncedHandleSubmitPasswordRequest({ email }); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const Success = () => { | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |       <div className="space-y-6"> | 
					
						
							|  |  |  |         <h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">Done</h2> | 
					
						
							|  |  |  |         <p>Check your email. We sent you a link to reset your password.</p> | 
					
						
							|  |  |  |         {error && <p className="text-red-600">{error.message}</p>} | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <div className="min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8"> | 
					
						
							|  |  |  |       <Head> | 
					
						
							|  |  |  |         <title>Forgot Password</title> | 
					
						
							|  |  |  |         <link rel="icon" href="/favicon.ico" /> | 
					
						
							|  |  |  |       </Head> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       <div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md"> | 
					
						
							|  |  |  |         <div className="bg-white py-8 px-4 mx-2 shadow rounded-lg sm:px-10 space-y-6"> | 
					
						
							|  |  |  |           {success && <Success />} | 
					
						
							|  |  |  |           {!success && ( | 
					
						
							|  |  |  |             <> | 
					
						
							|  |  |  |               <div className="space-y-6"> | 
					
						
							|  |  |  |                 <h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">Forgot Password</h2> | 
					
						
							|  |  |  |                 <p> | 
					
						
							|  |  |  |                   Enter the email address associated with your account and we will send you a link to reset | 
					
						
							|  |  |  |                   your password. | 
					
						
							|  |  |  |                 </p> | 
					
						
							|  |  |  |                 {error && <p className="text-red-600">{error.message}</p>} | 
					
						
							|  |  |  |               </div> | 
					
						
							|  |  |  |               <form className="space-y-6" onSubmit={handleSubmit} action="#"> | 
					
						
							|  |  |  |                 <input name="csrfToken" type="hidden" defaultValue={csrfToken} hidden /> | 
					
						
							|  |  |  |                 <div> | 
					
						
							|  |  |  |                   <label htmlFor="email" className="block text-sm font-medium text-gray-700"> | 
					
						
							|  |  |  |                     Email address | 
					
						
							|  |  |  |                   </label> | 
					
						
							|  |  |  |                   <div className="mt-1"> | 
					
						
							|  |  |  |                     <input | 
					
						
							|  |  |  |                       onChange={handleChange} | 
					
						
							|  |  |  |                       id="email" | 
					
						
							|  |  |  |                       name="email" | 
					
						
							|  |  |  |                       type="email" | 
					
						
							|  |  |  |                       autoComplete="email" | 
					
						
							|  |  |  |                       placeholder="john.doe@example.com" | 
					
						
							|  |  |  |                       required | 
					
						
							| 
									
										
										
										
											2021-08-02 15:24:01 +00:00
										 |  |  |                       className="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-black focus:border-black sm:text-sm" | 
					
						
							| 
									
										
										
										
											2021-06-24 15:59:11 +00:00
										 |  |  |                     /> | 
					
						
							|  |  |  |                   </div> | 
					
						
							|  |  |  |                 </div> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 <div> | 
					
						
							|  |  |  |                   <button | 
					
						
							|  |  |  |                     type="submit" | 
					
						
							|  |  |  |                     disabled={loading} | 
					
						
							| 
									
										
										
										
											2021-08-02 16:32:45 +00:00
										 |  |  |                     className={`w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-black hover:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black ${ | 
					
						
							| 
									
										
										
										
											2021-06-24 15:59:11 +00:00
										 |  |  |                       loading ? "cursor-not-allowed" : "" | 
					
						
							|  |  |  |                     }`}>
 | 
					
						
							|  |  |  |                     {loading && ( | 
					
						
							|  |  |  |                       <svg | 
					
						
							|  |  |  |                         className="animate-spin -ml-1 mr-3 h-5 w-5 text-white" | 
					
						
							|  |  |  |                         xmlns="http://www.w3.org/2000/svg" | 
					
						
							|  |  |  |                         fill="none" | 
					
						
							|  |  |  |                         viewBox="0 0 24 24"> | 
					
						
							|  |  |  |                         <circle | 
					
						
							|  |  |  |                           className="opacity-25" | 
					
						
							|  |  |  |                           cx="12" | 
					
						
							|  |  |  |                           cy="12" | 
					
						
							|  |  |  |                           r="10" | 
					
						
							|  |  |  |                           stroke="currentColor" | 
					
						
							|  |  |  |                           strokeWidth="4"></circle> | 
					
						
							|  |  |  |                         <path | 
					
						
							|  |  |  |                           className="opacity-75" | 
					
						
							|  |  |  |                           fill="currentColor" | 
					
						
							|  |  |  |                           d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> | 
					
						
							|  |  |  |                       </svg> | 
					
						
							|  |  |  |                     )} | 
					
						
							|  |  |  |                     Request Password Reset | 
					
						
							|  |  |  |                   </button> | 
					
						
							|  |  |  |                 </div> | 
					
						
							| 
									
										
										
										
											2021-06-29 08:45:54 +00:00
										 |  |  |                 <div className="space-y-2"> | 
					
						
							|  |  |  |                   <Link href="/auth/login"> | 
					
						
							|  |  |  |                     <button | 
					
						
							|  |  |  |                       type="button" | 
					
						
							| 
									
										
										
										
											2021-08-02 16:32:45 +00:00
										 |  |  |                       className="w-full flex justify-center py-2 px-4 text-sm font-medium text-black focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black"> | 
					
						
							| 
									
										
										
										
											2021-06-29 08:45:54 +00:00
										 |  |  |                       Login | 
					
						
							|  |  |  |                     </button> | 
					
						
							|  |  |  |                   </Link> | 
					
						
							|  |  |  |                 </div> | 
					
						
							| 
									
										
										
										
											2021-06-24 15:59:11 +00:00
										 |  |  |               </form> | 
					
						
							|  |  |  |             </> | 
					
						
							|  |  |  |           )} | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |     </div> | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Page.getInitialProps = async ({ req }) => { | 
					
						
							|  |  |  |   return { | 
					
						
							|  |  |  |     csrfToken: await getCsrfToken({ req }), | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | }; |