From 795ca27397942572a1cea523fc3f5191702696bf Mon Sep 17 00:00:00 2001 From: Prakhar Trivedi Date: Tue, 12 Aug 2025 18:48:15 +0800 Subject: [PATCH] completed create user dialog --- src/components/Identity/CreateUserDialog.jsx | 149 +++++++++++++++++++ src/pages/AdminConsole.jsx | 14 +- src/pages/Profile.jsx | 2 +- src/pages/UserManagement.jsx | 8 +- 4 files changed, 154 insertions(+), 19 deletions(-) create mode 100644 src/components/Identity/CreateUserDialog.jsx diff --git a/src/components/Identity/CreateUserDialog.jsx b/src/components/Identity/CreateUserDialog.jsx new file mode 100644 index 0000000..699e46d --- /dev/null +++ b/src/components/Identity/CreateUserDialog.jsx @@ -0,0 +1,149 @@ +import { Button, CloseButton, Dialog, Field, IconButton, Input, Portal, Text, VStack } from '@chakra-ui/react'; +import { useState, useEffect } from 'react'; +import { FaPlus } from 'react-icons/fa'; +import { useNavigate } from 'react-router-dom'; +import { withMask } from 'use-mask-input'; +import ToastWizard from '../toastWizard'; +import server, { JSONResponse } from '../../networking'; + +function CreateUserDialog() { + const navigate = useNavigate(); + + const [dialogOpen, setDialogOpen] = useState(false); + const [fname, setFname] = useState(''); + const [lname, setLname] = useState(''); + const [username, setUsername] = useState(''); + const [email, setEmail] = useState(''); + const [contact, setContact] = useState(''); + const [role, setRole] = useState(''); + const [creatingUser, setCreatingUser] = useState(false); + + const isDisabled = !fname || !lname || !username || !email || !contact || !role; + + const handleCreateUser = async () => { + if (isDisabled) { + ToastWizard.standard("error", "All fields are required."); + return; + } + + setCreatingUser(true); + + try { + const response = await server.post('/admin/createUser', { + fname, + lname, + username, + email, + contact, + role + }) + + if (response.data instanceof JSONResponse) { + if (response.data.isErrorStatus()) { + const errObject = { + response: { + data: response.data + } + }; + throw new Error(errObject); + } + + // Success case + ToastWizard.standard("success", "Account Created", `Welcome ${fname} to the family! Login instructions have been sent via email!`); + setDialogOpen(false); + if (response.data.raw.newUserID) { + navigate(`/profile/${response.data.raw.newUserID}`); + } + } else { + throw new Error("Unexpected response format"); + } + } catch (err) { + if (err.response && err.response.data instanceof JSONResponse) { + console.log("Error response in user creation request:", err.response.data.fullMessage()); + if (err.response.data.userErrorType()) { + ToastWizard.standard("error", "User creation failed.", err.response.data.message); + } else { + ToastWizard.standard("error", "Something went wrong", "Couldn't create user. Please try again.") + } + } else { + console.log("Unexpected error in user creation request:", err); + ToastWizard.standard("error", "Something went wrong", "Couldn't create user. Please try again.") + } + } finally { + setCreatingUser(false); + } + } + + const handleEnterKey = (e) => { + if (e.key === 'Enter') { + handleCreateUser(); + } + } + + return ( + setDialogOpen(e.open)} unmountOnExit> + + + + + + + + + Create New Account + + + + Create new accounts to enable more people to gain access to ArchAIve's innovative artefact digitisation services! + Users will be able to access most of the platform's features, except those that are sensitive like managing other users. + Every user's activity is monitored closely, empowering you to redress in any dire situations at all times. + + + + First Name + setFname(e.target.value)} /> + + + + Last Name + setLname(e.target.value)} /> + + + + Username + setUsername(e.target.value)} /> + + + + Email + setEmail(e.target.value)} /> + + + + Contact + setContact(e.target.value)} /> + + + + Role + setRole(e.target.value)} /> + + + + + + + + + + + + + + + + + ) +} + +export default CreateUserDialog \ No newline at end of file diff --git a/src/pages/AdminConsole.jsx b/src/pages/AdminConsole.jsx index 5407d89..9769402 100644 --- a/src/pages/AdminConsole.jsx +++ b/src/pages/AdminConsole.jsx @@ -12,7 +12,7 @@ function AdminConsole() { return ( Admin Console - + User Management @@ -25,18 +25,6 @@ function AdminConsole() { - - - Data Management - - Analyse and manage batches, collections, artefacts and other data that goes into the platform. - - - - - - - Platform Controls diff --git a/src/pages/Profile.jsx b/src/pages/Profile.jsx index 10a6d77..3091463 100644 --- a/src/pages/Profile.jsx +++ b/src/pages/Profile.jsx @@ -241,7 +241,7 @@ function Profile() { Security & Authentication - Last Login: {originalAccountInfo.lastLogin} + Last Login: {originalAccountInfo.lastLogin || 'Never'} diff --git a/src/pages/UserManagement.jsx b/src/pages/UserManagement.jsx index d6820af..75bc85c 100644 --- a/src/pages/UserManagement.jsx +++ b/src/pages/UserManagement.jsx @@ -1,16 +1,14 @@ -import { Box, Button, IconButton, SimpleGrid, Skeleton, Spinner, Text } from '@chakra-ui/react' -import { FaPlus } from 'react-icons/fa' +import { Box, SimpleGrid, Skeleton, Text } from '@chakra-ui/react' import IAMStatisticBox from '../components/Identity/IAMStatisticBox' import IAMUserCard from '../components/Identity/IAMUserCard' -import { useNavigate } from 'react-router-dom' import { useSelector } from 'react-redux' import { useState } from 'react' import server, { JSONResponse } from '../networking'; import ToastWizard from '../components/toastWizard'; import { useEffect } from 'react' +import CreateUserDialog from '../components/Identity/CreateUserDialog' function UserManagement() { - const navigate = useNavigate(); const { loaded, superuser } = useSelector(state => state.auth); const [userData, setUserData] = useState({}); @@ -68,7 +66,7 @@ function UserManagement() { User Management - +