-
Notifications
You must be signed in to change notification settings - Fork 93
UI Improvements: Add Forgot Password & Social Icons + Fix Pricing Card Hover VisibilityFeature/scroll faq #324
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
Changes from 5 commits
0680910
d0541bf
ce728f4
3d932a3
fc91546
08eafee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,204 @@ | ||||||||||||||||||||||||||||||||||||||||
| import { useState } from "react"; | ||||||||||||||||||||||||||||||||||||||||
| import { useNavigate } from "react-router-dom"; | ||||||||||||||||||||||||||||||||||||||||
| import SEO from "../components/SEO"; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| export default function ForgotPassword() { | ||||||||||||||||||||||||||||||||||||||||
| const [email, setEmail] = useState(""); | ||||||||||||||||||||||||||||||||||||||||
| const [loading, setLoading] = useState(false); | ||||||||||||||||||||||||||||||||||||||||
| const [message, setMessage] = useState(""); | ||||||||||||||||||||||||||||||||||||||||
| const [error, setError] = useState(""); | ||||||||||||||||||||||||||||||||||||||||
| const [emailError, setEmailError] = useState(""); | ||||||||||||||||||||||||||||||||||||||||
| const navigate = useNavigate(); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Email validation regex | ||||||||||||||||||||||||||||||||||||||||
| const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const validateEmail = (emailValue) => { | ||||||||||||||||||||||||||||||||||||||||
| if (!emailValue) { | ||||||||||||||||||||||||||||||||||||||||
| setEmailError(""); | ||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| if (!emailRegex.test(emailValue)) { | ||||||||||||||||||||||||||||||||||||||||
| setEmailError("Please enter a valid email address"); | ||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| setEmailError(""); | ||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const handleEmailChange = (e) => { | ||||||||||||||||||||||||||||||||||||||||
| const value = e.target.value; | ||||||||||||||||||||||||||||||||||||||||
| setEmail(value); | ||||||||||||||||||||||||||||||||||||||||
| if (value) { | ||||||||||||||||||||||||||||||||||||||||
| validateEmail(value); | ||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||
| setEmailError(""); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const handleEmailBlur = () => { | ||||||||||||||||||||||||||||||||||||||||
| if (email) { | ||||||||||||||||||||||||||||||||||||||||
| validateEmail(email); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| const handleSendOTP = async (e) => { | ||||||||||||||||||||||||||||||||||||||||
| e.preventDefault(); | ||||||||||||||||||||||||||||||||||||||||
| setError(""); | ||||||||||||||||||||||||||||||||||||||||
| setMessage(""); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Validate email | ||||||||||||||||||||||||||||||||||||||||
| if (!validateEmail(email)) { | ||||||||||||||||||||||||||||||||||||||||
| setError("Please enter a valid email address"); | ||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| setLoading(true); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||
| // TODO: Implement actual OTP sending logic here | ||||||||||||||||||||||||||||||||||||||||
| // Example API call: | ||||||||||||||||||||||||||||||||||||||||
| // const response = await fetch('/api/auth/forgot-password', { | ||||||||||||||||||||||||||||||||||||||||
| // method: 'POST', | ||||||||||||||||||||||||||||||||||||||||
| // headers: { 'Content-Type': 'application/json' }, | ||||||||||||||||||||||||||||||||||||||||
| // body: JSON.stringify({ email }) | ||||||||||||||||||||||||||||||||||||||||
| // }); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| // Simulated success for now | ||||||||||||||||||||||||||||||||||||||||
| setTimeout(() => { | ||||||||||||||||||||||||||||||||||||||||
| setLoading(false); | ||||||||||||||||||||||||||||||||||||||||
| setMessage("OTP sent successfully! Please check your email."); | ||||||||||||||||||||||||||||||||||||||||
| }, 1500); | ||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
| } catch { | |
| } catch (err) { | |
| console.error("Failed to send OTP:", err); |
Copilot
AI
Feb 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rendering 800 div elements for the grid background is inefficient and can impact performance. Consider using CSS gradients or pseudo-elements to create the grid pattern instead, which would be much more performant. For example, you could use background-image: repeating-linear-gradient() or a single div with a background pattern.
| <div className="absolute inset-0 grid grid-cols-[repeat(auto-fill,minmax(60px,1fr))] grid-rows-[repeat(auto-fill,minmax(60px,1fr))] pointer-events-auto"> | |
| {Array.from({ length: 800 }).map((_, i) => ( | |
| <div | |
| key={i} | |
| className=" | |
| border border-white/5 | |
| transition-colors duration-90 ease-out | |
| hover:bg-[#10b981] | |
| " | |
| /> | |
| ))} | |
| </div> | |
| <div | |
| className="absolute inset-0 pointer-events-none" | |
| style={{ | |
| backgroundImage: | |
| "repeating-linear-gradient(to right, rgba(255,255,255,0.05) 0 1px, transparent 1px 60px), repeating-linear-gradient(to bottom, rgba(255,255,255,0.05) 0 1px, transparent 1px 60px)", | |
| }} | |
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Lenis smooth scrolling is being initialized globally in App.jsx and will run on every page, including pages where it might conflict with existing scroll behavior (e.g., dashboard, interview room, settings pages). The useEffect dependency array is empty, meaning it will only initialize once on mount and won't respond to route changes. Consider either:
The Landing and PricingPage already initialize their own Lenis instances, which could lead to duplicate initialization conflicts.