custos-portal/src/components/Users/UserSettings.tsx (218 lines of code) (raw):

import { NavContainer } from "../NavContainer"; import { Box, Flex, Text, Input, Icon, TableContainer, Table, Thead, Tr, Th, Td, Tbody, Stack, FormControl, FormLabel, IconButton, Code, Spinner, HStack, } from "@chakra-ui/react"; import { PageTitle } from "../PageTitle"; import { ActionButton } from "../ActionButton"; import { Link, useParams } from "react-router-dom"; import { FaArrowLeft } from "react-icons/fa6"; import { LeftRightLayout } from "../LeftRightLayout"; import { FiTrash2 } from "react-icons/fi"; import { StackedBorderBox } from "../StackedBorderBox"; import { BACKEND_URL, CLIENT_ID } from "../../lib/constants"; import { useApi } from "../../hooks/useApi"; import { isEmpty } from "../../lib/util"; import { useEffect, useState } from "react"; import { useAuth } from "react-oidc-context"; export const UserSettings = () => { const { email } = useParams(); const auth = useAuth(); const [user, setUser] = useState<User | null>(null); const [group, setGroup] = useState<any | null>(null); useEffect(() => { async function fetchData() { const userResp = await fetch( `${BACKEND_URL}/api/v1/user-management/user/profile/${email}`, { headers: { Authorization: `Bearer ${auth.user?.access_token}`, }, } ); const userData = await userResp.json(); const groupResp = await fetch( `${BACKEND_URL}/api/v1/group-management/users/${email}/group-memberships`, { headers: { client_id: CLIENT_ID, userId: email, Authorization: `Bearer ${auth.user?.access_token}`, }, } ); const groupData = await groupResp.json(); setUser(userData); setGroup(groupData); } fetchData(); }, []); if (!user || !group) { return ( <NavContainer activeTab="Users"> <Spinner /> </NavContainer> ); } return ( <> <NavContainer activeTab="Users"> <Link to="/users"> <Flex alignItems="center" gap={2} color="default.secondary"> <Icon as={FaArrowLeft} /> <Text fontWeight="bold" fontSize="sm"> Back to Users </Text> </Flex> </Link> <Flex mt={4} justify="space-between"> <Box> <PageTitle> {user.first_name} {user.last_name} </PageTitle> <Text color="default.secondary" mt={2}> {user.email} </Text> </Box> <ActionButton icon={FiTrash2} onClick={() => {}}> Disable User </ActionButton> </Flex> <StackedBorderBox> <LeftRightLayout left={<Text fontSize="lg">Basic Information</Text>} right={ <> <Stack spacing={4}> <FormControl color="default.default"> <FormLabel>Name</FormLabel> <Input type="text" value={user.first_name + " " + user.last_name} /> </FormControl> <FormControl> <FormLabel>Email</FormLabel> <Input type="text" value={user.email} /> </FormControl> <FormControl> <FormLabel>Joined</FormLabel> <Input type="text" disabled={true} value={new Date( parseInt(user.created_at) ).toLocaleString()} /> </FormControl> <FormControl> <FormLabel>Last Modified</FormLabel> <Input type="text" disabled={true} value={new Date( parseInt(user.last_modified_at) ).toLocaleString()} /> </FormControl> </Stack> </> } /> <Box> <Text fontSize="lg">Group Memberships</Text> <TableContainer mt={4}> <Table variant="simple"> <Thead> <Tr> <Th>Name</Th> <Th>Role</Th> <Th>Owner</Th> <Th>Actions</Th> </Tr> </Thead> <Tbody> <Tr> <Td> <Link to="/groups/1">Group 1</Link> </Td> <Td>Admin</Td> <Td>Stella Zhou</Td> <Td> {/* remove icon */} <IconButton aria-label="Delete Role" icon={<FiTrash2 />} size="sm" bg="" /> </Td> </Tr> </Tbody> </Table> </TableContainer> </Box> <Box> <Text fontSize="lg">Client Roles</Text> {!isEmpty(user.client_roles) ? ( <> <Text mt={2} color="gray.600"> Through their group memberships, this user has the following client roles </Text> <HStack mt={2}> {user.client_roles?.map((role: string) => ( <Code key={role} size="lg"> {role} </Code> ))} </HStack> </> ) : ( <Text mt={2} color="gray.600"> This user has no client roles </Text> )} </Box> <Box> <Text fontSize="lg">Realm Roles</Text> {!isEmpty(user.realm_roles) ? ( <> <Text mt={2} color="gray.600"> Through their group memberships, this user has the following realm roles </Text> <HStack mt={2}> {user.client_roles?.map((role: string) => ( <Code key={role} size="lg"> {role} </Code> ))} </HStack> </> ) : ( <Text mt={2} color="gray.600"> This user has no realm roles </Text> )} </Box> </StackedBorderBox> </NavContainer> </> ); };