Authentication Pages
Overview
The authentication pages handle user registration and login functionality in the Notes App. These pages provide the user interface for creating accounts and signing into the application, managing the complete authentication flow from user input to successful login.
What are Authentication Pages?
Authentication pages are user interface components that:
- Collect user credentials (email, password, name)
- Validate input data before sending to the server
- Communicate with the backend to verify or create accounts
- Handle authentication tokens for maintaining user sessions
- Provide user feedback through error messages and navigation
Login Page
File: frontend/notes-app/src/pages/Login/Login.jsx
The Login page allows existing users to access their accounts by providing email and password credentials.
Component Structure
import React, { useState } from 'react'
import Navbar from '../../components/Navbar/Navbar'
import { Link, useNavigate } from 'react-router-dom';
import PasswordInput from '../../components/Input/PasswordInput';
import { validateEmail } from '../../utils/helper';
import axiosInstance from '../../utils/axiosInstance';
Import Breakdown
useState
: React hook for managing component stateNavbar
: Shared navigation componentLink, useNavigate
: React Router components for navigationPasswordInput
: Custom component for password input with show/hide functionalityvalidateEmail
: Utility function for email validationaxiosInstance
: Configured HTTP client for API calls
State Management
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState(null);
const navigate = useNavigate();
State Variables Explained
email
: Stores the user's email inputpassword
: Stores the user's password inputerror
: Stores error messages to display to the usernavigate
: Function to programmatically change routes
Login Handler Function
const handleLogin = async (e) => {
e.preventDefault();
if (!validateEmail(email)) {
setError("Please enter a valid email address.");
return;
}
if (!password) {
setError("Please enter the password")
return;
}
setError("");
try {
const response = await axiosInstance.post("/login", {
email: email,
password: password
});
if (response.data && response.data.accessToken) {
localStorage.setItem("token", response.data.accessToken);
navigate("/dashboard");
}
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
setError(error.response.data.message);
} else {
setError("An unexpected error occurred. Please try again.");
}
}
};
Login Flow Breakdown
- Prevent default form submission:
e.preventDefault()
stops page reload - Client-side validation: Check email format and password presence
- Clear previous errors: Reset error state before new attempt
- API call: Send credentials to
/login
endpoint - Success handling: Store token and navigate to dashboard
- Error handling: Display server or generic error messages
Key Concepts
async/await
: Modern JavaScript syntax for handling asynchronous operationslocalStorage.setItem()
: Stores authentication token in browser storagenavigate("/dashboard")
: Redirects user to main application- Error response structure: Checks for nested error properties
User Interface
return (
<>
<Navbar />
<div className="flex items-center justify-center mt-28">
<div className="w-96 border rounded bg-white px-7 py-10">
<form onSubmit={handleLogin}>
<h4 className="text-2xl mb-7">Login</h4>
<input type="text"
placeholder="Email"
className="input-box"
value={email}
onChange={e => setEmail(e.target.value)}
/>
<PasswordInput
value={password}
onChange={(e)=> setPassword(e.target.value)}
/>
{error && <p className="text-red-500 text-xs pb-1">{error}</p>}
<button type="submit" className="btn-primary">
Login
</button>
<p className="text-sm text-center mt-4">
Not registered yet?{" "}
<Link to="/signUp" className="font-medium text-primary underline">
Create an Account
</Link>
</p>
</form>
</div>
</div>
</>
);
UI Features
- Centered layout: Flexbox centering for form container
- Controlled inputs: Input values controlled by React state
- Conditional error display: Shows errors only when they exist
- Navigation link: Link to signup page for new users
SignUp Page
File: frontend/notes-app/src/pages/SignUp/SignUp.jsx
The SignUp page allows new users to create accounts by providing their name, email, and password.
State Management
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState(null);
const navigate = useNavigate();
The signup page manages an additional state variable for the user's name.
SignUp Handler Function
const handleSignUp = async(e) => {
e.preventDefault();
if(!name){
setError("Please enter your name");
return;
}
if(!validateEmail(email)){
setError("Please enter a valid email address.");
return;
}
if(!password){
setError("Please enter the password")
return;
}
setError("");
try {
const response = await axiosInstance.post("/create-account", {
fullName: name,
email: email,
password: password
});
if (response.data && response.data.error) {
setError(response.data.message);
return;
}
if(response.data && response.data.accessToken){
localStorage.setItem("token", response.data.accessToken);
navigate("/dashboard");
}
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
setError(error.response.data.message);
} else {
setError("An unexpected error occurred. Please try again.");
}
}
};
SignUp Flow Differences
- Additional validation: Checks for name field
- Different endpoint: Calls
/create-account
instead of/login
- Field mapping: Maps
name
tofullName
in API request - Success response handling: Checks for error flag in successful responses
Shared Components
PasswordInput Component
File: frontend/notes-app/src/components/Input/PasswordInput.jsx
A reusable component that provides password input with show/hide functionality.
const PasswordInput = ({value, onChange, placeholder}) => {
const [isShowPassword, setIsShowPassword] = useState(false)
const toggleShowPassword = () => {
setIsShowPassword(!isShowPassword)
}
return (
<div className="flex items-center bg-transparent border-[1.5px] px-5 rounded mb-3">
<input
value={value}
onChange={onChange}
type={isShowPassword ? "text":"password"}
placeholder={placeholder || "Password"}
className="w-full text-sm bg-transparent py-3 rounded outline-none"
/>
{isShowPassword ? (
<FaRegEye
size={22}
className="text-primary cursor-pointer"
onClick={()=> toggleShowPassword()}
/>
): (
<FaRegEyeSlash
size={22}
className="text-slate-400 cursor-pointer"
onClick={()=> toggleShowPassword()}
/>
)}
</div>
);
};
Component Features
- Props interface: Accepts
value
,onChange
, and optionalplaceholder
- Toggle functionality: Switches between password and text input types
- Visual feedback: Different icons for show/hide states
- Accessibility: Clickable icons with cursor pointer
Toast Component
File: frontend/notes-app/src/components/ToastMessage/Toast.jsx
A notification component for displaying temporary messages to users.
const Toast = ({ isShown, message, type, onClose }) => {
useEffect(() => {
const timeoutId = setTimeout(() => {
onClose();
}, 3000);
return () => {
clearTimeout(timeoutId);
};
}, [onClose]);
return (
<div
className={`absolute top-20 right-6 transition-all duration-400 ${
isShown ? "opacity-100" : "opacity-0"
}`}
>
<div
className={`min-w-52 bg-white border shadow-2xl rounded-md after:w-[5px] after:h-full ${
type === "delete" ? "after:bg-red-500" : "after:bg-green-500"
} after:absolute after:left-0 after:top-0 after:rounded-l-lg`}
>
<div className="flex items-center gap-3 py-2 px-4">
<div
className={`w-10 h-10 flex items-center justify-center rounded-full ${
type === "delete" ? "bg-red-50" : "bg-green-50"
}`}
>
{type === "delete" ? (
<MdDeleteOutline className="text-xl" />
) : (
<LuCheck className="text-xl text-green-500" />
)}
</div>
<p className="text-sm text-slate-800">{message}</p>
</div>
</div>
</div>
);
};
Toast Features
- Auto-dismiss: Automatically closes after 3 seconds using
useEffect
- Type-based styling: Different colors and icons for success/delete messages
- Smooth transitions: CSS transitions for show/hide animations
- Cleanup: Clears timeout on component unmount to prevent memory leaks
User Experience Flow
New User Registration
- Navigate to signup: User clicks "Create an Account" link
- Fill form: Enter name, email, and password
- Client validation: Check required fields and email format
- API call: Send data to
/create-account
endpoint - Success: Store token and redirect to dashboard
- Error: Display error message and allow retry
Existing User Login
- Navigate to login: User visits login page or clicks login link
- Enter credentials: Provide email and password
- Client validation: Verify email format and password presence
- API call: Send credentials to
/login
endpoint - Success: Store token and redirect to dashboard
- Error: Display error message for invalid credentials
Security Considerations
Client-Side Validation
- Email format validation: Prevents obviously invalid emails
- Required field checks: Ensures all necessary data is provided
- Immediate feedback: Shows errors without server round-trip
Token Management
- Secure storage: Tokens stored in localStorage for persistence
- Automatic inclusion: Axios interceptor adds tokens to requests
- Navigation control: Successful auth redirects to protected areas
Connection to Other Components
Backend Integration
- API endpoints: Communicates with
/login
and/create-account
- Token handling: Receives and stores JWT tokens
- Error handling: Processes server error responses
Frontend Navigation
- React Router: Uses navigation hooks for page transitions
- Protected routes: Successful auth leads to dashboard access
- Cross-page links: Login and signup pages link to each other
Shared Components
- Navbar: Common navigation across auth pages
- PasswordInput: Reusable password field with show/hide
- Toast notifications: User feedback for various operations