From 868d52e2246bc92739f4eb9950c586b7d93662a7 Mon Sep 17 00:00:00 2001 From: Bailey Taylor Date: Wed, 29 Oct 2025 11:23:07 +0800 Subject: [PATCH] Added editable user fields --- src/app/(protected)/admin/users/page.tsx | 1 + src/components/admin/UserTableSection.tsx | 239 ++++++++++++++++++++-- 2 files changed, 224 insertions(+), 16 deletions(-) diff --git a/src/app/(protected)/admin/users/page.tsx b/src/app/(protected)/admin/users/page.tsx index bd98e6c..f7fc2f3 100644 --- a/src/app/(protected)/admin/users/page.tsx +++ b/src/app/(protected)/admin/users/page.tsx @@ -13,6 +13,7 @@ interface UserDTO { email: string; role: string; clientName: string; + clientId?: number; enabled: boolean; } diff --git a/src/components/admin/UserTableSection.tsx b/src/components/admin/UserTableSection.tsx index 1938d95..f76cbb9 100644 --- a/src/components/admin/UserTableSection.tsx +++ b/src/components/admin/UserTableSection.tsx @@ -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(initialUsers); const [openUserDialog, setOpenUserDialog] = useState(false); const [openClientDialog, setOpenClientDialog] = useState(false); const [openInviteUserDialog, setOpenInviteUserDialog] = useState(false); + // Edit mode state + const [editingUserId, setEditingUserId] = useState(null); + const [editFormData, setEditFormData] = useState>({}); + const [clients, setClients] = useState([]); + 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 ( User Management @@ -57,23 +144,143 @@ export default function UserTableSection({ initialUsers }: { initialUsers: UserD Role Client Status + Actions - {users.map((user) => ( - - {user.username} - {user.displayName} - {user.firstName} - {user.lastName} - {user.email} - {user.role} - {user.clientName} - - - - - ))} + {users.map((user) => { + const isEditing = editingUserId === user.id; + return ( + + + {isEditing ? ( + setEditFormData({ ...editFormData, username: e.target.value })} + fullWidth + /> + ) : ( + user.username + )} + + + {isEditing ? ( + setEditFormData({ ...editFormData, displayName: e.target.value })} + fullWidth + /> + ) : ( + user.displayName + )} + + + {isEditing ? ( + setEditFormData({ ...editFormData, firstName: e.target.value })} + fullWidth + /> + ) : ( + user.firstName + )} + + + {isEditing ? ( + setEditFormData({ ...editFormData, lastName: e.target.value })} + fullWidth + /> + ) : ( + user.lastName + )} + + + {isEditing ? ( + setEditFormData({ ...editFormData, email: e.target.value })} + fullWidth + /> + ) : ( + user.email + )} + + + {isEditing ? ( + + + + ) : ( + user.role + )} + + + {isEditing ? ( + + + + ) : ( + user.clientName + )} + + + + + + {isEditing ? ( + + handleSave(user.id)} + disabled={loading} + size="small" + > + + + + + + + ) : ( + handleEdit(user)} + size="small" + > + + + )} + + + ); + })}