Aller au contenu principal

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 state
  • Navbar: Shared navigation component
  • Link, useNavigate: React Router components for navigation
  • PasswordInput: Custom component for password input with show/hide functionality
  • validateEmail: Utility function for email validation
  • axiosInstance: 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 input
  • password: Stores the user's password input
  • error: Stores error messages to display to the user
  • navigate: 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

  1. Prevent default form submission: e.preventDefault() stops page reload
  2. Client-side validation: Check email format and password presence
  3. Clear previous errors: Reset error state before new attempt
  4. API call: Send credentials to /login endpoint
  5. Success handling: Store token and navigate to dashboard
  6. Error handling: Display server or generic error messages

Key Concepts

  • async/await: Modern JavaScript syntax for handling asynchronous operations
  • localStorage.setItem(): Stores authentication token in browser storage
  • navigate("/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

  1. Additional validation: Checks for name field
  2. Different endpoint: Calls /create-account instead of /login
  3. Field mapping: Maps name to fullName in API request
  4. 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 optional placeholder
  • 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

  1. Navigate to signup: User clicks "Create an Account" link
  2. Fill form: Enter name, email, and password
  3. Client validation: Check required fields and email format
  4. API call: Send data to /create-account endpoint
  5. Success: Store token and redirect to dashboard
  6. Error: Display error message and allow retry

Existing User Login

  1. Navigate to login: User visits login page or clicks login link
  2. Enter credentials: Provide email and password
  3. Client validation: Verify email format and password presence
  4. API call: Send credentials to /login endpoint
  5. Success: Store token and redirect to dashboard
  6. 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