-
Notifications
You must be signed in to change notification settings - Fork 0
Add more auth pages #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
75eb0ec
Add forgot password page
jzgom067 20fd8ef
Add reset password page
jzgom067 9858e27
Add extra checks to reset password page
jzgom067 40ac04c
Add email sent section to sign up
jzgom067 039e1ad
Change login and signup pages to have email fields
jzgom067 e44e9c2
Add verify email page
jzgom067 ceb8e5f
Add email verification functionality
jzgom067 e97b2be
Create MessagePage component
jzgom067 b02fd18
Separate email sent page from sign up
jzgom067 914e612
Separate success page from reset password
jzgom067 c9f62aa
Remove random email verification
jzgom067 9f5cf85
Remove button type file
jzgom067 432d4be
Decrease spacing in message page
jzgom067 9f354d5
Change secondary button to use border
jzgom067 048a0f1
Change button type to avoid form submission
jzgom067 ac921ec
Change description argument to optional
jzgom067 cf541de
Move MessagePage to layouts folder
jzgom067 275d296
Add cooldown to resend email button
jzgom067 8e96365
Fix email resend timer persistence
jzgom067 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,74 @@ | ||
| "use client"; | ||
|
|
||
| import React, { useState } from "react"; | ||
| import Link from "next/link"; | ||
| import MessagePage from "../ui/layout/message-page"; | ||
| import { useRouter } from "next/navigation"; | ||
|
|
||
| export default function Page() { | ||
| return <div>FORGOTPASSWORD</div>; | ||
| const [email, setEmail] = useState(""); | ||
| const [emailSent, setEmailSent] = useState(false); | ||
| const router = useRouter(); | ||
|
|
||
| const handleSubmit = (e: React.FormEvent) => { | ||
| e.preventDefault(); | ||
|
|
||
| if (!email) { | ||
| alert("Please enter an email address."); | ||
| return; | ||
| } | ||
| setEmailSent(true); | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="flex h-screen items-center justify-center"> | ||
| {emailSent ? ( | ||
| <MessagePage | ||
| title="Check your email" | ||
| description={`A password reset link was sent to ${email}.`} | ||
| buttons={[ | ||
| { | ||
| type: "primary", | ||
| label: "back to login", | ||
| onClick: () => router.push("/login"), | ||
| }, | ||
| ]} | ||
| /> | ||
| ) : ( | ||
| <form | ||
| onSubmit={handleSubmit} | ||
| className="flex w-80 flex-col items-center" | ||
| > | ||
| {/* Title */} | ||
| <h1 className="font-display mb-4 block text-center text-5xl leading-none text-lion md:text-8xl"> | ||
| reset password | ||
| </h1> | ||
|
|
||
| {/* Email */} | ||
| <input | ||
| type="email" | ||
| placeholder="Email" | ||
| value={email} | ||
| onChange={(e) => setEmail(e.target.value)} | ||
| className="mb-4 w-full rounded-full border px-4 py-2 focus:ring-2 focus:outline-none" | ||
| /> | ||
|
|
||
| <div className="flex w-full items-center justify-between"> | ||
| {/* Forgot Password */} | ||
| <Link href="/login" className="mb-8 text-xs"> | ||
| Remembered password? | ||
| </Link> | ||
|
|
||
| {/* Email Button */} | ||
| <button | ||
| type="submit" | ||
| className="mb-2 cursor-pointer gap-2 rounded-full bg-blue px-4 py-2 font-medium transition" | ||
| > | ||
| send reset link | ||
| </button> | ||
| </div> | ||
| </form> | ||
| )} | ||
| </div> | ||
| ); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| "use client"; | ||
|
|
||
| import { useRouter, useSearchParams } from "next/navigation"; | ||
| import React, { useState } from "react"; | ||
|
|
||
| export default function Page() { | ||
| const [newPassword, setNewPassword] = useState(""); | ||
| const [confirmPassword, setConfirmPassword] = useState(""); | ||
| const router = useRouter(); | ||
|
|
||
| const searchParams = useSearchParams(); | ||
| const pwdResetToken = searchParams.get("token"); | ||
|
|
||
| const handleSubmit = (e: React.FormEvent) => { | ||
| e.preventDefault(); | ||
|
|
||
| if (!pwdResetToken) { | ||
| alert("Invalid or missing password reset token."); | ||
| return; | ||
| } | ||
|
|
||
| if (!newPassword || !confirmPassword) { | ||
| alert("Please fill in all fields."); | ||
| return; | ||
| } | ||
|
|
||
| // TODO: Replace with real password reset API call | ||
| if (newPassword !== confirmPassword) { | ||
| alert("Passwords do not match."); | ||
| } else { | ||
| router.push("/reset-password/success"); | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="flex h-screen items-center justify-center"> | ||
| <form onSubmit={handleSubmit} className="flex w-80 flex-col items-center"> | ||
| {/* Title */} | ||
| <h1 className="font-display mb-4 block text-center text-5xl leading-none text-lion md:text-8xl"> | ||
| reset password | ||
| </h1> | ||
|
|
||
| {/* New Password */} | ||
| <input | ||
| type="password" | ||
| placeholder="New Password" | ||
| value={newPassword} | ||
| onChange={(e) => setNewPassword(e.target.value)} | ||
| className="mb-4 w-full rounded-full border px-4 py-2 focus:ring-2 focus:outline-none" | ||
| /> | ||
|
|
||
| {/* Confirm Password */} | ||
| <input | ||
| type="password" | ||
| placeholder="Confirm Password" | ||
| value={confirmPassword} | ||
| onChange={(e) => setConfirmPassword(e.target.value)} | ||
| className="mb-4 w-full rounded-full border px-4 py-2 focus:ring-2 focus:outline-none" | ||
| /> | ||
|
|
||
| {/* Change Password Button */} | ||
| <div className="flex w-full"> | ||
| <button | ||
| type="submit" | ||
| className="mb-2 ml-auto cursor-pointer gap-2 rounded-full bg-blue px-4 py-2 font-medium transition" | ||
| > | ||
| reset password | ||
| </button> | ||
| </div> | ||
| </form> | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| "use client"; | ||
|
|
||
| import { useRouter } from "next/navigation"; | ||
| import MessagePage from "../../ui/layout/message-page"; | ||
|
|
||
| export default function Page() { | ||
| const router = useRouter(); | ||
|
|
||
| return ( | ||
| <div className="flex h-screen items-center justify-center"> | ||
| <MessagePage | ||
| title="Password Reset Successful" | ||
| buttons={[ | ||
| { | ||
| type: "primary", | ||
| label: "back to login", | ||
| onClick: () => router.push("/login"), | ||
| }, | ||
| ]} | ||
| /> | ||
| </div> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| "use client"; | ||
|
|
||
| import { useRouter } from "next/navigation"; | ||
| import { useEffect, useRef } from "react"; | ||
| import MessagePage from "../../ui/layout/message-page"; | ||
|
|
||
| export default function Page() { | ||
| const router = useRouter(); | ||
| const email = sessionStorage.getItem("sign_up_email"); | ||
| const lastEmailResend = useRef(Date.now()); | ||
|
|
||
| useEffect(() => { | ||
| if (!email) { | ||
| // the user shouldn't be here | ||
| router.push("/login"); | ||
| } | ||
| // clear the email from storage | ||
| sessionStorage.removeItem("sign_up_email"); | ||
| }, []); | ||
jzgom067 marked this conversation as resolved.
Show resolved
Hide resolved
jzgom067 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| if (!email) { | ||
| // stop rendering if there's no email | ||
| return null; | ||
| } | ||
|
|
||
| const handleResendEmail = () => { | ||
| const emailResendCooldown = 30000; // 30 seconds | ||
| let timeLeft = | ||
| (emailResendCooldown - (Date.now() - lastEmailResend.current)) / 1000; | ||
| timeLeft = Math.ceil(timeLeft); | ||
| if (timeLeft > 0) { | ||
| alert(`Slow down! ${timeLeft} seconds until you can send again.`); | ||
| return; | ||
| } | ||
| // TODO: Replace with real resend email API logic | ||
| console.log("Resending email to:", email); | ||
| lastEmailResend.current = Date.now(); | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="flex h-screen items-center justify-center"> | ||
| <MessagePage | ||
| title="Check your email" | ||
| description={`A verification link was sent to ${email}.`} | ||
| buttons={[ | ||
| { | ||
| type: "secondary", | ||
| label: "resend email", | ||
| onClick: handleResendEmail, | ||
| }, | ||
| { | ||
| type: "primary", | ||
| label: "go to login", | ||
| onClick: () => router.push("/login"), | ||
| }, | ||
| ]} | ||
| /> | ||
| </div> | ||
| ); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| enum ButtonTypeEnum { | ||
| primary = "primary", | ||
| secondary = "secondary", | ||
| } | ||
| type ButtonType = keyof typeof ButtonTypeEnum; | ||
|
|
||
| type ButtonData = { type: ButtonType; label: string; onClick: () => void }; | ||
|
|
||
| type MessagePageProps = { | ||
| title: string; | ||
| description?: string; | ||
| buttons: ButtonData[]; | ||
| }; | ||
|
|
||
| export default function MessagePage({ | ||
| title, | ||
| description, | ||
| buttons, | ||
| }: MessagePageProps) { | ||
| return ( | ||
| <div className="text-center"> | ||
| <h2 className="mb-4 text-4xl font-bold">{title}</h2> | ||
| {description && <p className="mb-4">{description}</p>} | ||
| <div className="flex justify-center gap-4"> | ||
| {buttons.map((button, index) => ( | ||
| <button | ||
| key={index} | ||
jzgom067 marked this conversation as resolved.
Show resolved
Hide resolved
jzgom067 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| type="button" | ||
jzgom067 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| onClick={button.onClick} | ||
| className={`mb-2 cursor-pointer rounded-full px-4 py-2 font-medium transition ${ | ||
| button.type === "primary" | ||
| ? "bg-blue dark:bg-red" | ||
| : "border border-2 border-blue hover:bg-blue-100 dark:border-red dark:hover:bg-red/25" | ||
jzgom067 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }`} | ||
| > | ||
| {button.label} | ||
| </button> | ||
| ))} | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| "use client"; | ||
|
|
||
| import { useRouter, useSearchParams } from "next/navigation"; | ||
| import { useEffect, useState } from "react"; | ||
| import MessagePage from "../ui/layout/message-page"; | ||
|
|
||
| export default function Page() { | ||
| const [verifying, setVerifying] = useState(true); | ||
| const [emailVerified, setEmailVerified] = useState(false); | ||
| const router = useRouter(); | ||
|
|
||
| const searchParams = useSearchParams(); | ||
| const token = searchParams.get("code"); | ||
|
|
||
| useEffect(() => { | ||
| const verifyEmail = async () => { | ||
| // simulate network delay | ||
| await new Promise((resolve) => setTimeout(resolve, 1000)); | ||
|
|
||
| if (!token) { | ||
| setVerifying(false); | ||
| setEmailVerified(false); | ||
| return; | ||
| } | ||
|
|
||
| // TODO: Replace with an actual API call | ||
| setVerifying(false); | ||
| setEmailVerified(true); | ||
| }; | ||
|
|
||
| verifyEmail(); | ||
| }, [token]); | ||
|
|
||
| return ( | ||
| <div className="flex h-screen items-center justify-center"> | ||
| {verifying ? ( | ||
| <div className="text-center"> | ||
| <h2 className="mb-6">Verifying...</h2> | ||
| </div> | ||
| ) : emailVerified ? ( | ||
| <MessagePage | ||
| title="Email Verified" | ||
| description="Welcome to Plancake!" | ||
| buttons={[ | ||
| { | ||
| type: "primary", | ||
| label: "go to login", | ||
| onClick: () => router.push("/login"), | ||
| }, | ||
| ]} | ||
| /> | ||
| ) : ( | ||
| <MessagePage | ||
| title="Failed to Verify Email" | ||
| description="This link is invalid or has expired." | ||
| buttons={[ | ||
| { | ||
| type: "secondary", | ||
| label: "back to sign up", | ||
| onClick: () => router.push("/sign-up"), | ||
| }, | ||
| ]} | ||
| /> | ||
| )} | ||
| </div> | ||
| ); | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.