mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-05 23:44:22 +00:00
Implement admin edit user
This commit is contained in:
105
frontend/src/components/modals/user/EditUserModal.jsx
Normal file
105
frontend/src/components/modals/user/EditUserModal.jsx
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import {
|
||||||
|
Modal,
|
||||||
|
Stack,
|
||||||
|
TextInput,
|
||||||
|
Select,
|
||||||
|
Button,
|
||||||
|
Group,
|
||||||
|
PasswordInput,
|
||||||
|
Text,
|
||||||
|
} from '@mantine/core';
|
||||||
|
|
||||||
|
const EditUserModal = ({ opened, onClose, onEditUser, loading, user }) => {
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
email: '',
|
||||||
|
displayName: '',
|
||||||
|
role: '',
|
||||||
|
password: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (user) {
|
||||||
|
setFormData({
|
||||||
|
email: user.email,
|
||||||
|
displayName: user.displayName || '',
|
||||||
|
role: user.role,
|
||||||
|
password: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
const updateData = {
|
||||||
|
...formData,
|
||||||
|
...(formData.password ? { password: formData.password } : {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await onEditUser(user.id, updateData);
|
||||||
|
if (result.success) {
|
||||||
|
setFormData({
|
||||||
|
email: '',
|
||||||
|
displayName: '',
|
||||||
|
role: '',
|
||||||
|
password: '',
|
||||||
|
});
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal opened={opened} onClose={onClose} title="Edit User" centered>
|
||||||
|
<Stack>
|
||||||
|
<TextInput
|
||||||
|
label="Email"
|
||||||
|
required
|
||||||
|
value={formData.email}
|
||||||
|
onChange={(e) =>
|
||||||
|
setFormData({ ...formData, email: e.currentTarget.value })
|
||||||
|
}
|
||||||
|
placeholder="user@example.com"
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Display Name"
|
||||||
|
value={formData.displayName}
|
||||||
|
onChange={(e) =>
|
||||||
|
setFormData({ ...formData, displayName: e.currentTarget.value })
|
||||||
|
}
|
||||||
|
placeholder="John Doe"
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
label="Role"
|
||||||
|
required
|
||||||
|
value={formData.role}
|
||||||
|
onChange={(value) => setFormData({ ...formData, role: value })}
|
||||||
|
data={[
|
||||||
|
{ value: 'admin', label: 'Admin' },
|
||||||
|
{ value: 'editor', label: 'Editor' },
|
||||||
|
{ value: 'viewer', label: 'Viewer' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<PasswordInput
|
||||||
|
label="New Password"
|
||||||
|
value={formData.password}
|
||||||
|
onChange={(e) =>
|
||||||
|
setFormData({ ...formData, password: e.currentTarget.value })
|
||||||
|
}
|
||||||
|
placeholder="Enter new password (leave empty to keep current)"
|
||||||
|
/>
|
||||||
|
<Text size="xs" c="dimmed">
|
||||||
|
Leave password empty to keep the current password
|
||||||
|
</Text>
|
||||||
|
<Group justify="flex-end" mt="md">
|
||||||
|
<Button variant="default" onClick={onClose}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleSubmit} loading={loading}>
|
||||||
|
Save Changes
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditUserModal;
|
||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
import { notifications } from '@mantine/notifications';
|
import { notifications } from '@mantine/notifications';
|
||||||
import { useAdmin } from '../../../hooks/useAdmin';
|
import { useAdmin } from '../../../hooks/useAdmin';
|
||||||
import CreateUserModal from '../../modals/user/CreateUserModal';
|
import CreateUserModal from '../../modals/user/CreateUserModal';
|
||||||
|
import EditUserModal from '../../modals/user/EditUserModal';
|
||||||
import DeleteUserModal from '../../modals/user/DeleteUserModal';
|
import DeleteUserModal from '../../modals/user/DeleteUserModal';
|
||||||
|
|
||||||
const AdminUsersTab = ({ currentUser }) => {
|
const AdminUsersTab = ({ currentUser }) => {
|
||||||
@@ -26,15 +27,22 @@ const AdminUsersTab = ({ currentUser }) => {
|
|||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
create,
|
create,
|
||||||
|
update,
|
||||||
delete: deleteUser,
|
delete: deleteUser,
|
||||||
} = useAdmin('users');
|
} = useAdmin('users');
|
||||||
|
|
||||||
const [createModalOpened, setCreateModalOpened] = useState(false);
|
const [createModalOpened, setCreateModalOpened] = useState(false);
|
||||||
|
const [editModalData, setEditModalData] = useState(null);
|
||||||
const [deleteModalData, setDeleteModalData] = useState(null);
|
const [deleteModalData, setDeleteModalData] = useState(null);
|
||||||
|
|
||||||
const handleCreateUser = async (userData) => {
|
const handleCreateUser = async (userData) => {
|
||||||
return await create(userData);
|
return await create(userData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEditUser = async (id, userData) => {
|
||||||
|
return await update(id, userData);
|
||||||
|
};
|
||||||
|
|
||||||
const handleDeleteClick = (user) => {
|
const handleDeleteClick = (user) => {
|
||||||
if (user.id === currentUser.id) {
|
if (user.id === currentUser.id) {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
@@ -65,7 +73,11 @@ const AdminUsersTab = ({ currentUser }) => {
|
|||||||
<Table.Td>{new Date(user.createdAt).toLocaleDateString()}</Table.Td>
|
<Table.Td>{new Date(user.createdAt).toLocaleDateString()}</Table.Td>
|
||||||
<Table.Td>
|
<Table.Td>
|
||||||
<Group gap="xs" justify="flex-end">
|
<Group gap="xs" justify="flex-end">
|
||||||
<ActionIcon variant="subtle" color="blue">
|
<ActionIcon
|
||||||
|
variant="subtle"
|
||||||
|
color="blue"
|
||||||
|
onClick={() => setEditModalData(user)}
|
||||||
|
>
|
||||||
<IconEdit size={16} />
|
<IconEdit size={16} />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
@@ -128,6 +140,14 @@ const AdminUsersTab = ({ currentUser }) => {
|
|||||||
loading={loading}
|
loading={loading}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<EditUserModal
|
||||||
|
opened={!!editModalData}
|
||||||
|
onClose={() => setEditModalData(null)}
|
||||||
|
onEditUser={handleEditUser}
|
||||||
|
user={editModalData}
|
||||||
|
loading={loading}
|
||||||
|
/>
|
||||||
|
|
||||||
<DeleteUserModal
|
<DeleteUserModal
|
||||||
opened={!!deleteModalData}
|
opened={!!deleteModalData}
|
||||||
onClose={() => setDeleteModalData(null)}
|
onClose={() => setDeleteModalData(null)}
|
||||||
|
|||||||
Reference in New Issue
Block a user