Skip to content

Commit

Permalink
Merge pull request #27 from abinth11/features-admin-student-management
Browse files Browse the repository at this point in the history
Features admin student management
  • Loading branch information
abinth11 authored Jul 20, 2023
2 parents 49524ea + 55978c7 commit 492762d
Show file tree
Hide file tree
Showing 18 changed files with 960 additions and 15 deletions.
23 changes: 23 additions & 0 deletions client/src/api/endpoints/studentManagement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
getAllStudentsService,
blockStudentService,
unblockStudentService,
getAllBlockedStudentsService,
} from "../services/studentManageService";
import END_POINTS from "../../constants/endpoints";

export const getAllStudents = () => {
return getAllStudentsService(END_POINTS.GET_ALL_STUDENTS);
};

export const blockStudents = (studentId:string,reason: string) => {
return blockStudentService(END_POINTS.BLOCK_STUDENT,studentId, reason);
};

export const unblockStudent = (studentId:string) => {
return unblockStudentService(END_POINTS.UNBLOCK_STUDENT,studentId);
};

export const getAllBlockedStudents = ()=>{
return getAllBlockedStudentsService(END_POINTS.GET_BLOCKED_STUDENTS)
}
1 change: 0 additions & 1 deletion client/src/api/middlewares/protectedInterceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ api.interceptors.response.use(
);
return api(originalRequest);
} catch (err) {
console.log(err);
return Promise.reject(err);
}
}
Expand Down
38 changes: 38 additions & 0 deletions client/src/api/services/studentManageService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import CONSTANTS_COMMON from "../../constants/common";
import api from "../middlewares/protectedInterceptor";

export const blockStudentService = async (
endpoint: string,
studentId: string,
reason: string
) => {
const response = await api.patch(
`${CONSTANTS_COMMON.API_BASE_URL}/${endpoint}/${studentId}`,
{ reason }
);
return response.data;
};

export const unblockStudentService = async (
endpoint: string,
studentId: string
) => {
const response = await api.patch(
`${CONSTANTS_COMMON.API_BASE_URL}/${endpoint}/${studentId}`
);
return response.data;
};

export const getAllStudentsService = async (endpoint: string) => {
const response = await api.get(
`${CONSTANTS_COMMON.API_BASE_URL}/${endpoint}`
);
return response.data;
};

export const getAllBlockedStudentsService = async (endpoint: string) => {
const response = await api.get(
`${CONSTANTS_COMMON.API_BASE_URL}/${endpoint}`
);
return response.data;
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { InstructorApiResponse } from "../../../api/types/apiResponses/apiRespon



const ViewMoreInstructorRequest: React.FC = () => {
const ViewMoreInstructorRequest: React.FC = () => {
const { id } = useParams();
const [instructor, setInstructor] = useState<InstructorApiResponse>();
const [open, setOpen] = useState<boolean>(false)
Expand Down
138 changes: 138 additions & 0 deletions client/src/components/pages/studentManagement/BlockStudentModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { Fragment, useRef, useState } from "react";
import { Dialog, Transition } from "@headlessui/react";
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
import { SetStateAction, Dispatch } from "react";
import {toast} from 'react-toastify'
import { blockStudents } from "../../../api/endpoints/studentManagement";
interface ModalProps {
open:boolean;
setOpen: Dispatch<SetStateAction<boolean>>;
updated:boolean;
setUpdated:Dispatch<SetStateAction<boolean>>;
id:string
};
export default function BlockStudentModal({open,setOpen,updated,setUpdated,id}:ModalProps) {
const cancelButtonRef = useRef(null);
const [selectedReason, setSelectedReason] = useState("");

const reasons = [
"posted wrong comments",
"Violated the rules",
"others",
];

const handleBlock = async (studentId: string, reason: string) => {
try {
const response = await blockStudents(studentId, reason);
toast.success(response?.message, {
position: toast.POSITION.BOTTOM_RIGHT,
});
setUpdated(!updated)

} catch (error: any) {
toast.error(error.data.message, {
position: toast.POSITION.BOTTOM_RIGHT,
});
}
};

return (
<Transition.Root show={open} as={Fragment}>
<Dialog
as='div'
className='relative z-20'
initialFocus={cancelButtonRef}
onClose={setOpen}
>
<Transition.Child
as={Fragment}
enter='ease-out duration-300'
enterFrom='opacity-0'
enterTo='opacity-100'
leave='ease-in duration-200'
leaveFrom='opacity-100'
leaveTo='opacity-0'
>
<div className='fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity' />
</Transition.Child>

<div className='fixed inset-0 z-50 overflow-y-auto'>
<div className='flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0'>
<Transition.Child
as={Fragment}
enter='ease-out duration-300'
enterFrom='opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95'
enterTo='opacity-100 translate-y-0 sm:scale-100'
leave='ease-in duration-200'
leaveFrom='opacity-100 translate-y-0 sm:scale-100'
leaveTo='opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95'
>
<Dialog.Panel className='relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg z-50'>
<div className='bg-white px-4 pb-4 pt-5 sm:p-6 sm:pb-4'>
<div className='sm:flex sm:items-start'>
<div className='mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10'>
<ExclamationTriangleIcon
className='h-6 w-6 text-red-600'
aria-hidden='true'
/>
</div>
<div className='mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left'>
<Dialog.Title
as='h3'
className='text-base font-semibold leading-6 text-gray-900'
>
Block Student
</Dialog.Title>
<div className='mt-2'>
<label
htmlFor='reason'
className='block text-sm font-medium text-gray-700'
>
Reason for blocking the Student
</label>
<select
id='reason'
name='reason'
value={selectedReason}
onChange={(e) => setSelectedReason(e.target.value)}
className='mt-1 block w-full py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm'
>
<option value=''>Select a reason</option>
{reasons.map((reason) => (
<option key={reason} value={reason}>
{reason}
</option>
))}
</select>
</div>
</div>
</div>
</div>
<div className='bg-gray-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6'>
<button
type='button'
className='inline-flex w-full justify-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 sm:ml-3 sm:w-auto'
onClick={()=>{
handleBlock(id,selectedReason)
setOpen(false)
}}
>
Block
</button>
<button
type='button'
className='mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto'
onClick={() => setOpen(false)}
ref={cancelButtonRef}
>
Cancel
</button>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
}
Loading

0 comments on commit 492762d

Please sign in to comment.