mirror of
https://github.com/samanhappy/mcphub.git
synced 2025-12-30 21:49:13 -05:00
154 lines
4.9 KiB
TypeScript
154 lines
4.9 KiB
TypeScript
import { useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useUserData } from '@/hooks/useUserData';
|
|
import { UserFormData } from '@/types';
|
|
|
|
interface AddUserFormProps {
|
|
onAdd: () => void;
|
|
onCancel: () => void;
|
|
}
|
|
|
|
const AddUserForm = ({ onAdd, onCancel }: AddUserFormProps) => {
|
|
const { t } = useTranslation();
|
|
const { createUser } = useUserData();
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
|
|
const [formData, setFormData] = useState<UserFormData>({
|
|
username: '',
|
|
password: '',
|
|
isAdmin: false,
|
|
});
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setError(null);
|
|
|
|
if (!formData.username.trim()) {
|
|
setError(t('users.usernameRequired'));
|
|
return;
|
|
}
|
|
|
|
if (!formData.password.trim()) {
|
|
setError(t('users.passwordRequired'));
|
|
return;
|
|
}
|
|
|
|
if (formData.password.length < 6) {
|
|
setError(t('users.passwordTooShort'));
|
|
return;
|
|
}
|
|
|
|
setIsSubmitting(true);
|
|
|
|
try {
|
|
const result = await createUser(formData);
|
|
if (result?.success) {
|
|
onAdd();
|
|
} else {
|
|
setError(result?.message || t('users.createError'));
|
|
}
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : t('users.createError'));
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
}
|
|
};
|
|
|
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const { name, value, type, checked } = e.target;
|
|
setFormData(prev => ({
|
|
...prev,
|
|
[name]: type === 'checkbox' ? checked : value
|
|
}));
|
|
};
|
|
|
|
return (
|
|
<div className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full flex items-center justify-center z-50">
|
|
<div className="bg-white p-8 rounded-lg shadow-xl max-w-md w-full mx-4">
|
|
<form onSubmit={handleSubmit}>
|
|
<h2 className="text-xl font-semibold text-gray-800 mb-4">{t('users.addNew')}</h2>
|
|
|
|
{error && (
|
|
<div className="bg-red-100 border-l-4 border-red-500 text-red-700 p-3 mb-4">
|
|
<p className="text-sm">{error}</p>
|
|
</div>
|
|
)}
|
|
|
|
<div className="space-y-4">
|
|
<div>
|
|
<label htmlFor="username" className="block text-sm font-medium text-gray-700 mb-1">
|
|
{t('users.username')} *
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="username"
|
|
name="username"
|
|
value={formData.username}
|
|
onChange={handleInputChange}
|
|
placeholder={t('users.usernamePlaceholder')}
|
|
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
required
|
|
disabled={isSubmitting}
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label htmlFor="password" className="block text-sm font-medium text-gray-700 mb-1">
|
|
{t('users.password')} *
|
|
</label>
|
|
<input
|
|
type="password"
|
|
id="password"
|
|
name="password"
|
|
value={formData.password}
|
|
onChange={handleInputChange}
|
|
placeholder={t('users.passwordPlaceholder')}
|
|
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
required
|
|
disabled={isSubmitting}
|
|
minLength={6}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex items-center">
|
|
<input
|
|
type="checkbox"
|
|
id="isAdmin"
|
|
name="isAdmin"
|
|
checked={formData.isAdmin}
|
|
onChange={handleInputChange}
|
|
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
|
disabled={isSubmitting}
|
|
/>
|
|
<label htmlFor="isAdmin" className="ml-2 block text-sm text-gray-700">
|
|
{t('users.adminRole')}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex justify-end space-x-3 mt-6">
|
|
<button
|
|
type="button"
|
|
onClick={onCancel}
|
|
className="px-4 py-2 text-gray-700 bg-gray-200 rounded hover:bg-gray-300 transition-colors duration-200"
|
|
disabled={isSubmitting}
|
|
>
|
|
{t('common.cancel')}
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
disabled={isSubmitting}
|
|
>
|
|
{isSubmitting ? t('common.creating') : t('users.create')}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AddUserForm;
|