import {
Button,
Container,
Heading,
HStack,
Image,
Input,
Stack,
Text,
VStack,
} from '@chakra-ui/react'; // Importing Chakra UI components for styling
import React, { useEffect, useState } from 'react'; // Importing React and hooks
import { Link } from 'react-router-dom'; // For routing
import { useDispatch, useSelector } from 'react-redux'; // For accessing Redux state and dispatch
import { getAllCourses } from '../../redux/actions/course'; // Action to fetch courses
import toast from 'react-hot-toast'; // For notifications
import { addToPlaylist } from '../../redux/actions/profile'; // Action to add course to playlist
import { loadUser } from '../../redux/actions/user'; // Action to load user data
// Component to display individual course details
const Course = ({
views,
title,
imageSrc,
id,
addToPlaylistHandler,
creator,
description,
lectureCount,
loading,
}) => {
return (
<VStack className="course" alignItems={['center', 'flex-start']}>
<Image src={imageSrc} boxSize="60" objectFit={'contain'} /> {/* Course image */}
<Heading
textAlign={['center', 'left']}
maxW="200px"
size={'sm'}
fontFamily={'sans-serif'}
noOfLines={3
} // Title with line limit
children={title}
/>
<Text noOfLines={2} children={description} /> {/* Course description */}
<HStack>
<Text
fontWeight={'bold'}
textTransform="uppercase"
children={'Creator'}
/>
<Text
fontFamily={'body'}
textTransform="uppercase"
children={creator} // Course creator's name
/>
</HStack>
<Heading
textAlign={'center'}
size="xs"
children={`Lectures - ${lectureCount}`} // Number of lectures
textTransform="uppercase"
/>
<Heading
size="xs"
children={`Views - ${views}`} // Number of views
textTransform="uppercase"
/>
<Stack direction={['column', 'row']} alignItems="center">
<Link to={`/course/${id}`}> {/* Link to the course details page */}
<Button colorScheme={'yellow'}>Watch Now</Button>
</Link>
<Button
isLoading={loading} // Loading state for button
variant={'ghost'}
colorScheme={'yellow'}
onClick={() => addToPlaylistHandler(id)} // Add course to playlist
>
Add to playlist
</Button>
</Stack>
</VStack>
);
};
// Main component to display all courses
const Courses = () => {
const [keyword, setKeyword] = useState(''); // State for search keyword
const [category, setCategory] = useState(''); // State for selected category
const dispatch = useDispatch(); // Accessing dispatch function
// Handler for adding course to playlist
const addToPlaylistHandler = async courseId => {
await dispatch(addToPlaylist(courseId)); // Dispatch add to playlist action
dispatch(loadUser()); // Reload user data
};
// Predefined categories for filtering courses
const categories = [
'Web development',
'Artificial Intelligence',
'Data Structure & Algorithm',
'App Development',
'Data Science',
'Game Development',
];
const { loading, courses, error, message } = useSelector(
state => state.course // Accessing course-related state from Redux
);
// Effect to fetch courses based on keyword and category
useEffect(() => {
dispatch(getAllCourses(category, keyword)); // Fetch courses
// Handle error messages
if (error) {
toast.error(error); // Show error notification
dispatch({ type: 'clearError' }); // Clear error from state
}
// Handle success messages
if (message) {
toast.success(message); // Show success notification
dispatch({ type: 'clearMessage' }); // Clear message from state
}
}, [category, keyword, dispatch, error, message]); // Dependencies for the effect
return (
<Container minH={'95vh'} maxW="container.lg" paddingY={'8'}>
<Heading children="All Courses" m={'8'} /> {/* Main heading for the page */}
<Input
value={keyword} // Controlled input value for search
onChange={e => setKeyword(e.target.value)} // Update keyword on change
placeholder="Search a course..."
type={'text'}
focusBorderColor="yellow.500" // Border color on focus
/>
<HStack
overflowX={'auto'} // Allow horizontal scrolling for categories
paddingY="8"
css={{
'&::-webkit-scrollbar': {
display: 'none', // Hide scrollbar
},
}}
>
{categories.map((item, index) => (
<Button key={index} onClick={() => setCategory(item)} minW={'60'}>
<Text children={item} /> {/* Category button */}
</Button>
))}
</HStack>
<Stack
direction={['column', 'row']}
flexWrap="wrap"
justifyContent={['flex-start', 'space-evenly']} // Responsive layout for courses
alignItems={['center', 'flex-start']}
>
{courses.length > 0 ? ( // Conditional rendering based on courses availability
courses.map(item => (
<Course
key={item._id} // Unique key for each course
title={item.title}
description={item.description}
views={item.views}
imageSrc={item.poster.url}
id={item._id}
creator={item.createdBy}
lectureCount={item.numOfVideos}
addToPlaylistHandler={addToPlaylistHandler}
loading={loading}
/>
))
) : (
<Heading mt="4" children="Courses Not Found" /> // Message when no courses are found
)}
</Stack>
</Container>
);
};
export default Courses; // Exporting Courses component
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)