0% found this document useful (0 votes)
9 views5 pages

AdminUserCreatePage J

The AdminUserCreatePage component allows administrators to create new users by filling out a form with fields such as username, email, password, and role. It fetches roles and blood types from a user service and validates the input data before submission. Upon successful creation, it navigates back to the user list and displays success or error messages as needed.

Uploaded by

nttuu254
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views5 pages

AdminUserCreatePage J

The AdminUserCreatePage component allows administrators to create new users by filling out a form with fields such as username, email, password, and role. It fetches roles and blood types from a user service and validates the input data before submission. Upon successful creation, it navigates back to the user list and displays success or error messages as needed.

Uploaded by

nttuu254
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

// src/pages/admin/AdminUserCreatePage.

jsx
import React, { useState, useEffect } from 'react';
import { useNavigate, Link } from 'react-router-dom';
import toast from 'react-hot-toast';
import { ArrowLeft, UserPlus } from 'lucide-react';

import userService from '../../services/userService'; //


import InputField from '../../components/common/InputField'; //
import Button from '../../components/common/Button'; //
import LoadingSpinner from '../../components/common/LoadingSpinner'; //

const AdminUserCreatePage = () => {


const navigate = useNavigate();
const [formData, setFormData] = useState({
username: '',
email: '',
fullName: '',
password: '',
confirmPassword: '',
roleName: 'Member', // Default role
bloodTypeId: '',
phone: '',
status: 'Active', // Default status
emailVerified: false,
phoneVerified: false,
});
const [roles, setRoles] = useState([]);
const [bloodTypes, setBloodTypes] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [errors, setErrors] = useState({});

useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
try {
const rolesData = await userService.getRoles();
setRoles(rolesData || []); //
const bloodTypesData = await userService.getBloodTypes();
setBloodTypes(bloodTypesData || []);
} catch (error) {
toast.error("Lỗi khi tải dữ liệu Roles hoặc Blood Types: " +
error.message);
}
setIsLoading(false);
};
fetchData();
}, []);

const handleInputChange = (e) => {


const { name, value, type, checked } = e.target;
setFormData(prev => ({
...prev,
[name]: type === 'checkbox' ? checked : value,
}));
if (errors[name]) {
setErrors(prev => ({ ...prev, [name]: null }));
}
};
const validateForm = () => {
const newErrors = {};
if (!formData.username.trim()) newErrors.username = "Tên đăng nhập không
được để trống.";
else if (formData.username.length < 3) newErrors.username = "Tên đăng nhập
phải có ít nhất 3 ký tự.";
if (!formData.email.trim()) newErrors.email = "Email không được để trống.";
else if (!/\S+@\S+\.\S+/.test(formData.email)) newErrors.email = "Email
không hợp lệ.";
if (!formData.fullName.trim()) newErrors.fullName = "Họ tên không được để
trống.";
if (!formData.password) newErrors.password = "Mật khẩu không được để
trống.";
else if (formData.password.length < 6) newErrors.password = "Mật khẩu phải
có ít nhất 6 ký tự.";
if (formData.password !== formData.confirmPassword)
newErrors.confirmPassword = "Mật khẩu xác nhận không khớp.";
if (!formData.roleName) newErrors.roleName = "Vai trò không được để
trống.";

setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};

const uniqueBloodTypes = bloodTypes.filter((value, index, self) =>


index === self.findIndex((t) => (
t.bloodGroup === value.bloodGroup
))
);

const handleSubmit = async (e) => {


e.preventDefault();
if (!validateForm()) {
toast.error("Vui lòng kiểm tra lại các trường thông tin.");
return;
}
setIsLoading(true);
const toastId = toast.loading("Đang tạo người dùng...");

const requestData = {
...formData,
phone: formData.phone.trim() || null,
description: formData.description.trim() || null,
bloodTypeId: formData.bloodTypeId ? parseInt(formData.bloodTypeId,
10) : null,
};
delete requestData.confirmPassword; // Không gửi confirmPassword lên server

try {
await userService.createUserByAdmin(requestData); //
toast.success("Tạo người dùng thành công!", { id: toastId });
navigate('/admin/users');
} catch (error) {
toast.error(`Lỗi khi tạo người dùng: ${error.message || 'Vui lòng thử
lại.'}`, { id: toastId });
// Kiểm tra lỗi từ server để hiển thị cụ thể hơn nếu có
if (error.response && error.response.data && typeof error.response.data
=== 'object') {
const serverErrors = {};
for (const key in error.response.data) {
serverErrors[key] = error.response.data[key];
}
setErrors(prev => ({ ...prev, ...serverErrors }));
}
} finally {
setIsLoading(false);
}
};

if (isLoading && roles.length === 0) { // Chỉ hiển thị loading ban đầu
return <div className="flex justify-center items-center h-
64"><LoadingSpinner size="12" /></div>;
}

