fix: fixed search in students table

This commit is contained in:
Sergey Yarkov 2021-12-16 20:52:14 +03:00
parent 1dff6be5e4
commit d133b69982
5 changed files with 64 additions and 55 deletions

View File

@ -16,7 +16,7 @@ import { IconType } from 'react-icons';
export interface IBaseModalProps extends ModalProps {
isOpen: boolean;
isDisabled: boolean;
isDisabled?: boolean | undefined;
onClose: () => void;
onProceed?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
heading: string;

View File

@ -34,6 +34,7 @@ const AddStudentsModal: React.FC<AddStudentsModalPropsType> = ({
const [selected, setSelected] = useState<Array<IUser>>([]);
const handleSelectStudents = (students: Array<IUser>) => setSelected(students);
const handleAttachStudents = async () => {
if (selected.length !== 0) {
try {

View File

@ -60,7 +60,13 @@ const AuthForm: React.FC = () => {
<InputLeftElement>
<Icon as={MdAccountCircle} />
</InputLeftElement>
<Input type='text' placeholder='Login' {...register('login')} isInvalid={!!errors.login} />
<Input
type='text'
placeholder='Login'
{...register('login')}
autoComplete='login'
isInvalid={!!errors.login}
/>
</InputGroup>
<Text as='small' color='red.500'>
{errors.login?.message}
@ -72,6 +78,7 @@ const AuthForm: React.FC = () => {
placeholder='******'
isInvalid={!!errors.password}
errorMessage={errors.password?.message}
autoComplete='current-password'
/>
<Button

View File

@ -32,16 +32,26 @@ type StudentTableListPropsType = {
const StudentTableList: React.FC<StudentTableListPropsType> = props => {
const { render: Row, course } = props;
const [rows, setRows] = useState<ICourse['students']>(props.course.students);
const [selected, setSelected] = useState<ICourse['students']>([]);
const [search, setSearch] = useState<string>('');
const [editing, setEditing] = useState<ICourse['students'][number] | null>(null);
const filteredRows = !search
? rows
: rows.filter(s => s.fullname.toLowerCase().includes(search) || s.email.toLowerCase().includes(search));
/**
* Add students modal
*/
const {
isOpen: isOpenAddStudentModal,
onOpen: onOpenAddStudentModal,
onClose: onCloseAddStudentModal,
} = useDisclosure();
/**
* Edit student modal
*/
const {
isOpen: isOpenEditStudentModal,
onOpen: onOpenEditStudentModal,
@ -50,39 +60,18 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
const { deleteUser } = useDeleteUser();
const { detachStudents } = useDetachStudents();
const isEmptyRows = rows.length === 0;
const isEmptyRows = rows.length === 0 || filteredRows.length === 0;
const isEmptySelected = selected.length === 0;
const isRowSelected = (student: ICourse['students'][number]) => !!selected.find(s => s.id === student.id);
/**
* Search for a student by input
*/
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value);
setRows(
props.course.students.filter(
s => s.fullname.toLowerCase().includes(e.target.value) || s.email.toLowerCase().includes(e.target.value)
)
);
const isRowSelected = (student: ICourse['students'][number]) => {
return !!selected.find(selected => selected.id === student.id);
};
const onRemoved = (removedStudents: ICourse['students']) => {
setSelected(prev => prev.filter(s => removedStudents.every(r => s.id !== r.id)));
const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
setSearch(event.target.value);
};
const onAdded = (users: IUser[]) => {
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
*/
const handleSelectAll = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.checked) {
const handleSelectAll = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.checked) {
setSelected(rows);
return;
}
@ -90,35 +79,30 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
setSelected([]);
};
/**
* Select a student with checkbox
*/
const handleSelect = useCallback((e: React.ChangeEvent<HTMLInputElement>, student: ICourse['students'][number]) => {
if (e.target.checked) {
const handleSelect = useCallback(
(event: React.ChangeEvent<HTMLInputElement>, student: ICourse['students'][number]) => {
if (event.target.checked) {
setSelected(prev => [...prev, student]);
return;
}
setSelected(prev => prev.filter(s => s.id !== student.id));
}, []);
setSelected(prev => prev.filter(selected => selected.id !== student.id));
},
[]
);
/**
* Delete student handler
*/
const handleDelete = (id: string) => {
return async () => {
try {
const deleted = await deleteUser(id);
setRows(prev => prev.filter(s => s.id !== deleted.id));
const deletedStudent = await deleteUser(id);
setRows(prev => prev.filter(student => student.id !== deletedStudent.id));
setSelected(prev => prev.filter(selected => selected.id !== id));
} catch (error) {
console.error(error);
}
};
};
/**
* Edit student handler
*/
const handleEdit = (student: ICourse['students'][number]) => {
return () => {
setEditing(student);
@ -126,20 +110,32 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
};
};
/**
* Remove from course student handler
*/
const handleRemove = (id: string) => {
return async () => {
try {
await detachStudents(course.id, [id]);
setRows(prev => prev.filter(s => s.id !== id));
setRows(prev => prev.filter(student => student.id !== id));
setSelected(prev => prev.filter(selected => selected.id !== id));
} catch (error) {
console.error(error);
}
};
};
const onRemoved = (removedStudents: ICourse['students']) => {
setSelected(prev =>
prev.filter(selected => removedStudents.every(removedStudent => selected.id !== removedStudent.id))
);
};
const onAdded = (users: IUser[]) => {
setRows(prev => [...prev, ...users]);
};
const onEdited = (editedUser: IUser) => {
setRows(prev => prev.map(student => (student.id === editedUser.id ? { ...editedUser } : student)));
};
return (
<Box>
<AddStudentsModal
@ -189,7 +185,7 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
<Table borderRadius='lg' mt='2'>
<StudentTableHead onSelectAll={handleSelectAll} />
<Tbody>
{rows.map(student => (
{filteredRows.map(student => (
<Row
key={student.id}
student={student}

View File

@ -1,7 +1,7 @@
import { AxiosInstance } from 'axios';
import { ApiServiceInstance } from '.';
import * as helpers from '@educt/helpers';
import { IApiRespose, ICourse } from '@educt/interfaces';
import { IApiRespose, ICourse, IUser } from '@educt/interfaces';
import { CourseStatusEnum } from '@educt/enums';
import { CreateCourseParamsType, FetchCoursesParams, UpdateCourseParamsType } from '@educt/types';
@ -119,6 +119,11 @@ class CourseService {
);
return result.data;
}
public async fetchStudentsById(courseId: string): Promise<IApiRespose<Array<IUser>>> {
const result = await this.api.get(`/v1/courses/${courseId}/students`);
return result.data;
}
}
export const CourseServiceInstance = new CourseService(ApiServiceInstance.api);