mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 18:29:15 +03:00
feat: editing students from table
This commit is contained in:
parent
21779419c9
commit
1dff6be5e4
@ -16,8 +16,9 @@ import { IconType } from 'react-icons';
|
|||||||
|
|
||||||
export interface IBaseModalProps extends ModalProps {
|
export interface IBaseModalProps extends ModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
|
isDisabled: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onProceed: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
onProceed?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
||||||
heading: string;
|
heading: string;
|
||||||
icon?: IconType;
|
icon?: IconType;
|
||||||
description?: string;
|
description?: string;
|
||||||
@ -27,8 +28,19 @@ export interface IBaseModalProps extends ModalProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const BaseModal: React.FC<IBaseModalProps> = props => {
|
const BaseModal: React.FC<IBaseModalProps> = props => {
|
||||||
const { heading, description, isOpen, onClose, onProceed, confirmText, icon, isLoading, loadingText, ...modalProps } =
|
const {
|
||||||
props;
|
heading,
|
||||||
|
description,
|
||||||
|
isOpen,
|
||||||
|
onClose,
|
||||||
|
onProceed,
|
||||||
|
confirmText,
|
||||||
|
icon,
|
||||||
|
isLoading,
|
||||||
|
isDisabled,
|
||||||
|
loadingText,
|
||||||
|
...modalProps
|
||||||
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onClose={onClose} {...modalProps}>
|
<Modal isOpen={isOpen} onClose={onClose} {...modalProps}>
|
||||||
@ -61,6 +73,7 @@ const BaseModal: React.FC<IBaseModalProps> = props => {
|
|||||||
<Button
|
<Button
|
||||||
onClick={onProceed}
|
onClick={onProceed}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
isDisabled={isDisabled}
|
||||||
loadingText={loadingText || 'Loading...'}
|
loadingText={loadingText || 'Loading...'}
|
||||||
borderRadius='md'
|
borderRadius='md'
|
||||||
variant='outline'
|
variant='outline'
|
||||||
|
|||||||
152
src/components/Modals/EditUserModal/EditUserModal.tsx
Normal file
152
src/components/Modals/EditUserModal/EditUserModal.tsx
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import BaseModal from '@educt/components/Modal';
|
||||||
|
|
||||||
|
import * as helpers from '@educt/helpers';
|
||||||
|
import { FormControl, FormLabel, FormHelperText, Input, Select, Stack } from '@chakra-ui/react';
|
||||||
|
import { CheckIcon } from '@chakra-ui/icons';
|
||||||
|
import { MdModeEdit } from 'react-icons/md';
|
||||||
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types
|
||||||
|
*/
|
||||||
|
import { IUser } from '@educt/interfaces';
|
||||||
|
import { UserRoleEnum } from '@educt/enums';
|
||||||
|
import { SubmitHandler } from 'react-hook-form';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks
|
||||||
|
*/
|
||||||
|
import { useEffect, useMemo } from 'react';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { useRootStore } from '@educt/hooks/useRootStore';
|
||||||
|
import { useUpdateUser } from '@educt/hooks/queries';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schema
|
||||||
|
*/
|
||||||
|
import EditUserSchema from './EditUserModal.validator';
|
||||||
|
|
||||||
|
type EditUserModalPropsType = {
|
||||||
|
user: IUser;
|
||||||
|
isOpen: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onEdited?: (updatedUser: IUser) => void | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
type UpdateUserInputType = {
|
||||||
|
first_name: string;
|
||||||
|
last_name: string;
|
||||||
|
login: string | null;
|
||||||
|
email: string;
|
||||||
|
role: UserRoleEnum;
|
||||||
|
password: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const EditUserModal: React.FC<EditUserModalPropsType> = props => {
|
||||||
|
const { user, onClose, onEdited, isOpen } = props;
|
||||||
|
const {
|
||||||
|
userStore: { me },
|
||||||
|
} = useRootStore();
|
||||||
|
const { updateUser, isLoading } = useUpdateUser();
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
reset,
|
||||||
|
formState: { errors, isDirty, dirtyFields },
|
||||||
|
} = useForm<UpdateUserInputType>({
|
||||||
|
resolver: yupResolver(EditUserSchema),
|
||||||
|
defaultValues: useMemo(() => {
|
||||||
|
return props.user;
|
||||||
|
}, [props]),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (me === null) return null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit handler
|
||||||
|
*/
|
||||||
|
const onSubmit: SubmitHandler<UpdateUserInputType> = async data => {
|
||||||
|
try {
|
||||||
|
const params = helpers.getDirtyFields<UpdateUserInputType>(dirtyFields, data);
|
||||||
|
const updated = await updateUser(user.id, params);
|
||||||
|
onClose();
|
||||||
|
onEdited && onEdited(updated);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
reset(props.user);
|
||||||
|
}, [props.user]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseModal
|
||||||
|
icon={MdModeEdit}
|
||||||
|
heading='Edit user'
|
||||||
|
confirmText='Save'
|
||||||
|
loadingText='Saving...'
|
||||||
|
isLoading={isLoading}
|
||||||
|
isDisabled={!isDirty}
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
onProceed={handleSubmit(onSubmit)}
|
||||||
|
>
|
||||||
|
<Stack spacing='4'>
|
||||||
|
<FormControl isDisabled>
|
||||||
|
<FormLabel>Identificator</FormLabel>
|
||||||
|
<Input value={user.id} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>New Login</FormLabel>
|
||||||
|
<Input placeholder='e.g student001' {...register('login')} isInvalid={!!errors.login} />
|
||||||
|
{errors.login && <FormHelperText color='red.500'>{errors.login.message}</FormHelperText>}
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl isRequired>
|
||||||
|
<FormLabel>First name</FormLabel>
|
||||||
|
<Input placeholder='First name' {...register('first_name')} isInvalid={!!errors.first_name} />
|
||||||
|
{errors.first_name && <FormHelperText color='red.500'>{errors.first_name.message}</FormHelperText>}
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl isRequired>
|
||||||
|
<FormLabel>Last name</FormLabel>
|
||||||
|
<Input placeholder='Last name' {...register('last_name')} isInvalid={!!errors.last_name} />
|
||||||
|
{errors.last_name && <FormHelperText color='red.500'>{errors.last_name.message}</FormHelperText>}
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl isRequired>
|
||||||
|
<FormLabel>Email</FormLabel>
|
||||||
|
<Input placeholder='example@email.com' {...register('email')} isInvalid={!!errors.email} />
|
||||||
|
{errors.email && <FormHelperText color='red.500'>{errors.email.message}</FormHelperText>}
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl isRequired>
|
||||||
|
<FormLabel>Role</FormLabel>
|
||||||
|
<Select w='full' mr='2' {...register('role')} isInvalid={!!errors.role}>
|
||||||
|
<option value={UserRoleEnum.STUDENT}>Student</option>
|
||||||
|
{me.isAdmin && (
|
||||||
|
<>
|
||||||
|
<option value={UserRoleEnum.TEACHER}>Teacher</option>
|
||||||
|
<option value={UserRoleEnum.ADMIN}>Administrator</option>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Select>
|
||||||
|
{errors.role ? <FormHelperText color='red.500'>{errors.role.message}</FormHelperText> : null}
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>New Password</FormLabel>
|
||||||
|
<Input placeholder='******' {...register('password')} isInvalid={!!errors.password} />
|
||||||
|
<FormHelperText color={errors.password ? 'red' : 'gray.500'}>
|
||||||
|
{errors.password ? errors.password.message : 'Must be at least 6 characters.'}
|
||||||
|
</FormHelperText>
|
||||||
|
</FormControl>
|
||||||
|
</Stack>
|
||||||
|
</BaseModal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditUserModal;
|
||||||
3
src/components/Modals/EditUserModal/index.ts
Normal file
3
src/components/Modals/EditUserModal/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import EditUserModal from './EditUserModal';
|
||||||
|
|
||||||
|
export default EditUserModal;
|
||||||
@ -27,7 +27,7 @@ export interface ICourse {
|
|||||||
teacher: Pick<IUser, 'id' | 'first_name' | 'fullname' | 'last_name' | 'email' | 'created_at' | 'updated_at'>;
|
teacher: Pick<IUser, 'id' | 'first_name' | 'fullname' | 'last_name' | 'email' | 'created_at' | 'updated_at'>;
|
||||||
category: ICategory;
|
category: ICategory;
|
||||||
lessons: ILesson[];
|
lessons: ILesson[];
|
||||||
students: Array<Pick<IUser, 'id' | 'first_name' | 'fullname' | 'last_name' | 'email' | 'created_at' | 'updated_at'>>;
|
students: IUser[];
|
||||||
color: ColorType | null;
|
color: ColorType | null;
|
||||||
students_count: string;
|
students_count: string;
|
||||||
likes_count: string;
|
likes_count: string;
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Table, Tbody, Input, InputGroup, InputLeftElement, Flex, Box, Text } from '@chakra-ui/react';
|
import { Table, Tbody, Input, InputGroup, InputLeftElement, Flex, Box, Text } from '@chakra-ui/react';
|
||||||
import { MdSearch } from 'react-icons/md';
|
import { MdSearch } from 'react-icons/md';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Components
|
||||||
|
*/
|
||||||
import AddStudentsModal from '@educt/components/Modals/AddStudentsModal';
|
import AddStudentsModal from '@educt/components/Modals/AddStudentsModal';
|
||||||
|
import EditUserModal from '@educt/components/Modals/EditUserModal';
|
||||||
import { AddButton } from '@educt/components/Buttons';
|
import { AddButton } from '@educt/components/Buttons';
|
||||||
import BulkActionsMenu from './BulkActionsMenu';
|
import BulkActionsMenu from './BulkActionsMenu';
|
||||||
import StudentTableHead from './StudentTableHead';
|
import StudentTableHead from './StudentTableHead';
|
||||||
@ -31,11 +36,17 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
|
|||||||
const [rows, setRows] = useState<ICourse['students']>(props.course.students);
|
const [rows, setRows] = useState<ICourse['students']>(props.course.students);
|
||||||
const [selected, setSelected] = useState<ICourse['students']>([]);
|
const [selected, setSelected] = useState<ICourse['students']>([]);
|
||||||
const [search, setSearch] = useState<string>('');
|
const [search, setSearch] = useState<string>('');
|
||||||
|
const [editing, setEditing] = useState<ICourse['students'][number] | null>(null);
|
||||||
const {
|
const {
|
||||||
isOpen: isOpenAddStudentModal,
|
isOpen: isOpenAddStudentModal,
|
||||||
onOpen: onOpenAddStudentModal,
|
onOpen: onOpenAddStudentModal,
|
||||||
onClose: onCloseAddStudentModal,
|
onClose: onCloseAddStudentModal,
|
||||||
} = useDisclosure();
|
} = useDisclosure();
|
||||||
|
const {
|
||||||
|
isOpen: isOpenEditStudentModal,
|
||||||
|
onOpen: onOpenEditStudentModal,
|
||||||
|
onClose: onCloseEditStudentModal,
|
||||||
|
} = useDisclosure();
|
||||||
const { deleteUser } = useDeleteUser();
|
const { deleteUser } = useDeleteUser();
|
||||||
const { detachStudents } = useDetachStudents();
|
const { detachStudents } = useDetachStudents();
|
||||||
|
|
||||||
@ -63,6 +74,10 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
|
|||||||
setRows(prev => [...prev, ...users]);
|
setRows(prev => [...prev, ...users]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onEdited = (user: IUser) => {
|
||||||
|
setRows(prev => prev.map(u => (u.id === user.id ? { ...user } : u)));
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select all students in a table
|
* Select all students in a table
|
||||||
*/
|
*/
|
||||||
@ -104,10 +119,10 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
|
|||||||
/**
|
/**
|
||||||
* Edit student handler
|
* Edit student handler
|
||||||
*/
|
*/
|
||||||
const handleEdit = (id: string) => {
|
const handleEdit = (student: ICourse['students'][number]) => {
|
||||||
return () => {
|
return () => {
|
||||||
// TODO open the edit user modal
|
setEditing(student);
|
||||||
console.log(`editing id: ${id}`);
|
onOpenEditStudentModal();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -134,6 +149,14 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
|
|||||||
currentStudents={rows}
|
currentStudents={rows}
|
||||||
onAdded={onAdded}
|
onAdded={onAdded}
|
||||||
/>
|
/>
|
||||||
|
{editing && (
|
||||||
|
<EditUserModal
|
||||||
|
user={editing}
|
||||||
|
isOpen={isOpenEditStudentModal}
|
||||||
|
onClose={onCloseEditStudentModal}
|
||||||
|
onEdited={onEdited}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Flex justifyContent='space-between' flexDir={{ base: 'column', lg: 'row' }}>
|
<Flex justifyContent='space-between' flexDir={{ base: 'column', lg: 'row' }}>
|
||||||
<Flex mb='2' alignItems='center'>
|
<Flex mb='2' alignItems='center'>
|
||||||
<Box>
|
<Box>
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export type StudentTableRowPropsType = {
|
|||||||
student: ICourse['students'][number];
|
student: ICourse['students'][number];
|
||||||
onSelect: (e: React.ChangeEvent<HTMLInputElement>, student: ICourse['students'][number]) => void;
|
onSelect: (e: React.ChangeEvent<HTMLInputElement>, student: ICourse['students'][number]) => void;
|
||||||
actions: {
|
actions: {
|
||||||
onEdit: (id: string) => () => void;
|
onEdit: (student: ICourse['students'][number]) => () => void;
|
||||||
onRemove: (id: string) => () => void;
|
onRemove: (id: string) => () => void;
|
||||||
onDelete: (id: string) => () => void;
|
onDelete: (id: string) => () => void;
|
||||||
};
|
};
|
||||||
@ -25,7 +25,7 @@ const StudentTableItem: React.FC<StudentTableRowPropsType> = ({ student, isSelec
|
|||||||
<InfoCell id={student.id} fullname={student.fullname} email={student.email} />
|
<InfoCell id={student.id} fullname={student.fullname} email={student.email} />
|
||||||
<RegisteredCell registered={student.created_at} />
|
<RegisteredCell registered={student.created_at} />
|
||||||
<ActionsCell
|
<ActionsCell
|
||||||
onEdit={actions.onEdit(student.id)}
|
onEdit={actions.onEdit(student)}
|
||||||
onRemove={actions.onRemove(student.id)}
|
onRemove={actions.onRemove(student.id)}
|
||||||
onDelete={actions.onDelete(student.id)}
|
onDelete={actions.onDelete(student.id)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -1,187 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import * as helpers from '@educt/helpers';
|
|
||||||
import {
|
|
||||||
Modal,
|
|
||||||
ModalOverlay,
|
|
||||||
ModalContent,
|
|
||||||
ModalHeader,
|
|
||||||
ModalCloseButton,
|
|
||||||
ModalBody,
|
|
||||||
ModalFooter,
|
|
||||||
FormControl,
|
|
||||||
FormLabel,
|
|
||||||
FormHelperText,
|
|
||||||
Input,
|
|
||||||
Button,
|
|
||||||
Flex,
|
|
||||||
Text,
|
|
||||||
Divider,
|
|
||||||
Select,
|
|
||||||
Stack,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import { CheckIcon } from '@chakra-ui/icons';
|
|
||||||
import { MdModeEdit } from 'react-icons/md';
|
|
||||||
import { yupResolver } from '@hookform/resolvers/yup';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Types
|
|
||||||
*/
|
|
||||||
import { IUser } from '@educt/interfaces';
|
|
||||||
import { UserRoleEnum } from '@educt/enums';
|
|
||||||
import { SubmitHandler } from 'react-hook-form';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hooks
|
|
||||||
*/
|
|
||||||
import { useEffect, useMemo } from 'react';
|
|
||||||
import { useForm } from 'react-hook-form';
|
|
||||||
import { useRootStore } from '@educt/hooks/useRootStore';
|
|
||||||
import { useUpdateUser } from '@educt/hooks/queries';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schema
|
|
||||||
*/
|
|
||||||
import UpdateUserSchema from './EditUserForm.validator';
|
|
||||||
|
|
||||||
type UpdateUserFormPropsType = {
|
|
||||||
user: IUser;
|
|
||||||
isOpen: boolean;
|
|
||||||
onClose: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
type UpdateUserInputType = {
|
|
||||||
first_name: string;
|
|
||||||
last_name: string;
|
|
||||||
login: string | null;
|
|
||||||
email: string;
|
|
||||||
role: UserRoleEnum;
|
|
||||||
password: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const UpdateUserForm: React.FC<UpdateUserFormPropsType> = props => {
|
|
||||||
const { user, onClose, isOpen } = props;
|
|
||||||
const {
|
|
||||||
userStore: { me },
|
|
||||||
} = useRootStore();
|
|
||||||
const { updateUser, isLoading } = useUpdateUser();
|
|
||||||
const {
|
|
||||||
register,
|
|
||||||
handleSubmit,
|
|
||||||
reset,
|
|
||||||
formState: { errors, isDirty, dirtyFields },
|
|
||||||
} = useForm<UpdateUserInputType>({
|
|
||||||
resolver: yupResolver(UpdateUserSchema),
|
|
||||||
defaultValues: useMemo(() => {
|
|
||||||
return props.user;
|
|
||||||
}, [props]),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (me === null) return null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submit handler
|
|
||||||
*/
|
|
||||||
const onSubmit: SubmitHandler<UpdateUserInputType> = async data => {
|
|
||||||
try {
|
|
||||||
const params = helpers.getDirtyFields<UpdateUserInputType>(dirtyFields, data);
|
|
||||||
await updateUser(user.id, params);
|
|
||||||
onClose();
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
reset(props.user);
|
|
||||||
}, [props.user]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal isOpen={isOpen} onClose={onClose}>
|
|
||||||
<ModalOverlay />
|
|
||||||
<ModalContent>
|
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
|
||||||
<ModalHeader>
|
|
||||||
<Flex alignItems='center'>
|
|
||||||
<MdModeEdit />
|
|
||||||
<Text ml={2}>Edit user</Text>
|
|
||||||
</Flex>
|
|
||||||
</ModalHeader>
|
|
||||||
<ModalCloseButton />
|
|
||||||
<Divider />
|
|
||||||
<ModalBody pb={6}>
|
|
||||||
<Stack spacing='4'>
|
|
||||||
<FormControl isDisabled>
|
|
||||||
<FormLabel>Identificator</FormLabel>
|
|
||||||
<Input value={user.id} />
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormControl>
|
|
||||||
<FormLabel>New Login</FormLabel>
|
|
||||||
<Input placeholder='e.g student001' {...register('login')} isInvalid={!!errors.login} />
|
|
||||||
{errors.login && <FormHelperText color='red.500'>{errors.login.message}</FormHelperText>}
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormControl isRequired>
|
|
||||||
<FormLabel>First name</FormLabel>
|
|
||||||
<Input placeholder='First name' {...register('first_name')} isInvalid={!!errors.first_name} />
|
|
||||||
{errors.first_name && <FormHelperText color='red.500'>{errors.first_name.message}</FormHelperText>}
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormControl isRequired>
|
|
||||||
<FormLabel>Last name</FormLabel>
|
|
||||||
<Input placeholder='Last name' {...register('last_name')} isInvalid={!!errors.last_name} />
|
|
||||||
{errors.last_name && <FormHelperText color='red.500'>{errors.last_name.message}</FormHelperText>}
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormControl isRequired>
|
|
||||||
<FormLabel>Email</FormLabel>
|
|
||||||
<Input placeholder='example@email.com' {...register('email')} isInvalid={!!errors.email} />
|
|
||||||
{errors.email && <FormHelperText color='red.500'>{errors.email.message}</FormHelperText>}
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormControl isRequired>
|
|
||||||
<FormLabel>Role</FormLabel>
|
|
||||||
<Select w='full' mr='2' {...register('role')} isInvalid={!!errors.role}>
|
|
||||||
<option value={UserRoleEnum.STUDENT}>Student</option>
|
|
||||||
{me.isAdmin && (
|
|
||||||
<>
|
|
||||||
<option value={UserRoleEnum.TEACHER}>Teacher</option>
|
|
||||||
<option value={UserRoleEnum.ADMIN}>Administrator</option>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Select>
|
|
||||||
{errors.role ? <FormHelperText color='red.500'>{errors.role.message}</FormHelperText> : null}
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
<FormControl>
|
|
||||||
<FormLabel>New Password</FormLabel>
|
|
||||||
<Input placeholder='******' {...register('password')} isInvalid={!!errors.password} />
|
|
||||||
<FormHelperText color={errors.password ? 'red' : 'gray.500'}>
|
|
||||||
{errors.password ? errors.password.message : 'Must be at least 6 characters.'}
|
|
||||||
</FormHelperText>
|
|
||||||
</FormControl>
|
|
||||||
</Stack>
|
|
||||||
</ModalBody>
|
|
||||||
|
|
||||||
<ModalFooter>
|
|
||||||
<Button
|
|
||||||
type='submit'
|
|
||||||
variant='outline'
|
|
||||||
mr={3}
|
|
||||||
colorScheme='blue'
|
|
||||||
isLoading={isLoading}
|
|
||||||
loadingText='Saving...'
|
|
||||||
isDisabled={!isDirty}
|
|
||||||
leftIcon={<CheckIcon />}
|
|
||||||
>
|
|
||||||
Save
|
|
||||||
</Button>
|
|
||||||
<Button onClick={onClose}>Cancel</Button>
|
|
||||||
</ModalFooter>
|
|
||||||
</form>
|
|
||||||
</ModalContent>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UpdateUserForm;
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
import EditUserForm from './EditUserForm';
|
|
||||||
|
|
||||||
export default EditUserForm;
|
|
||||||
@ -8,7 +8,7 @@ import { Button } from '@chakra-ui/button';
|
|||||||
* Components
|
* Components
|
||||||
*/
|
*/
|
||||||
import LoadingList from '@educt/components/LoadingList';
|
import LoadingList from '@educt/components/LoadingList';
|
||||||
import EditUserForm from '../EditUserForm';
|
import EditUserModal from '@educt/components/Modals/EditUserModal';
|
||||||
import DeleteUserDialog from '@educt/components/Dialogs/DeleteUserDialog';
|
import DeleteUserDialog from '@educt/components/Dialogs/DeleteUserDialog';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,7 +74,7 @@ const UserList: React.FC<UserListPropsType> = ({ render: Item, limit }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
{editing && <EditUserForm user={editing} isOpen={isOpenEditModal} onClose={onCloseEditModal} />}
|
{editing && <EditUserModal user={editing} isOpen={isOpenEditModal} onClose={onCloseEditModal} />}
|
||||||
{deleting && <DeleteUserDialog user={deleting} isOpen={isOpenDeleteDialog} onClose={onCloseDeleteDialog} />}
|
{deleting && <DeleteUserDialog user={deleting} isOpen={isOpenDeleteDialog} onClose={onCloseDeleteDialog} />}
|
||||||
|
|
||||||
<Flex justifyContent='space-between' sx={{ gap: '10px' }} flexWrap='wrap'>
|
<Flex justifyContent='space-between' sx={{ gap: '10px' }} flexWrap='wrap'>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user