Files
Hotel-Booking/docs/LOGIN_FORM_GUIDE.md
Iliyan Angelov 93d4c1df80 update
2025-11-16 15:12:43 +02:00

9.5 KiB

Function 4: Login Form - Usage Guide

📋 Overview

Login form has been fully implemented with:

  • Form validation with React Hook Form + Yup
  • Show/hide password
  • "Remember me" checkbox (7 days)
  • Loading state during login process
  • Display errors from server
  • Redirect after successful login
  • Beautiful UI with Tailwind CSS and Lucide Icons
  • Responsive design

🗂️ Files Created/Updated

1. LoginPage.tsx - Login form component

Path: client/src/pages/auth/LoginPage.tsx

// Main features:
- React Hook Form with Yup validation
- Show/hide password toggle
- Remember me checkbox
- Loading state with spinner
- Error handling
- Redirect with location state

2. index.ts - Export module

Path: client/src/pages/auth/index.ts

export { default as LoginPage } from './LoginPage';

3. App.tsx - Routing updated

Path: client/src/App.tsx

// Added:
import { LoginPage } from './pages/auth';

// Route:
<Route path="/login" element={<LoginPage />} />

🎨 UI Structure

Layout

┌─────────────────────────────────────┐
│   🏨 Hotel Icon                     │
│   Login                             │
│   Welcome back...                   │
├─────────────────────────────────────┤
│  ┌───────────────────────────────┐  │
│  │ [Error message if any]        │  │
│  ├───────────────────────────────┤  │
│  │ Email                         │  │
│  │ [📧 email@example.com       ] │  │
│  ├───────────────────────────────┤  │
│  │ Password                      │  │
│  │ [🔒 ••••••••            👁️] │  │
│  ├───────────────────────────────┤  │
│  │ ☑️ Remember me                │  │
│  │              Forgot password? → │  │
│  ├───────────────────────────────┤  │
│  │      [🔐 Login]               │  │
│  └───────────────────────────────┘  │
│  Don't have an account? Sign up now │
│                                     │
│  Terms & Privacy Policy             │
└─────────────────────────────────────┘

🔧 Usage

1. Access Form

# URL
http://localhost:5173/login

2. Form Fields

Field Type Required Validation
Email text Valid email
Password password Min 8 characters
Remember Me checkbox Boolean

3. Validation Rules

Email:

- Required: "Email is required"
- Valid email format: "Invalid email format"
- Trim whitespace

Password:

- Required: "Password is required"
- Min 8 characters: "Password must be at least 8 characters"

4. Login Flow

1. User enters email + password
2. Click "Login"
3. Form validation (client-side)
4. If valid:
   - Button disabled + show loading
   - Call useAuthStore.login()
   - API POST /api/auth/login
5. If successful:
   - Save token to localStorage
   - Update Zustand state
   - Redirect to /dashboard
6. If error:
   - Display error message
   - Button enabled again

🎯 Main Features

1. Show/Hide Password

const [showPassword, setShowPassword] = useState(false);

// Toggle button
<button onClick={() => setShowPassword(!showPassword)}>
  {showPassword ? <EyeOff /> : <Eye />}
</button>

// Input type
<input type={showPassword ? 'text' : 'password'} />

2. Remember Me (7 days)

// Checkbox
<input {...register('rememberMe')} type="checkbox" />

// Logic in authService.login()
if (rememberMe) {
  // Token will be saved in localStorage
  // and won't be deleted when closing browser
}

3. Loading State

// Button disabled when loading
<button disabled={isLoading}>
  {isLoading ? (
    <>
      <Loader2 className="animate-spin" />
      Processing...
    </>
  ) : (
    <>
      <LogIn />
      Login
    </>
  )}
</button>

4. Error Handling

// Error from Zustand store
const { error } = useAuthStore();

// Display error message
{error && (
  <div className="bg-red-50 border border-red-200">
    {error}
  </div>
)}

5. Redirect Logic

// Get location state from ProtectedRoute
const location = useLocation();

// Redirect to previous page or dashboard
const from = location.state?.from?.pathname || '/dashboard';
navigate(from, { replace: true });

🔗 Integration with Zustand Store

// Hook usage
const { 
  login,      // Function to login
  isLoading,  // Loading state
  error,      // Error message
  clearError  // Clear error
} = useAuthStore();

// Login call
await login({
  email: 'user@example.com',
  password: 'password123',
  rememberMe: true
});

🎨 Styling with Tailwind

Color Scheme

- Primary: blue-600, blue-700
- Background: gradient from-blue-50 to-indigo-100
- Error: red-50, red-200, red-600, red-700
- Text: gray-600, gray-700, gray-900

Responsive Design

// Container
className="max-w-md w-full"  // Max width 28rem

// Grid (if any)
className="grid grid-cols-1 md:grid-cols-2"

🧪 Testing Scenarios

1. Validation Testing

Test Case 1: Empty form

- Input: Submit empty form
- Expected: Display error "Email is required"

Test Case 2: Invalid email

- Input: Email = "notanemail"
- Expected: "Invalid email format"

Test Case 3: Short password

- Input: Password = "123"
- Expected: "Password must be at least 8 characters"

2. Authentication Testing

Test Case 4: Valid credentials

- Input: Valid email + password
- Expected: Redirect to /dashboard

Test Case 5: Invalid credentials

- Input: Wrong password
- Expected: Error message from server

Test Case 6: Network error

- Input: Server offline
- Expected: Error message "An error occurred"

3. UX Testing

Test Case 7: Show/hide password

- Action: Click eye icon
- Expected: Password text visible/hidden

Test Case 8: Remember me

- Action: Check "Remember me"
- Expected: Token persists after reload

Test Case 9: Loading state

- Action: Submit form
- Expected: Button disabled, spinner displayed

🔐 Security Features

1. Password Visibility

// Default: password hidden
type="password"

// Toggle: user control
onClick={() => setShowPassword(!showPassword)}

2. HTTPS Only (Production)

// In .env
VITE_API_URL=https://api.yourdomain.com

3. Token Storage

// LocalStorage for remember me
if (rememberMe) {
  localStorage.setItem('token', token);
}

// SessionStorage for session only
else {
  sessionStorage.setItem('token', token);
}

📝 Best Practices

1. Form Validation

 Client-side validation (Yup)
 Server-side validation (Express validator)
 Immediate feedback
 Clear error messages

2. Error Handling

 Try-catch blocks
 User-friendly messages
 Clear error state
 Console logging for debugging

3. UX

 Loading indicators
 Disabled states
 Auto-focus first field
 Enter key submit
 Remember form state

🚀 Next Steps (Function 5-7)

  1. Function 5: Register Form

    • Copy structure from LoginPage
    • Add fields: name, phone, confirmPassword
    • Use registerSchema
    • Redirect to /login after success
  2. Function 6: Forgot Password

    • Simple form with email only
    • Send reset link
    • Success message
  3. Function 7: Reset Password

    • Form with password + confirmPassword
    • Token from URL params
    • Redirect to /login after success

🐛 Troubleshooting

Issue 1: "Error: Token expired"

Solution: Check token expiry time
- Access token: 1 hour
- Refresh token: 7 days

Issue 2: Form doesn't submit

Solution: Check console for validation errors
- Open DevTools > Console
- Look for Yup validation errors

Issue 3: Redirect doesn't work

Solution: Check location state
console.log(location.state?.from);

Issue 4: Remember me doesn't work

Solution: Check localStorage
- Open DevTools > Application > Local Storage
- Check "token" and "refreshToken" keys

📚 Resources

Checklist

  • Create validationSchemas.ts
  • Create LoginPage.tsx
  • Add route to App.tsx
  • Email validation
  • Password validation
  • Show/hide password
  • Remember me checkbox
  • Loading state
  • Error display
  • Redirect after login
  • Responsive design
  • Icons integration
  • E2E testing

Status: Function 4 completed Next: Function 5 - Register Form