This commit is contained in:
Iliyan Angelov
2025-11-16 15:12:43 +02:00
parent 824eec6190
commit 93d4c1df80
54 changed files with 1606 additions and 1612 deletions

View File

@@ -1,15 +1,15 @@
# useAuthStore - Zustand Authentication Store
## ✅ Hoàn thành Chức năng 3
## ✅ Function 3 Completed
### 📦 Files đã tạo:
### 📦 Files Created:
1. **`src/store/useAuthStore.ts`** - Zustand store quản lý auth
2. **`src/services/api/apiClient.ts`** - Axios client với interceptors
1. **`src/store/useAuthStore.ts`** - Zustand store managing auth
2. **`src/services/api/apiClient.ts`** - Axios client with interceptors
3. **`src/services/api/authService.ts`** - Auth API service
4. **`.env.example`** - Template cho environment variables
4. **`.env.example`** - Template for environment variables
### 🎯 Tính năng đã implement:
### 🎯 Features Implemented:
#### State Management:
```typescript
@@ -24,19 +24,19 @@ interface AuthState {
```
#### Actions:
-`login(credentials)` - Đăng nhập
-`register(data)` - Đăng ký tài khoản mới
-`logout()` - Đăng xuất
-`setUser(user)` - Cập nhật thông tin user
-`refreshAuthToken()` - Làm mới token
-`forgotPassword(data)` - Quên mật khẩu
-`resetPassword(data)` - Đặt lại mật khẩu
-`initializeAuth()` - Khởi tạo auth từ localStorage
-`clearError()` - Xóa error message
-`login(credentials)` - Login
-`register(data)` - Register new account
-`logout()` - Logout
-`setUser(user)` - Update user information
-`refreshAuthToken()` - Refresh token
-`forgotPassword(data)` - Forgot password
-`resetPassword(data)` - Reset password
-`initializeAuth()` - Initialize auth from localStorage
-`clearError()` - Clear error message
### 📝 Cách sử dụng:
### 📝 Usage:
#### 1. Khởi tạo trong App.tsx:
#### 1. Initialize in App.tsx:
```typescript
import useAuthStore from './store/useAuthStore';
@@ -56,7 +56,7 @@ function App() {
}
```
#### 2. Sử dụng trong Login Form:
#### 2. Use in Login Form:
```typescript
import useAuthStore from '../store/useAuthStore';
@@ -67,9 +67,9 @@ const LoginPage = () => {
const handleSubmit = async (data) => {
try {
await login(data);
navigate('/dashboard'); // Redirect sau khi login
navigate('/dashboard'); // Redirect after login
} catch (error) {
// Error đã được xử lý bởi store
// Error has been handled by store
}
};
@@ -78,14 +78,14 @@ const LoginPage = () => {
{/* Form fields */}
{error && <div>{error}</div>}
<button disabled={isLoading}>
{isLoading ? 'Đang xử lý...' : 'Đăng nhập'}
{isLoading ? 'Processing...' : 'Login'}
</button>
</form>
);
};
```
#### 3. Sử dụng trong Register Form:
#### 3. Use in Register Form:
```typescript
const RegisterPage = () => {
const { register, isLoading } = useAuthStore();
@@ -94,9 +94,9 @@ const RegisterPage = () => {
const handleSubmit = async (data) => {
try {
await register(data);
navigate('/login'); // Redirect về login
navigate('/login'); // Redirect to login
} catch (error) {
// Error được hiển thị qua toast
// Error displayed via toast
}
};
@@ -111,21 +111,21 @@ const Header = () => {
const handleLogout = async () => {
await logout();
// Auto redirect về login nếu cần
// Auto redirect to login if needed
};
return <button onClick={handleLogout}>Đăng xuất</button>;
return <button onClick={handleLogout}>Logout</button>;
};
```
#### 5. Hiển thị thông tin user:
#### 5. Display user information:
```typescript
const Profile = () => {
const { userInfo } = useAuthStore();
return (
<div>
<h1>Xin chào, {userInfo?.name}</h1>
<h1>Hello, {userInfo?.name}</h1>
<p>Email: {userInfo?.email}</p>
<p>Role: {userInfo?.role}</p>
</div>
@@ -135,68 +135,68 @@ const Profile = () => {
### 🔐 LocalStorage Persistence:
Store tự động lưu và đọc từ localStorage:
Store automatically saves and reads from localStorage:
- `token` - JWT access token
- `refreshToken` - JWT refresh token
- `userInfo` - Thông tin user
- `userInfo` - User information
Khi reload page, auth state được khôi phục tự động qua `initializeAuth()`.
When page reloads, auth state is automatically restored via `initializeAuth()`.
### 🌐 API Integration:
#### Base URL Configuration:
Tạo file `.env` trong thư mục `client/`:
Create `.env` file in `client/` directory:
```env
VITE_API_URL=http://localhost:3000
VITE_ENV=development
```
#### API Endpoints được sử dụng:
- `POST /api/auth/login` - Đăng nhập
- `POST /api/auth/register` - Đăng ký
- `POST /api/auth/logout` - Đăng xuất
- `GET /api/auth/profile` - Lấy profile
#### API Endpoints Used:
- `POST /api/auth/login` - Login
- `POST /api/auth/register` - Register
- `POST /api/auth/logout` - Logout
- `GET /api/auth/profile` - Get profile
- `POST /api/auth/refresh-token` - Refresh token
- `POST /api/auth/forgot-password` - Quên mật khẩu
- `POST /api/auth/reset-password` - Đặt lại mật khẩu
- `POST /api/auth/forgot-password` - Forgot password
- `POST /api/auth/reset-password` - Reset password
### 🛡️ Security Features:
1. **Auto Token Injection**:
- Axios interceptor tự động thêm token o headers
- Axios interceptor automatically adds token to headers
```typescript
Authorization: Bearer <token>
```
2. **Auto Logout on 401**:
- Khi token hết hạn (401), tự động logout redirect về login
- When token expires (401), automatically logout and redirect to login
3. **Token Refresh**:
- Có thể refresh token khi sắp hết hạn
- Can refresh token when about to expire
4. **Password Hashing**:
- Backend xử lý bcrypt hashing
- Backend handles bcrypt hashing
### 📱 Toast Notifications:
Store tự động hiển thị toast cho các events:
- ✅ Login thành công
- ✅ Đăng ký thành công
Store automatically displays toast for events:
- ✅ Login successful
- ✅ Registration successful
- ✅ Logout
- ❌ Login thất bại
- ❌ Đăng ký thất bại
- ❌ Login failed
- ❌ Registration failed
- ❌ API errors
### 🔄 Component Updates:
#### ProtectedRoute:
```typescript
// TRƯỚC (với props)
// BEFORE (with props)
<ProtectedRoute isAuthenticated={isAuthenticated}>
<Dashboard />
</ProtectedRoute>
// SAU (tự động lấy từ store)
// AFTER (automatically gets from store)
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
@@ -204,19 +204,19 @@ Store tự động hiển thị toast cho các events:
#### AdminRoute:
```typescript
// TRƯỚC (với props)
// BEFORE (with props)
<AdminRoute userInfo={userInfo}>
<AdminPanel />
</AdminRoute>
// SAU (tự động lấy từ store)
// AFTER (automatically gets from store)
<AdminRoute>
<AdminPanel />
</AdminRoute>
```
#### LayoutMain:
Vẫn nhận props từ App.tsx để hiển thị Header/Navbar:
Still receives props from App.tsx to display Header/Navbar:
```typescript
<LayoutMain
isAuthenticated={isAuthenticated}
@@ -227,44 +227,44 @@ Vẫn nhận props từ App.tsx để hiển thị Header/Navbar:
### 🧪 Testing:
Để test authentication flow:
To test authentication flow:
1. **Tạo file `.env`**:
1. **Create `.env` file**:
```bash
cp .env.example .env
```
2. **Ensure backend đang chạy**:
2. **Ensure backend is running**:
```bash
cd server
npm run dev
```
3. **Chạy frontend**:
3. **Run frontend**:
```bash
cd client
npm run dev
```
4. **Test flow**:
- Truy cập `/register` → Đăng ký tài khoản
- Truy cập `/login` → Đăng nhập
- Truy cập `/dashboard` → Xem dashboard (protected)
- Click logout → Xóa session
- Reload page → Auth state được khôi phục
- Access `/register` → Register account
- Access `/login` → Login
- Access `/dashboard` → View dashboard (protected)
- Click logout → Clear session
- Reload page → Auth state restored
### 🚀 Next Steps:
**Chức năng 4: Form Login**
- Tạo LoginPage với React Hook Form + Yup
- Tích hợp với useAuthStore
**Function 4: Login Form**
- Create LoginPage with React Hook Form + Yup
- Integrate with useAuthStore
- UX enhancements (loading, show/hide password, remember me)
**Chức năng 5: Form Register**
- Tạo RegisterPage với validation
- Tích hợp với useAuthStore
**Function 5: Register Form**
- Create RegisterPage with validation
- Integrate with useAuthStore
**Chức năng 6-7: Password Reset Flow**
**Function 6-7: Password Reset Flow**
- ForgotPasswordPage
- ResetPasswordPage
@@ -295,11 +295,11 @@ interface UserInfo {
}
```
### ✅ Kết quả đạt được:
### ✅ Results Achieved:
1.Toàn bộ thông tin user được quản lý tập trung
2.Duy trì đăng nhập sau khi reload trang
3.Dễ dàng truy cập userInfo trong mọi component
1.All user information managed centrally
2.Maintain login after page reload
3.Easy access to userInfo in any component
4. ✅ Auto token management
5. ✅ Type-safe với TypeScript
6. ✅ Clean code, dễ maintain
5. ✅ Type-safe with TypeScript
6. ✅ Clean code, easy to maintain