mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 18:29:15 +03:00
fix: fixed search in students table
This commit is contained in:
parent
1dff6be5e4
commit
d133b69982
@ -16,7 +16,7 @@ import { IconType } from 'react-icons';
|
|||||||
|
|
||||||
export interface IBaseModalProps extends ModalProps {
|
export interface IBaseModalProps extends ModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
isDisabled: boolean;
|
isDisabled?: boolean | undefined;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onProceed?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
onProceed?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
||||||
heading: string;
|
heading: string;
|
||||||
|
|||||||
@ -34,6 +34,7 @@ const AddStudentsModal: React.FC<AddStudentsModalPropsType> = ({
|
|||||||
const [selected, setSelected] = useState<Array<IUser>>([]);
|
const [selected, setSelected] = useState<Array<IUser>>([]);
|
||||||
|
|
||||||
const handleSelectStudents = (students: Array<IUser>) => setSelected(students);
|
const handleSelectStudents = (students: Array<IUser>) => setSelected(students);
|
||||||
|
|
||||||
const handleAttachStudents = async () => {
|
const handleAttachStudents = async () => {
|
||||||
if (selected.length !== 0) {
|
if (selected.length !== 0) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -60,7 +60,13 @@ const AuthForm: React.FC = () => {
|
|||||||
<InputLeftElement>
|
<InputLeftElement>
|
||||||
<Icon as={MdAccountCircle} />
|
<Icon as={MdAccountCircle} />
|
||||||
</InputLeftElement>
|
</InputLeftElement>
|
||||||
<Input type='text' placeholder='Login' {...register('login')} isInvalid={!!errors.login} />
|
<Input
|
||||||
|
type='text'
|
||||||
|
placeholder='Login'
|
||||||
|
{...register('login')}
|
||||||
|
autoComplete='login'
|
||||||
|
isInvalid={!!errors.login}
|
||||||
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<Text as='small' color='red.500'>
|
<Text as='small' color='red.500'>
|
||||||
{errors.login?.message}
|
{errors.login?.message}
|
||||||
@ -72,6 +78,7 @@ const AuthForm: React.FC = () => {
|
|||||||
placeholder='******'
|
placeholder='******'
|
||||||
isInvalid={!!errors.password}
|
isInvalid={!!errors.password}
|
||||||
errorMessage={errors.password?.message}
|
errorMessage={errors.password?.message}
|
||||||
|
autoComplete='current-password'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@ -32,16 +32,26 @@ type StudentTableListPropsType = {
|
|||||||
|
|
||||||
const StudentTableList: React.FC<StudentTableListPropsType> = props => {
|
const StudentTableList: React.FC<StudentTableListPropsType> = props => {
|
||||||
const { render: Row, course } = props;
|
const { render: Row, course } = 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 [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 {
|
const {
|
||||||
isOpen: isOpenAddStudentModal,
|
isOpen: isOpenAddStudentModal,
|
||||||
onOpen: onOpenAddStudentModal,
|
onOpen: onOpenAddStudentModal,
|
||||||
onClose: onCloseAddStudentModal,
|
onClose: onCloseAddStudentModal,
|
||||||
} = useDisclosure();
|
} = useDisclosure();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit student modal
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
isOpen: isOpenEditStudentModal,
|
isOpen: isOpenEditStudentModal,
|
||||||
onOpen: onOpenEditStudentModal,
|
onOpen: onOpenEditStudentModal,
|
||||||
@ -50,39 +60,18 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
|
|||||||
const { deleteUser } = useDeleteUser();
|
const { deleteUser } = useDeleteUser();
|
||||||
const { detachStudents } = useDetachStudents();
|
const { detachStudents } = useDetachStudents();
|
||||||
|
|
||||||
const isEmptyRows = rows.length === 0;
|
const isEmptyRows = rows.length === 0 || filteredRows.length === 0;
|
||||||
const isEmptySelected = selected.length === 0;
|
const isEmptySelected = selected.length === 0;
|
||||||
const isRowSelected = (student: ICourse['students'][number]) => !!selected.find(s => s.id === student.id);
|
const isRowSelected = (student: ICourse['students'][number]) => {
|
||||||
|
return !!selected.find(selected => selected.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 onRemoved = (removedStudents: ICourse['students']) => {
|
const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setSelected(prev => prev.filter(s => removedStudents.every(r => s.id !== r.id)));
|
setSearch(event.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAdded = (users: IUser[]) => {
|
const handleSelectAll = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setRows(prev => [...prev, ...users]);
|
if (event.target.checked) {
|
||||||
};
|
|
||||||
|
|
||||||
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) {
|
|
||||||
setSelected(rows);
|
setSelected(rows);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -90,35 +79,30 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
|
|||||||
setSelected([]);
|
setSelected([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
const handleSelect = useCallback(
|
||||||
* Select a student with checkbox
|
(event: React.ChangeEvent<HTMLInputElement>, student: ICourse['students'][number]) => {
|
||||||
*/
|
if (event.target.checked) {
|
||||||
const handleSelect = useCallback((e: React.ChangeEvent<HTMLInputElement>, student: ICourse['students'][number]) => {
|
|
||||||
if (e.target.checked) {
|
|
||||||
setSelected(prev => [...prev, student]);
|
setSelected(prev => [...prev, student]);
|
||||||
return;
|
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) => {
|
const handleDelete = (id: string) => {
|
||||||
return async () => {
|
return async () => {
|
||||||
try {
|
try {
|
||||||
const deleted = await deleteUser(id);
|
const deletedStudent = await deleteUser(id);
|
||||||
setRows(prev => prev.filter(s => s.id !== deleted.id));
|
setRows(prev => prev.filter(student => student.id !== deletedStudent.id));
|
||||||
|
setSelected(prev => prev.filter(selected => selected.id !== id));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Edit student handler
|
|
||||||
*/
|
|
||||||
const handleEdit = (student: ICourse['students'][number]) => {
|
const handleEdit = (student: ICourse['students'][number]) => {
|
||||||
return () => {
|
return () => {
|
||||||
setEditing(student);
|
setEditing(student);
|
||||||
@ -126,20 +110,32 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove from course student handler
|
|
||||||
*/
|
|
||||||
const handleRemove = (id: string) => {
|
const handleRemove = (id: string) => {
|
||||||
return async () => {
|
return async () => {
|
||||||
try {
|
try {
|
||||||
await detachStudents(course.id, [id]);
|
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) {
|
} catch (error) {
|
||||||
console.error(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 (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<AddStudentsModal
|
<AddStudentsModal
|
||||||
@ -189,7 +185,7 @@ const StudentTableList: React.FC<StudentTableListPropsType> = props => {
|
|||||||
<Table borderRadius='lg' mt='2'>
|
<Table borderRadius='lg' mt='2'>
|
||||||
<StudentTableHead onSelectAll={handleSelectAll} />
|
<StudentTableHead onSelectAll={handleSelectAll} />
|
||||||
<Tbody>
|
<Tbody>
|
||||||
{rows.map(student => (
|
{filteredRows.map(student => (
|
||||||
<Row
|
<Row
|
||||||
key={student.id}
|
key={student.id}
|
||||||
student={student}
|
student={student}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { AxiosInstance } from 'axios';
|
import { AxiosInstance } from 'axios';
|
||||||
import { ApiServiceInstance } from '.';
|
import { ApiServiceInstance } from '.';
|
||||||
import * as helpers from '@educt/helpers';
|
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 { CourseStatusEnum } from '@educt/enums';
|
||||||
import { CreateCourseParamsType, FetchCoursesParams, UpdateCourseParamsType } from '@educt/types';
|
import { CreateCourseParamsType, FetchCoursesParams, UpdateCourseParamsType } from '@educt/types';
|
||||||
|
|
||||||
@ -119,6 +119,11 @@ class CourseService {
|
|||||||
);
|
);
|
||||||
return result.data;
|
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);
|
export const CourseServiceInstance = new CourseService(ApiServiceInstance.api);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user