return (
<div className="p-6 max-w-4xl mx-auto">
<Link to="/admin/users" className="flex items-center text-red-600
hover:text-red-800 mb-4">
<ArrowLeft size={20} className="mr-2" />
Quay lại danh sách
</Link>
<h1 className="text-2xl font-bold text-gray-800 mb-6">Tạo Người dùng
mới</h1>
<form onSubmit={handleSubmit} className="bg-white p-8 rounded-lg
shadow-md space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<InputField label="Tên đăng nhập" id="username" name="username"
value={formData.username} onChange={handleInputChange} required
error={errors.username} disabled={isLoading} />
<InputField label="Email" id="email" name="email" type="email"
value={formData.email} onChange={handleInputChange} required error={errors.email}
disabled={isLoading} />
</div>
<InputField label="Họ và tên đầy đủ" id="fullName" name="fullName"
value={formData.fullName} onChange={handleInputChange} required
error={errors.fullName} disabled={isLoading} />
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<InputField label="Mật khẩu" id="password" name="password"
type="password" value={formData.password} onChange={handleInputChange} required
error={errors.password} disabled={isLoading} />
<InputField label="Xác nhận mật khẩu" id="confirmPassword"
name="confirmPassword" type="password" value={formData.confirmPassword}
onChange={handleInputChange} required error={errors.confirmPassword}
disabled={isLoading} />
</div>
<InputField label="Số điện thoại (Tùy chọn)" id="phone"
name="phone" type="tel" value={formData.phone} onChange={handleInputChange}
error={errors.phone} disabled={isLoading} />

<div className="grid grid-cols-1 md:grid-cols-2 gap-6">


<div>
<label htmlFor="roleName" className="block text-sm font-
medium text-gray-700 mb-1">Vai trò {<span
className="text-red-500">*</span>}</label>
<select id="roleName" name="roleName"
value={formData.roleName} onChange={handleInputChange} disabled={isLoading ||
roles.length === 0} required
className={`block w-full px-3 py-2 border rounded-md
shadow-sm focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm $
{errors.roleName ? 'border-red-500' : 'border-gray-300'}`}>
{roles.map(role => <option key={role.name}
value={role.name}>{role.name} ({role.description})</option>)}
</select>
{errors.roleName && <p className="mt-1 text-xs text-red-
600">{errors.roleName}</p>}
</div>
<div>
<label htmlFor="status" className="block text-sm font-
medium text-gray-700 mb-1">Trạng thái</label>
<select id="status" name="status" value={formData.status}
onChange={handleInputChange} disabled={isLoading}
className="block w-full px-3 py-2 border border-gray-
300 rounded-md shadow-sm focus:outline-none focus:ring-red-500 focus:border-red-500
sm:text-sm">
<option value="Active">Active</option>
<option value="Suspended">Suspended</option>
<option value="Pending">Pending</option>
</select>
</div>
</div>

{/* <div>
<label htmlFor="bloodTypeId" className="block text-sm font-
medium text-gray-700 mb-1">Nhóm máu (Tùy chọn)</label>
<select id="bloodTypeId" name="bloodTypeId"
value={formData.bloodTypeId} onChange={handleInputChange} disabled={isLoading ||
bloodTypes.length === 0}
className="block w-full px-3 py-2 border border-gray-300
rounded-md shadow-sm focus:outline-none focus:ring-red-500 focus:border-red-500
sm:text-sm">
<option value="">-- Chọn nhóm máu --</option>
{bloodTypes.map(bt => <option key={bt.id}
value={bt.id}>{bt.bloodGroup}</option>)}
</select>
</div> */}

<select id="bloodTypeId" name="bloodTypeId"


value={formData.bloodTypeId} onChange={handleInputChange} disabled={isLoading ||
uniqueBloodTypes.length === 0}
className="block w-full px-3 py-2 border border-gray-300
rounded-md shadow-sm focus:outline-none focus:ring-red-500 focus:border-red-500
sm:text-sm">
<option value="">-- Chọn nhóm máu --</option>
{uniqueBloodTypes.map(bt => <option key={bt.id}
value={bt.id}>{bt.bloodGroup}</option>)}
</select>

<div className="flex items-center space-x-8">


<div className="flex items-center">
<input id="emailVerified" name="emailVerified"
type="checkbox" checked={formData.emailVerified} onChange={handleInputChange}
disabled={isLoading} className="h-4 w-4 text-red-600 focus:ring-red-500 border-
gray-300 rounded" />
<label htmlFor="emailVerified" className="ml-2 block text-
sm text-gray-900">Email đã xác thực</label>
</div>
<div className="flex items-center">
<input id="phoneVerified" name="phoneVerified"
type="checkbox" checked={formData.phoneVerified} onChange={handleInputChange}
disabled={isLoading} className="h-4 w-4 text-red-600 focus:ring-red-500 border-
gray-300 rounded" />
<label htmlFor="phoneVerified" className="ml-2 block text-
sm text-gray-900">SĐT đã xác thực</label>
</div>
</div>

<div className="flex justify-end space-x-3">


<Link to="/admin/users">
<Button type="button" variant="secondary"
disabled={isLoading}>
Hủy
</Button>
</Link>
<Button type="submit" variant="primary" disabled={isLoading}>
{isLoading ? <LoadingSpinner size="5" color="white"
className="mr-2" /> : <UserPlus size={18} className="mr-2" />}
{isLoading ? 'Đang lưu...' : 'Tạo người dùng'}
</Button>
</div>
</form>
</div>
);
};

export default AdminUserCreatePage;

You might also like