487 lines
12 KiB
Markdown
487 lines
12 KiB
Markdown
# Function 5: Register Form - Completed ✅
|
|
|
|
## 📦 Files Created/Updated
|
|
|
|
### 1. **RegisterPage.tsx** - Register form component
|
|
**Path:** `client/src/pages/auth/RegisterPage.tsx`
|
|
|
|
### 2. **index.ts** - Export module
|
|
**Path:** `client/src/pages/auth/index.ts`
|
|
- Added export RegisterPage
|
|
|
|
### 3. **App.tsx** - Routing updated
|
|
**Path:** `client/src/App.tsx`
|
|
- Added route `/register`
|
|
|
|
## ✨ Main Features
|
|
|
|
### 1. Form Fields (5 fields)
|
|
✅ **Full Name** (name)
|
|
- Required, 2-50 characters
|
|
- Icon: User
|
|
- Placeholder: "John Doe"
|
|
|
|
✅ **Email**
|
|
- Required, valid email format
|
|
- Icon: Mail
|
|
- Placeholder: "email@example.com"
|
|
|
|
✅ **Phone Number** (phone) - Optional
|
|
- 10-11 digits
|
|
- Icon: Phone
|
|
- Placeholder: "0123456789"
|
|
|
|
✅ **Password** (password)
|
|
- Required, min 8 chars
|
|
- Must contain: uppercase, lowercase, number, special char
|
|
- Show/hide toggle with Eye icon
|
|
- Icon: Lock
|
|
|
|
✅ **Confirm Password** (confirmPassword)
|
|
- Must match password
|
|
- Show/hide toggle with Eye icon
|
|
- Icon: Lock
|
|
|
|
### 2. Password Strength Indicator
|
|
✅ **Visual Progress Bar** with 5 levels:
|
|
1. 🔴 Very weak (0/5)
|
|
2. 🟠 Weak (1/5)
|
|
3. 🟡 Medium (2/5)
|
|
4. 🔵 Strong (3/5)
|
|
5. 🟢 Very strong (5/5)
|
|
|
|
✅ **Real-time Requirements Checker:**
|
|
- ✅/❌ At least 8 characters
|
|
- ✅/❌ Lowercase (a-z)
|
|
- ✅/❌ Uppercase (A-Z)
|
|
- ✅/❌ Number (0-9)
|
|
- ✅/❌ Special character (@$!%*?&)
|
|
|
|
### 3. Validation Rules (Yup Schema)
|
|
|
|
```typescript
|
|
name:
|
|
- Required: "Full name is required"
|
|
- Min 2 chars: "Full name must be at least 2 characters"
|
|
- Max 50 chars: "Full name must not exceed 50 characters"
|
|
- Trim whitespace
|
|
|
|
email:
|
|
- Required: "Email is required"
|
|
- Valid format: "Invalid email format"
|
|
- Trim whitespace
|
|
|
|
phone (optional):
|
|
- Pattern /^[0-9]{10,11}$/
|
|
- Error: "Invalid phone number"
|
|
|
|
password:
|
|
- Required: "Password is required"
|
|
- Min 8 chars
|
|
- Pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])/
|
|
- Error: "Password must contain uppercase, lowercase, number and special characters"
|
|
|
|
confirmPassword:
|
|
- Required: "Please confirm password"
|
|
- Must match password: "Passwords do not match"
|
|
```
|
|
|
|
### 4. UX Features
|
|
|
|
✅ **Loading State**
|
|
```tsx
|
|
{isLoading ? (
|
|
<>
|
|
<Loader2 className="animate-spin" />
|
|
Processing...
|
|
</>
|
|
) : (
|
|
<>
|
|
<UserPlus />
|
|
Register
|
|
</>
|
|
)}
|
|
```
|
|
|
|
✅ **Show/Hide Password** (2 toggles)
|
|
- Eye/EyeOff icons
|
|
- Separate toggle for password and confirmPassword
|
|
- Visual feedback on hover
|
|
|
|
✅ **Error Display**
|
|
- Inline validation errors under each field
|
|
- Global error message at top of form
|
|
- Red border for fields with errors
|
|
|
|
✅ **Success Flow**
|
|
```typescript
|
|
1. Submit form
|
|
2. Validation passes
|
|
3. Call useAuthStore.register()
|
|
4. Show toast: "Registration successful! Please login."
|
|
5. Navigate to /login
|
|
```
|
|
|
|
### 5. Design & Styling
|
|
|
|
**Color Scheme:**
|
|
- Primary: purple-600, purple-700
|
|
- Background: gradient from-purple-50 to-pink-100
|
|
- Success: green-500, green-600
|
|
- Error: red-50, red-200, red-600
|
|
- Text: gray-600, gray-700, gray-900
|
|
|
|
**Layout:**
|
|
```
|
|
┌─────────────────────────────────────┐
|
|
│ 🏨 Hotel Icon (Purple) │
|
|
│ Register Account │
|
|
│ Create a new account to book... │
|
|
├─────────────────────────────────────┤
|
|
│ ┌───────────────────────────────┐ │
|
|
│ │ [Error message if any] │ │
|
|
│ ├───────────────────────────────┤ │
|
|
│ │ Full Name │ │
|
|
│ │ [👤 John Doe ] │ │
|
|
│ ├───────────────────────────────┤ │
|
|
│ │ Email │ │
|
|
│ │ [📧 email@example.com ] │ │
|
|
│ ├───────────────────────────────┤ │
|
|
│ │ Phone Number (Optional) │ │
|
|
│ │ [📱 0123456789 ] │ │
|
|
│ ├───────────────────────────────┤ │
|
|
│ │ Password │ │
|
|
│ │ [🔒 •••••••• 👁️] │ │
|
|
│ │ ▓▓▓▓▓░░░░░ Very strong │ │
|
|
│ │ ✅ At least 8 characters │ │
|
|
│ │ ✅ Lowercase (a-z) │ │
|
|
│ │ ✅ Uppercase (A-Z) │ │
|
|
│ │ ✅ Number (0-9) │ │
|
|
│ │ ✅ Special character │ │
|
|
│ ├───────────────────────────────┤ │
|
|
│ │ Confirm Password │ │
|
|
│ │ [🔒 •••••••• 👁️] │ │
|
|
│ ├───────────────────────────────┤ │
|
|
│ │ [👤 Register] │ │
|
|
│ └───────────────────────────────┘ │
|
|
│ Already have an account? Login now │
|
|
│ │
|
|
│ Terms & Privacy Policy │
|
|
└─────────────────────────────────────┘
|
|
```
|
|
|
|
## 🔗 Integration
|
|
|
|
### API Endpoint
|
|
```
|
|
POST /api/auth/register
|
|
```
|
|
|
|
### Request Body
|
|
```typescript
|
|
{
|
|
name: string; // "John Doe"
|
|
email: string; // "user@example.com"
|
|
password: string; // "Password123@"
|
|
phone?: string; // "0123456789" (optional)
|
|
}
|
|
```
|
|
|
|
### Response (Success)
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"message": "User registered successfully",
|
|
"data": {
|
|
"user": {
|
|
"id": 1,
|
|
"name": "John Doe",
|
|
"email": "user@example.com",
|
|
"phone": "0123456789",
|
|
"role": "customer"
|
|
},
|
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
}
|
|
}
|
|
```
|
|
|
|
### useAuthStore Integration
|
|
```typescript
|
|
const { register: registerUser, isLoading, error, clearError } =
|
|
useAuthStore();
|
|
|
|
await registerUser({
|
|
name: data.name,
|
|
email: data.email,
|
|
password: data.password,
|
|
phone: data.phone,
|
|
});
|
|
|
|
// After success:
|
|
navigate('/login', { replace: true });
|
|
```
|
|
|
|
## 🧪 Test Scenarios
|
|
|
|
### 1. Validation Tests
|
|
|
|
**Test Case 1: Empty form**
|
|
```
|
|
Action: Submit empty form
|
|
Expected: Show validation errors for name, email, password
|
|
```
|
|
|
|
**Test Case 2: Invalid email**
|
|
```
|
|
Input: email = "notanemail"
|
|
Expected: "Invalid email format"
|
|
```
|
|
|
|
**Test Case 3: Short name**
|
|
```
|
|
Input: name = "A"
|
|
Expected: "Full name must be at least 2 characters"
|
|
```
|
|
|
|
**Test Case 4: Weak password**
|
|
```
|
|
Input: password = "abc123"
|
|
Expected: "Password must contain uppercase, lowercase, number and special characters"
|
|
Password strength: Weak/Medium
|
|
```
|
|
|
|
**Test Case 5: Password mismatch**
|
|
```
|
|
Input:
|
|
password = "Password123@"
|
|
confirmPassword = "Password456@"
|
|
Expected: "Passwords do not match"
|
|
```
|
|
|
|
**Test Case 6: Invalid phone**
|
|
```
|
|
Input: phone = "123"
|
|
Expected: "Invalid phone number"
|
|
```
|
|
|
|
### 2. UX Tests
|
|
|
|
**Test Case 7: Password strength indicator**
|
|
```
|
|
Input: Type password character by character
|
|
Expected:
|
|
- Progress bar animates
|
|
- Color changes: red → orange → yellow → blue → green
|
|
- Checkmarks appear as requirements met
|
|
```
|
|
|
|
**Test Case 8: Show/hide password**
|
|
```
|
|
Action: Click eye icon on password field
|
|
Expected: Password text becomes visible/hidden
|
|
Action: Click eye icon on confirmPassword field
|
|
Expected: Confirm password text becomes visible/hidden
|
|
```
|
|
|
|
**Test Case 9: Loading state**
|
|
```
|
|
Action: Submit valid form
|
|
Expected:
|
|
- Button disabled
|
|
- Spinner shows
|
|
- Text changes to "Processing..."
|
|
```
|
|
|
|
### 3. Integration Tests
|
|
|
|
**Test Case 10: Successful registration**
|
|
```
|
|
Input: All valid data
|
|
Expected:
|
|
1. API POST /api/auth/register called
|
|
2. Toast: "Registration successful! Please login."
|
|
3. Redirect to /login
|
|
```
|
|
|
|
**Test Case 11: Email already exists**
|
|
```
|
|
Input: email = "existing@example.com"
|
|
Expected:
|
|
- Error message: "Email already registered"
|
|
- Toast error displayed
|
|
- Form remains on page
|
|
```
|
|
|
|
**Test Case 12: Network error**
|
|
```
|
|
Scenario: Server offline
|
|
Expected:
|
|
- Error message: "Registration failed. Please try again."
|
|
- Toast error displayed
|
|
```
|
|
|
|
## 📊 Password Strength Algorithm
|
|
|
|
```typescript
|
|
function getPasswordStrength(pwd: string) {
|
|
let strength = 0;
|
|
|
|
if (pwd.length >= 8) strength++; // +1
|
|
if (/[a-z]/.test(pwd)) strength++; // +1
|
|
if (/[A-Z]/.test(pwd)) strength++; // +1
|
|
if (/\d/.test(pwd)) strength++; // +1
|
|
if (/[@$!%*?&]/.test(pwd)) strength++; // +1
|
|
|
|
return {
|
|
strength: 0-5,
|
|
label: ['Very weak', 'Weak', 'Medium', 'Strong', 'Very strong'][strength],
|
|
color: ['bg-red-500', 'bg-orange-500', 'bg-yellow-500', 'bg-blue-500', 'bg-green-500'][strength]
|
|
};
|
|
}
|
|
```
|
|
|
|
## 🎨 Component Structure
|
|
|
|
```tsx
|
|
RegisterPage/
|
|
├── Header Section
|
|
│ ├── Hotel Icon (purple)
|
|
│ ├── Title: "Register Account"
|
|
│ └── Subtitle
|
|
│
|
|
├── Form Container (white card)
|
|
│ ├── Error Alert (conditional)
|
|
│ ├── Name Input
|
|
│ ├── Email Input
|
|
│ ├── Phone Input (optional)
|
|
│ ├── Password Input
|
|
│ │ ├── Show/Hide Toggle
|
|
│ │ ├── Strength Indicator
|
|
│ │ └── Requirements Checklist
|
|
│ ├── Confirm Password Input
|
|
│ │ └── Show/Hide Toggle
|
|
│ └── Submit Button (with loading)
|
|
│
|
|
├── Login Link
|
|
│ └── "Already have an account? Login now"
|
|
│
|
|
└── Footer Links
|
|
├── Terms of Service
|
|
└── Privacy Policy
|
|
```
|
|
|
|
## 🔐 Security Features
|
|
|
|
### 1. Password Validation
|
|
- Min 8 characters
|
|
- Requires: uppercase, lowercase, number, special char
|
|
- Visual feedback for strength
|
|
|
|
### 2. Confirm Password
|
|
- Must match original password
|
|
- Prevents typos
|
|
|
|
### 3. Client-side Validation
|
|
- Immediate feedback
|
|
- Prevents invalid API calls
|
|
- Better UX
|
|
|
|
### 4. Server-side Validation
|
|
- Backend also validates all fields
|
|
- Checks email uniqueness
|
|
- Password hashed with bcrypt
|
|
|
|
## 📝 Code Quality
|
|
|
|
✅ **TypeScript**: Full type safety
|
|
✅ **React Hook Form**: Optimized re-renders
|
|
✅ **Yup Validation**: Schema-based validation
|
|
✅ **Component Composition**: Reusable PasswordRequirement component
|
|
✅ **Accessibility**: Proper labels, IDs, autocomplete
|
|
✅ **Error Handling**: Try-catch, user-friendly messages
|
|
✅ **Loading States**: Visual feedback during async operations
|
|
✅ **Responsive Design**: Works on mobile and desktop
|
|
✅ **80 chars/line**: Code formatting standard
|
|
|
|
## 🚀 Usage
|
|
|
|
### Navigate to Register Page
|
|
```bash
|
|
http://localhost:5173/register
|
|
```
|
|
|
|
### Example Registration
|
|
```typescript
|
|
Name: "John Doe"
|
|
Email: "nguyenvana@example.com"
|
|
Phone: "0123456789"
|
|
Password: "Password123@"
|
|
Confirm: "Password123@"
|
|
|
|
Submit → Success → Redirect to /login
|
|
```
|
|
|
|
## 🔄 Flow Diagram
|
|
|
|
```
|
|
User visits /register
|
|
↓
|
|
Fill in form fields
|
|
↓
|
|
Real-time validation (Yup)
|
|
↓
|
|
Password strength updates live
|
|
↓
|
|
Submit button clicked
|
|
↓
|
|
Frontend validation passes
|
|
↓
|
|
Call useAuthStore.register()
|
|
↓
|
|
API POST /api/auth/register
|
|
↓
|
|
┌───────┴───────┐
|
|
↓ ↓
|
|
Success Failure
|
|
↓ ↓
|
|
Toast success Toast error
|
|
↓ ↓
|
|
Navigate Stay on page
|
|
to /login Show errors
|
|
```
|
|
|
|
## ✅ Checklist
|
|
|
|
- [x] ✅ Create RegisterPage.tsx component
|
|
- [x] ✅ Implement React Hook Form
|
|
- [x] ✅ Add Yup validation schema
|
|
- [x] ✅ Add 5 form fields (name, email, phone, password, confirmPassword)
|
|
- [x] ✅ Show/hide password toggle (2 fields)
|
|
- [x] ✅ Password strength indicator
|
|
- [x] ✅ Real-time requirements checker
|
|
- [x] ✅ Loading state
|
|
- [x] ✅ Error display (inline + global)
|
|
- [x] ✅ Integration with useAuthStore
|
|
- [x] ✅ Redirect to /login after success
|
|
- [x] ✅ Toast notifications
|
|
- [x] ✅ Add route to App.tsx
|
|
- [x] ✅ Responsive design
|
|
- [x] ✅ Purple color scheme
|
|
- [x] ✅ Icons integration (Lucide React)
|
|
- [x] ✅ Terms & Privacy links
|
|
|
|
## 📚 Related Files
|
|
|
|
- `client/src/pages/auth/LoginPage.tsx` - Login form (same design pattern)
|
|
- `client/src/utils/validationSchemas.ts` - Validation schemas
|
|
- `client/src/store/useAuthStore.ts` - Auth state management
|
|
- `client/src/services/api/authService.ts` - API calls
|
|
- `client/src/App.tsx` - Route configuration
|
|
|
|
---
|
|
|
|
**Status:** ✅ Function 5 completed
|
|
**Next:** Function 6 - Forgot Password
|
|
**Test URL:** http://localhost:5173/register
|