import {
Box,
Button,
Grid,
Heading,
HStack,
Image,
Table,
TableCaption,
TableContainer,
Tbody,
Td,
Th,
Thead,
Tr,
useDisclosure,
} from '@chakra-ui/react'; // Importing Chakra UI components for styling.
import React, { useState, useEffect } from 'react'; // Importing React, useState, and useEffect for state and lifecycle management.
import { RiDeleteBin7Fill } from 'react-icons/ri'; // Importing delete icon from react-icons.
import { useDispatch, useSelector } from 'react-redux'; // Importing hooks for interacting with Redux state.
import cursor from '../../../assets/images/cursor.png'; // Custom cursor image.
import Sidebar from '../Sidebar'; // Importing Sidebar component.
import CourseModal from './CourseModal'; // Importing CourseModal component for viewing and adding lectures.
import {
getAllCourses,
getCourseLectures,
} from '../../../redux/actions/course'; // Redux actions for getting courses and lectures.
import {
addLecture,
deleteCourse,
deleteLecture,
} from '../../../redux/actions/admin'; // Redux actions for adding/deleting courses/lectures.
import toast from 'react-hot-toast'; // For displaying toast notifications.
const AdminCourses = () => {
// Using Redux selectors to get the state from the Redux store.
const { courses, lectures } = useSelector(state => state.course);
const { loading, error, message } = useSelector(state => state.admin);
const dispatch = useDispatch(); // useDispatch hook for dispatching actions.
const { isOpen, onClose, onOpen } = useDisclosure(); // useDisclosure for handling modal open/close state.
// Local state for managing selected courseId and courseTitle.
const [courseId, setCourseId] = useState('');
const [courseTitle, setCourseTitle] = useState('');
// Function to handle fetching course lectures and opening the modal.
const coureDetailsHandler = (courseId, title) => {
dispatch(getCourseLectures(courseId)); // Dispatches action to fetch course lectures.
onOpen(); // Opens the modal.
setCourseId(courseId); // Sets the selected course ID.
setCourseTitle(title); // Sets the selected course title.
};
// Function to handle deleting a course by courseId.
const deleteButtonHandler = courseId => {
console.log(courseId); // Logs courseId for debugging.
dispatch(deleteCourse(courseId)); // Dispatches action to delete the course.
};
// Function to handle deleting a specific lecture within a course.
const deleteLectureButtonHandler = async (courseId, lectureId) => {
await dispatch(deleteLecture(courseId, lectureId)); // Deletes the lecture.
dispatch(getCourseLectures(courseId)); // Fetches updated lectures for the course.
};
// Function to handle adding a new lecture to a course.
const addLectureHandler = async (e, courseId, title, description, video) => {
e.preventDefault(); // Prevents default form submission behavior.
const myForm = new FormData(); // Creating a FormData object to send file data.
// Appending form data for the lecture.
myForm.append('title', title);
myForm.append('description', description);
myForm.append('file', video);
await dispatch(addLecture(courseId, myForm)); // Dispatches action to add the lecture.
dispatch(getCourseLectures(courseId)); // Fetches updated lectures for the course.
};
// useEffect hook to handle side effects such as error handling and fetching data on component load.
useEffect(() => {
if (error) {
toast.error(error); // Displays an error toast.
dispatch({ type: 'clearError' }); // Clears the error state in Redux.
}
if (message) {
toast.success(message); // Displays a success toast.
dispatch({ type: 'clearMessage' }); // Clears the message state in Redux.
}
dispatch(getAllCourses()); // Dispatches action to get all courses on component mount.
}, [dispatch, error, message, onClose]);
return (
<Grid
css={{
cursor: `url(${cursor}), default`, // Custom cursor for the page.
}}
minH={'100vh'} // Minimum height of 100vh (full viewport height).
templateColumns={['1fr', '5fr 1fr']} // Grid layout: full width on small screens, 5:1 ratio on larger screens.
>
<Box p={['0', '8']} overflowX="auto"> {/* Box for main content with responsive padding */}
<Heading
textTransform={'uppercase'} // Uppercase text for heading.
children="All Courses" // Page heading.
my="16" // Margin for vertical spacing.
textAlign={['center', 'left']} // Responsive text alignment (center on small screens, left on large).
/>
{/* Table containing all the courses */}
<TableContainer w={['100vw', 'full']}>
<Table variant={'simple'} size="lg">
<TableCaption>All available courses in the database</TableCaption> {/* Table caption */}
{/* Table headers */}
<Thead>
<Tr>
<Th>Id</Th>
<Th>Poster</Th>
<Th>Title</Th>
<Th>Category</Th>
<Th>Creator</Th>
<Th isNumeric>Views</Th>
<Th isNumeric>Lectures</Th>
<Th isNumeric>Action</Th>
</Tr>
</Thead>
{/* Table body with dynamic course rows */}
<Tbody>
{courses.map(item => (
<Row
coureDetailsHandler={coureDetailsHandler} // Passes the course details handler.
deleteButtonHandler={deleteButtonHandler} // Passes the delete handler.
key={item._id} // Unique key for each row.
item={item} // The course data.
loading={loading} // Loading state.
/>
))}
</Tbody>
</Table>
</TableContainer>
{/* Course modal to manage lectures for the selected course */}
<CourseModal
isOpen={isOpen}
onClose={onClose}
id={courseId}
courseTitle={courseTitle}
deleteButtonHandler={deleteLectureButtonHandler}
addLectureHandler={addLectureHandler}
lectures={lectures}
loading={loading}
/>
</Box>
{/* Sidebar for navigation (on the right side of the screen) */}
<Sidebar />
</Grid>
);
};
// Row component to render each row in the courses table.
function Row({ item, coureDetailsHandler, deleteButtonHandler, loading }) {
return (
<Tr>
<Td>#{item._id}</Td> {/* Course ID */}
<Td>
<Image src={item.poster.url} /> {/* Course poster image */}
</Td>
<Td>{item.title}</Td> {/* Course title */}
<Td textTransform={'uppercase'}>{item.category}</Td> {/* Course category */}
<Td>{item.createdBy}</Td> {/* Course creator */}
<Td isNumeric>{item.views}</Td> {/* Number of views (numeric) */}
<Td isNumeric>{item.numOfVideos}</Td> {/* Number of lectures (numeric) */}
{/* Action buttons to view lectures or delete the course */}
<Td isNumeric>
<HStack justifyContent={'flex-end'}>
<Button
onClick={() => coureDetailsHandler(item._id, item.title)} // View lectures button.
variant={'outline'}
color="purple.500"
isLoading={loading}
>
View Lectures
</Button>
<Button
onClick={() => deleteButtonHandler(item._id)} // Delete course button.
color={'purple.600'}
isLoading={loading}
>
<RiDeleteBin7Fill /> {/* Delete icon */}
</Button>
</HStack>
</Td>
</Tr>
);
}
export default AdminCourses; // Exporting the AdminCourses component.
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)