Added editable user fields
All checks were successful
Deploy Frontend / deploy (push) Successful in 23s

This commit is contained in:
Bailey Taylor
2025-10-29 11:23:07 +08:00
parent 1d882fbfee
commit 868d52e224
2 changed files with 224 additions and 16 deletions

View File

@@ -13,6 +13,7 @@ interface UserDTO {
email: string;
role: string;
clientName: string;
clientId?: number;
enabled: boolean;
}

View File

@@ -1,15 +1,20 @@
// src/components/admin/UserTableSection.tsx
'use client';
import { useState } from 'react';
import { useState, useEffect } from 'react';
import {
Typography, Table, TableBody, TableCell, TableContainer, TableHead,
TableRow, Paper, Box, Button, Dialog, DialogTitle, DialogContent, DialogActions
TableRow, Paper, Box, Button, Dialog, DialogTitle, DialogContent, DialogActions,
TextField, Select, MenuItem, FormControl, InputLabel, IconButton
} from '@mui/material';
import EditIcon from '@mui/icons-material/Edit';
import SaveIcon from '@mui/icons-material/Save';
import CancelIcon from '@mui/icons-material/Cancel';
import UserEnableToggle from './UserEnableToggle';
import AddUserForm from './forms/AddUserForm';
import AddClientForm from './forms/AddClientForm';
import InviteUserForm from './forms/InviteUserForm';
import api from '@/lib/axios';
interface UserDTO {
id: number;
@@ -20,15 +25,97 @@ interface UserDTO {
email: string;
role: string;
clientName: string;
clientId?: number;
enabled: boolean;
}
interface ClientDTO {
clientId: number;
clientIdentifier: string;
clientName: string;
}
export default function UserTableSection({ initialUsers }: { initialUsers: UserDTO[] }) {
const [users, setUsers] = useState<UserDTO[]>(initialUsers);
const [openUserDialog, setOpenUserDialog] = useState(false);
const [openClientDialog, setOpenClientDialog] = useState(false);
const [openInviteUserDialog, setOpenInviteUserDialog] = useState(false);
// Edit mode state
const [editingUserId, setEditingUserId] = useState<number | null>(null);
const [editFormData, setEditFormData] = useState<Partial<UserDTO>>({});
const [clients, setClients] = useState<ClientDTO[]>([]);
const [loading, setLoading] = useState(false);
// Fetch clients for dropdown
useEffect(() => {
const fetchClients = async () => {
try {
const res = await api.get('/auth/clients');
setClients(res.data);
} catch (err) {
console.error('Failed to fetch clients:', err);
}
};
fetchClients();
}, []);
const handleEdit = (user: UserDTO) => {
setEditingUserId(user.id);
setEditFormData({
username: user.username,
displayName: user.displayName,
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
role: user.role,
clientName: user.clientName,
clientId: user.clientId
});
};
const handleCancel = () => {
setEditingUserId(null);
setEditFormData({});
};
const handleSave = async (userId: number) => {
setLoading(true);
try {
// Find the selected client
const selectedClient = clients.find(c => c.clientId === editFormData.clientId);
await api.put(`/admin/users/${userId}`, {
username: editFormData.username,
displayName: editFormData.displayName,
firstName: editFormData.firstName,
lastName: editFormData.lastName,
email: editFormData.email,
role: editFormData.role,
clientId: editFormData.clientId
});
// Update local state
setUsers(users.map(user =>
user.id === userId
? {
...user,
...editFormData,
clientName: selectedClient?.clientName || user.clientName
}
: user
));
setEditingUserId(null);
setEditFormData({});
} catch (err) {
console.error('Failed to update user:', err);
alert('Failed to update user. Please try again.');
} finally {
setLoading(false);
}
};
return (
<Box sx={{ p: 4 }}>
<Typography variant="h5" gutterBottom>User Management</Typography>
@@ -57,23 +144,143 @@ export default function UserTableSection({ initialUsers }: { initialUsers: UserD
<TableCell>Role</TableCell>
<TableCell>Client</TableCell>
<TableCell>Status</TableCell>
<TableCell>Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
{users.map((user) => (
<TableRow key={user.id}>
<TableCell>{user.username}</TableCell>
<TableCell>{user.displayName}</TableCell>
<TableCell>{user.firstName}</TableCell>
<TableCell>{user.lastName}</TableCell>
<TableCell>{user.email}</TableCell>
<TableCell>{user.role}</TableCell>
<TableCell>{user.clientName}</TableCell>
<TableCell>
<UserEnableToggle userId={user.id} initialEnabled={user.enabled} />
</TableCell>
</TableRow>
))}
{users.map((user) => {
const isEditing = editingUserId === user.id;
return (
<TableRow key={user.id}>
<TableCell>
{isEditing ? (
<TextField
size="small"
value={editFormData.username || ''}
onChange={(e) => setEditFormData({ ...editFormData, username: e.target.value })}
fullWidth
/>
) : (
user.username
)}
</TableCell>
<TableCell>
{isEditing ? (
<TextField
size="small"
value={editFormData.displayName || ''}
onChange={(e) => setEditFormData({ ...editFormData, displayName: e.target.value })}
fullWidth
/>
) : (
user.displayName
)}
</TableCell>
<TableCell>
{isEditing ? (
<TextField
size="small"
value={editFormData.firstName || ''}
onChange={(e) => setEditFormData({ ...editFormData, firstName: e.target.value })}
fullWidth
/>
) : (
user.firstName
)}
</TableCell>
<TableCell>
{isEditing ? (
<TextField
size="small"
value={editFormData.lastName || ''}
onChange={(e) => setEditFormData({ ...editFormData, lastName: e.target.value })}
fullWidth
/>
) : (
user.lastName
)}
</TableCell>
<TableCell>
{isEditing ? (
<TextField
size="small"
value={editFormData.email || ''}
onChange={(e) => setEditFormData({ ...editFormData, email: e.target.value })}
fullWidth
/>
) : (
user.email
)}
</TableCell>
<TableCell>
{isEditing ? (
<FormControl fullWidth size="small">
<Select
value={editFormData.role || ''}
onChange={(e) => setEditFormData({ ...editFormData, role: e.target.value })}
>
<MenuItem value="USER">USER</MenuItem>
<MenuItem value="ADMIN">ADMIN</MenuItem>
</Select>
</FormControl>
) : (
user.role
)}
</TableCell>
<TableCell>
{isEditing ? (
<FormControl fullWidth size="small">
<Select
value={editFormData.clientId || ''}
onChange={(e) => setEditFormData({ ...editFormData, clientId: Number(e.target.value) })}
>
{clients.map(client => (
<MenuItem key={client.clientId} value={client.clientId}>
{client.clientName}
</MenuItem>
))}
</Select>
</FormControl>
) : (
user.clientName
)}
</TableCell>
<TableCell>
<UserEnableToggle userId={user.id} initialEnabled={user.enabled} />
</TableCell>
<TableCell>
{isEditing ? (
<Box sx={{ display: 'flex', gap: 1 }}>
<IconButton
color="primary"
onClick={() => handleSave(user.id)}
disabled={loading}
size="small"
>
<SaveIcon />
</IconButton>
<IconButton
color="default"
onClick={handleCancel}
disabled={loading}
size="small"
>
<CancelIcon />
</IconButton>
</Box>
) : (
<IconButton
color="primary"
onClick={() => handleEdit(user)}
size="small"
>
<EditIcon />
</IconButton>
)}
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>