[DDD] Thiết kế Chi tiết Trang Đăng ký
Tóm tắt tài liệu Tài liệu này mô tả thiết kế kỹ thuật chi tiết cho Trang Đăng ký (Register Page). Đây là bước cuối cùng của quy trình đăng ký, nơi người dùng nhập các thông tin cá nhân cuối cùng như họ tên và mật khẩu để hoàn tất việc tạo tài khoản.
1. Tổng quan
1.1. Bối cảnh và Vấn đề
Sau khi xác minh số điện thoại bằng OTP, người dùng cần cung cấp các thông tin cơ bản còn lại để tạo hồ sơ. Trang này cung cấp một biểu mẫu đơn giản để thu thập họ tên và mật khẩu, hoàn thiện quá trình đăng ký.
1.2. Mục tiêu & Phi mục tiêu (Goals and Non-Goals)
Mục tiêu (Goals)
- Cung cấp một biểu mẫu để người dùng nhập họ tên và mật khẩu.
- Có chức năng ẩn/hiện mật khẩu để cải thiện trải nghiệm người dùng.
- Sử dụng
ZodvàReact Hook Formđể xác thực các trường (họ tên, độ dài mật khẩu, mật khẩu khớp nhau). - Gửi tất cả thông tin (SĐT từ bước trước, họ tên, mật khẩu) đến API để tạo tài khoản mới.
- Điều hướng người dùng đến trang đăng nhập sau khi đăng ký thành công.
Phi mục tiêu (Non-Goals)
- Tải lên ảnh đại diện hoặc các thông tin hồ sơ chi tiết khác (việc này sẽ được thực hiện sau khi đăng nhập).
- Đăng nhập tự động sau khi đăng ký.
2. Kiến trúc Tổng thể
3. Thiết kế Chi tiết (Detailed Design)
3.1. Thiết kế Giao diện & Luồng người dùng (UI & User Flow)
Các thành phần giao diện sử dụng
Input: Trường nhập liệu (họ, tên, mật khẩu…)Button: Nút "Đăng ký"
Luồng người dùng
-
Sau khi người dùng nhập mã OTP thành công, họ sẽ được tự động chuyển đến trang đăng ký tài khoản.
- Đường dẫn trình duyệt sẽ có sẵn số điện thoại (ví dụ:
/register/09xxxxxxxx), giúp hệ thống biết người dùng nào đang đăng ký.
- Đường dẫn trình duyệt sẽ có sẵn số điện thoại (ví dụ:
-
Trên giao diện trang đăng ký, người dùng sẽ thấy các ô để nhập:
- Họ
- Tên
- Mật khẩu
- Nhập lại mật khẩu
-
Người dùng nhập đầy đủ thông tin vào các ô trên.
-
Khi nhấn nút "Đăng ký":
- Hệ thống sẽ kiểm tra thông tin:
- Nếu có lỗi (ví dụ: mật khẩu quá ngắn, nhập lại không khớp), hệ thống sẽ báo lỗi ngay bên dưới ô tương ứng.
- Nếu mọi thông tin hợp lệ → hệ thống sẽ tiến hành xử lý.
- Hệ thống sẽ kiểm tra thông tin:
-
Số điện thoại đã xác minh sẽ được tự động lấy từ đường dẫn và gửi cùng với các thông tin đăng ký.
-
Trong thời gian xử lý:
- Nút "Đăng ký" sẽ bị khóa (người dùng không thể nhấn lại).
- Hiển thị trạng thái “đang xử lý...”.
-
Kết quả xử lý:
- Thành công:
Người dùng sẽ được chuyển đến trang đăng nhập để tiếp tục sử dụng hệ thống. - Thất bại:
Nếu có lỗi chung (ví dụ: số điện thoại đã được sử dụng), một thông báo lỗi tổng quát sẽ hiển thị trên giao diện để người dùng biết và thử lại.
- Thành công:
3.2. Luồng Tương tác (Interaction Flow)
3.3. Quy tắc kiểm tra mật khẩu
Dưới đây là danh sách các quy tắc được áp dụng khi người dùng nhập mật khẩu. Mỗi quy tắc có một id, một hàm test, và một thông báo lỗi quốc tế hóa (message).
const passwordRules = [
{
id: 'minLength',
test: (v: string) => !!v && v.length >= 8,
message: t('toast.form.passwordMinimumLength'),
},
{
id: 'uppercase',
test: (v: string) => !!v && /[A-Z]/.test(v),
message: t('toast.form.passwordUppercase'),
},
{
id: 'lowercase',
test: (v: string) => !!v && /[a-z]/.test(v),
message: t('toast.form.passwordLowercase'),
},
{
id: 'number',
test: (v: string) => !!v && /\d/.test(v),
message: t('toast.form.passwordNumber'),
},
{
id: 'special',
test: (v: string) => !!v && /[^A-Za-z0-9]/.test(v),
message: t('toast.form.passwordSpecial'),
},
{
id: 'noLeadingTrailingSpaces',
test: (v: string) => !!v && v.trim() === v,
message: t('toast.form.passwordNoLeadingTrailingSpaces'),
},
];
Mô tả từng quy tắc
id | Mô tả chi tiết |
|---|---|
minLength | Mật khẩu phải có ít nhất 8 ký tự. |
uppercase | Mật khẩu phải chứa ít nhất 1 chữ cái viết hoa (A-Z). |
lowercase | Mật khẩu phải chứa ít nhất 1 chữ cái viết thường (a-z). |
number | Mật khẩu phải chứa ít nhất 1 chữ số (0-9). |
special | Mật khẩu phải chứa ít nhất 1 ký tự đặc biệt (ví dụ: !@#$%^&*). |
noLeadingTrailingSpaces | Mật khẩu không được có khoảng trắng ở đầu hoặc cuối. |
Ghi chú:
messagelà khóa quốc tế hóa (i18n) tương ứng để hiển thị thông báo lỗi cho người dùng.
3.4. Thiết kế API (API Design)
Endpoint: POST /auth/api/v1/register
Request Body:
{
"phone_number": "+84901234567",
"given_name": "Nguyễn",
"family_name": "Văn A",
"password": "secure_password_123",
"username": "nguyen.vana",
"role": "end_user"
}
Response (Success - 201 Created):
{
"success": true,
"message": "Account registration successful",
"data": {
"UserConfirmed": false,
"CodeDeliveryDetails": {
"Destination": "+***0092",
"DeliveryMedium": "SMS",
"AttributeName": "phone_number"
},
"UserSub": "f97a85**-****-****-****-********6a45",
"ResponseMetadata": {
"RequestId": "041a5f**-****-****-****-********65ca",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"date": "Fri, 25 Jul 2025 03:11:13 GMT",
"content-type": "application/x-amz-json-1.1",
"content-length": "1198",
"connection": "keep-alive",
"x-amzn-requestid": "041a5f**-****-****-****-********65ca"
},
"RetryAttempts": 0
}
}
}
Response (Error):
- 400 Bad Request: Nếu dữ liệu không hợp lệ.
- 409 Conflict: Nếu SĐT (hoặc một trường unique khác) đã tồn tại.
4. Yêu cầu Phi chức năng
4.1. Bảo mật (Security)
- Mật khẩu không bao giờ được lưu trữ dưới dạng văn bản thuần. Backend phải sử dụng một thuật toán băm mạnh (ví dụ: Bcrypt, Argon2) để băm mật khẩu trước khi lưu vào cơ sở dữ liệu.
4.2. Trải nghiệm người dùng (UX)
- Phản hồi rõ ràng: Việc vô hiệu hóa nút và thay đổi văn bản trong khi chờ phản hồi từ API cho người dùng biết rằng hành động của họ đang được xử lý.
- Liên kết điều hướng: Cung cấp liên kết quay lại trang đăng nhập cho những người dùng đã vô tình truy cập trang này.
5. Rủi ro & Giảm thiểu
| Rủi ro | Mức độ ảnh hưởng | Khả năng xảy ra | Phương án giảm thiểu |
|---|---|---|---|
| Người dùng tạo nhiều tài khoản spam | Trung bình | Trung bình | Ngoài việc xác minh qua SMS, có thể thêm CAPTCHA vào biểu mẫu đăng ký để ngăn chặn bot. |
| Lỗi không mong muốn trong quá trình đăng ký | Trung bình | Thấp | Ghi log chi tiết ở cả client và server. Hiển thị một mã lỗi (error ID) cho người dùng để họ có thể báo cáo lại cho bộ phận hỗ trợ. |
Tài liệu tham khảo: