DEV Community

Navnit Rai
Navnit Rai

Posted on

CourseModal

import {
  Box,
  Button,
  Grid,
  Heading,
  Input,
  Modal,
  ModalBody,
  ModalCloseButton,
  ModalContent,
  ModalFooter,
  ModalHeader,
  ModalOverlay,
  Stack,
  Text,
  VStack,
} from '@chakra-ui/react'; // Importing Chakra UI components.
import React, { useState } from 'react'; // Importing React and useState for local state management.
import { RiDeleteBin7Fill } from 'react-icons/ri'; // Importing delete icon from react-icons.
import { fileUploadCss } from '../../Auth/Register'; // Custom CSS for file input.

const CourseModal = ({
  isOpen,              // Modal open state.
  onClose,             // Function to close the modal.
  id,                  // Course ID.
  deleteButtonHandler, // Handler function to delete a lecture.
  addLectureHandler,   // Handler function to add a lecture.
  courseTitle,         // Title of the course.
  lectures = [],       // List of lectures for the course.
  loading,             // Loading state to disable actions when processing.
}) => {
  // Local state to manage form inputs for adding a new lecture.
  const [title, setTitle] = useState(''); // Lecture title.
  const [description, setDescription] = useState(''); // Lecture description.
  const [video, setVideo] = useState(''); // Video file to be uploaded.
  const [videoPrev, setVideoPrev] = useState(''); // Preview URL for the selected video.

  // Handler for video file input, converting the video to a preview URL.
  const changeVideoHandler = e => {
    const file = e.target.files[0]; // Get the selected file.
    const reader = new FileReader();

    reader.readAsDataURL(file); // Read the file as a data URL.

    reader.onloadend = () => {
      setVideoPrev(reader.result); // Set the video preview.
      setVideo(file); // Set the video file.
    };
  };

  // Function to reset the form and close the modal.
  const handleClose = () => {
    setTitle('');        // Reset title.
    setDescription('');  // Reset description.
    setVideo('');        // Reset video file.
    setVideoPrev('');    // Reset video preview.
    onClose();           // Close the modal.
  };

  return (
    <Modal
      isOpen={isOpen}              // Modal is open or not.
      size="full"                  // Modal size is full screen.
      onClose={handleClose}        // Close modal function.
      scrollBehavior="outside"     // Allow scrolling outside the modal content.
    >
      <ModalOverlay />              {/* Background overlay for modal. */}

      <ModalContent>
        <ModalHeader>{courseTitle}</ModalHeader> {/* Modal header shows the course title */}
        <ModalCloseButton /> {/* Button to close the modal */}

        <ModalBody p="16">
          <Grid templateColumns={['1fr', '3fr 1fr']}> {/* Responsive grid layout for content */}
            {/* Left side of modal: course details and lectures list */}
            <Box px={['0', '16']}>
              <Box my="5">
                <Heading children={courseTitle} /> {/* Display course title */}
                <Heading children={`#${id}`} size="sm" opacity={0.4} /> {/* Display course ID */}
              </Box>

              <Heading children={'Lectures'} size="lg" /> {/* Section for lectures */}

              {/* List of lectures for the course */}
              {lectures.map((item, i) => (
                <VideoCard
                  key={i}
                  title={item.title}
                  description={item.description}
                  num={i + 1} /* Lecture number */
                  lectureId={item._id} /* ID of the lecture */
                  courseId={id} /* ID of the course */
                  deleteButtonHandler={deleteButtonHandler} /* Pass the delete handler */
                  loading={loading} /* Pass the loading state */
                />
              ))}
            </Box>

            {/* Right side of modal: form to add a new lecture */}
            <Box>
              <form
                onSubmit={e =>
                  addLectureHandler(e, id, title, description, video) /* Handles lecture addition */
                }
              >
                <VStack spacing={'4'}>
                  <Heading
                    children="Add Lecture" /* Section heading */
                    size={'md'}
                    textTransform="uppercase"
                  />

                  {/* Input for lecture title */}
                  <Input
                    focusBorderColor="purple.300" /* Color on focus */
                    placeholder="Title"
                    value={title} /* Controlled input value */
                    onChange={e => setTitle(e.target.value)} /* Updates title state */
                  />

                  {/* Input for lecture description */}
                  <Input
                    focusBorderColor="purple.300"
                    placeholder="Description"
                    value={description} /* Controlled input value */
                    onChange={e => setDescription(e.target.value)} /* Updates description state */
                  />

                  {/* File input for video upload */}
                  <Input
                    accept="video/mp4" /* Only accepts mp4 videos */
                    required
                    type={'file'}
                    focusBorderColor="purple.300"
                    css={{
                      '&::file-selector-button': {
                        ...fileUploadCss, /* Custom file upload CSS */
                        color: 'purple',
                      },
                    }}
                    onChange={changeVideoHandler} /* Video file change handler */
                  />

                  {/* Display video preview if a video is selected */}
                  {videoPrev && (
                    <video
                      controlsList="nodownload" /* Disable video download */
                      controls
                      src={videoPrev} /* Video preview source */
                    ></video>
                  )}

                  {/* Button to upload the lecture */}
                  <Button
                    isLoading={loading} /* Shows loading spinner when loading */
                    w="full" /* Full width button */
                    colorScheme={'purple'} /* Purple button style */
                    type="submit" /* Submit button for form */
                  >
                    Upload
                  </Button>
                </VStack>
              </form>
            </Box>
          </Grid>
        </ModalBody>

        {/* Footer with close button */}
        <ModalFooter>
          <Button onClick={handleClose}>Close</Button> {/* Close modal button */}
        </ModalFooter>
      </ModalContent>
    </Modal>
  );
};

export default CourseModal; // Export the CourseModal component.

/* VideoCard component to display individual lecture information with a delete button */
function VideoCard({
  title,
  description,
  num,                // Lecture number.
  lectureId,          // Lecture ID.
  courseId,           // Course ID.
  deleteButtonHandler,// Function to delete the lecture.
  loading,            // Loading state to disable buttons when processing.
}) {
  return (
    <Stack
      direction={['column', 'row']} /* Responsive layout: column on small screens, row on larger */
      my="8" /* Margin */
      borderRadius={'lg'} /* Rounded corners */
      boxShadow={'0 0 10px rgba(107,70,193,0.5)'} /* Box shadow for styling */
      justifyContent={['flex-start', 'space-between']} /* Responsive content alignment */
      p={['4', '8']} /* Padding */
    >
      <Box>
        <Heading size={'sm'} children={`#${num} ${title}`} /> {/* Display lecture number and title */}
        <Text children={description} /> {/* Display lecture description */}
      </Box>

      {/* Button to delete the lecture */}
      <Button
        isLoading={loading} /* Show loading spinner if loading */
        color={'purple.600'} /* Purple color */
        onClick={() => deleteButtonHandler(courseId, lectureId)} /* Delete handler */
      >
        <RiDeleteBin7Fill /> {/* Trash bin icon for delete */}
      </Button>
    </Stack>
  );
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)