diff --git a/src/components/Modals/AddStudentsModal/AddSudentsModal.tsx b/src/components/Modals/AddStudentsModal/AddSudentsModal.tsx index bff81d3..f7e56ed 100644 --- a/src/components/Modals/AddStudentsModal/AddSudentsModal.tsx +++ b/src/components/Modals/AddStudentsModal/AddSudentsModal.tsx @@ -3,19 +3,27 @@ import React, { useState } from 'react'; import BaseModal from '@educt/components/Modal'; import { MdGroup } from 'react-icons/md'; import { UserRoleEnum } from '@educt/enums'; -import SelectUsersInput from '@educt/components/SelectUsersInput'; -import { IUser } from '@educt/interfaces'; +import SelectStudentsInput from '@educt/components/SelectStudentsInput'; +import { ICourse, IUser } from '@educt/interfaces'; import { CourseServiceInstance } from '@educt/services'; import { useToast } from '@chakra-ui/react'; import useIsMountedRef from '@educt/hooks/useIsMountedRef'; type AddStudentsModalPropsType = { + course: Omit; + currentStudents: ICourse['students']; isOpen: boolean; onClose: () => void; - courseId: string; + onAdded: (users: Array) => void; }; -const AddStudentsModal: React.FC = ({ isOpen, onClose, courseId }) => { +const AddStudentsModal: React.FC = ({ + isOpen, + onClose, + onAdded, + currentStudents, + course, +}) => { const [isLoading, setIsLoading] = useState(false); const isMountedRef = useIsMountedRef(); const [students, setStudents] = useState>([]); @@ -27,9 +35,10 @@ const AddStudentsModal: React.FC = ({ isOpen, onClose try { setIsLoading(true); const ids = students.map(s => s.id); - await CourseServiceInstance.attachStudentsList(courseId, ids); + await CourseServiceInstance.attachStudentsList(course.id, ids); - toast({ title: 'Students successfully added.', status: 'success' }); + toast({ title: 'Students added.', status: 'info' }); + onAdded(students); onClose(); } catch (error) { console.error(error); @@ -51,7 +60,8 @@ const AddStudentsModal: React.FC = ({ isOpen, onClose isLoading={isLoading} loadingText='Saving...' > - handleSelectStudents(selected)} placeholder='Search for students...' searchParams={{ role: UserRoleEnum.STUDENT }} diff --git a/src/components/SelectUsersInput/SelectUsersInput.tsx b/src/components/SelectStudentsInput/SelectStudentsInput.tsx similarity index 93% rename from src/components/SelectUsersInput/SelectUsersInput.tsx rename to src/components/SelectStudentsInput/SelectStudentsInput.tsx index 17ca8fd..74d8904 100644 --- a/src/components/SelectUsersInput/SelectUsersInput.tsx +++ b/src/components/SelectStudentsInput/SelectStudentsInput.tsx @@ -16,7 +16,7 @@ import { } from '@chakra-ui/react'; import { AddIcon, SearchIcon } from '@chakra-ui/icons'; import { UserServiceInstance } from '@educt/services'; -import { IUser } from '@educt/interfaces'; +import { ICourse, IUser } from '@educt/interfaces'; import { useErrorHandler } from 'react-error-boundary'; import { BeatLoader } from 'react-spinners'; import { Virtuoso } from 'react-virtuoso'; @@ -26,14 +26,22 @@ type SelectUsersInputPropsType = { placeholder?: string | undefined; searchParams?: FetchUsersParamsType | undefined; onSelect: (selected: Array) => void; + currentStudents: ICourse['students']; }; -const SelectUsersInput: React.FC = ({ placeholder, searchParams: params, onSelect }) => { +const SelectUsersInput: React.FC = ({ + placeholder, + searchParams: params, + onSelect, + currentStudents, +}) => { const [isLoading, setIsLoading] = useState(false); const [search, setSearch] = useState(''); const [selected, setSelected] = useState>([]); const [users, setUsers] = useState>([]); - const filtered = users.filter(u => selected.every(s => s.id !== u.id)); + const filtered = users + .filter(u => selected.every(s => s.id !== u.id)) + .filter(u => currentStudents.every(s => s.id !== u.id)); const handleError = useErrorHandler(); const isEmpty = filtered.length === 0; diff --git a/src/components/SelectStudentsInput/index.ts b/src/components/SelectStudentsInput/index.ts new file mode 100644 index 0000000..7c1da77 --- /dev/null +++ b/src/components/SelectStudentsInput/index.ts @@ -0,0 +1,3 @@ +import SelectStudentsInput from './SelectStudentsInput'; + +export default SelectStudentsInput; diff --git a/src/components/SelectUsersInput/index.ts b/src/components/SelectUsersInput/index.ts deleted file mode 100644 index 26a35e0..0000000 --- a/src/components/SelectUsersInput/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import SelectUsersInput from './SelectUsersInput'; - -export default SelectUsersInput; diff --git a/src/pages/courses/edit/components/StudentTableList/Cells/index.tsx b/src/pages/courses/edit/components/StudentTableList/Cells/index.tsx index fbc067d..1e520ea 100644 --- a/src/pages/courses/edit/components/StudentTableList/Cells/index.tsx +++ b/src/pages/courses/edit/components/StudentTableList/Cells/index.tsx @@ -51,15 +51,23 @@ export const RegisteredCell: React.FC = memo(({ registe {new Date(registered).toLocaleDateString()} )); -type ActionsCellPropsType = Pick; -export const ActionsCell: React.FC = memo(({ id }) => ( +type ActionsCellPropsType = { + onEdit: () => void; + onRemove: () => void; + onDelete: () => void; +}; +export const ActionsCell: React.FC = memo(({ onEdit, onRemove, onDelete }) => ( } variant='ghost' /> - }>Edit - }>Remove from course - } color='red.400'> + }> + Edit + + }> + Remove from course + + } color='red.400'> Delete diff --git a/src/pages/courses/edit/components/StudentTableList/StudentTableList.tsx b/src/pages/courses/edit/components/StudentTableList/StudentTableList.tsx index 3a2a6f4..5ca7191 100644 --- a/src/pages/courses/edit/components/StudentTableList/StudentTableList.tsx +++ b/src/pages/courses/edit/components/StudentTableList/StudentTableList.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import { Table, Tbody, Button, Input, InputGroup, InputLeftElement, Flex, Box, Text } from '@chakra-ui/react'; +import { Table, Tbody, Button, Input, InputGroup, InputLeftElement, Flex, Box, Text, useToast } from '@chakra-ui/react'; import { MdSearch } from 'react-icons/md'; - import AddStudentsModal from '@educt/components/Modals/AddStudentsModal'; +import { BeatLoader } from 'react-spinners'; import { AddButton } from '@educt/components/Buttons'; import BulkActionsMenu from './BulkActionsMenu'; import StudentTableHead from './StudentTableHead'; @@ -18,6 +18,7 @@ import type { ICourse } from '@educt/interfaces'; */ import { useCallback, useState } from 'react'; import { useDisclosure } from '@chakra-ui/react'; +import { UserServiceInstance } from '@educt/services'; type StudentTableListPropsType = { render: React.FC; @@ -28,6 +29,7 @@ const StudentTableList: React.FC = props => { const { render: Row, course } = props; const { students } = course; + const [isLoading, setIsLoading] = useState(false); const [rows, setRows] = useState(students); const [selected, setSelected] = useState([]); const [search, setSearch] = useState(''); @@ -36,6 +38,7 @@ const StudentTableList: React.FC = props => { onOpen: onOpenAddStudentModal, onClose: onCloseAddStudentModal, } = useDisclosure(); + const toast = useToast(); /** * Search for a student by input @@ -73,10 +76,52 @@ const StudentTableList: React.FC = props => { setSelected(prev => prev.filter(s => s.id !== student.id)); }, []); + /** + * Delete student handler + */ + const handleDelete = (id: string) => { + return async () => { + try { + setIsLoading(true); + const { data } = await UserServiceInstance.delete(id); + toast({ title: 'Student deleted', status: 'info' }); + setRows(prev => prev.filter(s => s.id !== data.id)); + } catch (error) { + console.error(error); + } finally { + setIsLoading(false); + } + }; + }; + + /** + * Edit student handler + */ + const handleEdit = (id: string) => { + return () => { + console.log(`editing id: ${id}`); + }; + }; + + /** + * Remove from course student handler + */ + const handleRemove = (id: string) => { + return () => { + console.log(`removing id: ${id}`); + }; + }; + if (rows.length === 0) { return ( <> - + setRows(prev => [...prev, ...users])} + /> There are no students in the course yet