Snai3i-MarketPlace / frontend / src / pages / Dashboard / Snai3iCourses / CreateSnai3iCourse / index.tsx
index.tsx
Raw
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';

import Details from './components/Details';
import Chapters from './components/Chapters';
import { Button } from '@/components/ui/button';
import { useEffect, useState } from 'react';
import { toast } from 'sonner';
import {
  useCreateSnai3iCourseMutation,
  useGetSnai3iCourseByIdQuery,
  useUpdateSnai3iCourseMutation,
} from '@/app/backend/endpoints/courses';
import { useNavigate, useParams } from 'react-router-dom';
import Fallback from '@/components/Fallback';
import useCourse from '@/hooks/useCourse';
import useTitle from '@/hooks/useTitle';

function CreateSnai3iCourse({ isEdit }: { isEdit?: boolean }) {
  useTitle('Create Snai3i Course');
  const { course, setCourse, resetState } = useCourse();
  const { courseId } = useParams();
  const navigate = useNavigate();

  const { data: courseDataWrap, isLoading: isGetLoading } =
    useGetSnai3iCourseByIdQuery(parseInt(courseId ?? ''), { skip: !isEdit });
  const courseData = courseDataWrap?.data;

  const [isUploading, setIsUploading] = useState(false);

  useEffect(() => {
    if (courseData !== undefined && isEdit) {
      setCourse(courseData);
    }
    return () => {
      resetState();
    };
  }, [courseData]);

  const [createCourse, { isLoading }] = useCreateSnai3iCourseMutation();
  const [updateCourse, { isLoading: isUpdating }] =
    useUpdateSnai3iCourseMutation();

  const [isImageValid, setIsImageValid] = useState(false);

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    if (course.thumbnail === '') {
      setIsImageValid(false);
      toast.error('Please upload a thumbnail');
      return;
    }
    if (course.title === '') {
      toast.error('Please enter the course title');
      return;
    }

    // check if there are any empty chapters or videos
    const emptyChapters = course.chapters?.filter((chapter) => {
      const emptyVideosOrDocs = chapter.data.filter((data) => {
        return data.title === '' || data.url === '';
      });
      return chapter.title === '' || emptyVideosOrDocs.length > 0;
    });
    if (emptyChapters!.length > 0) {
      toast.error('Please fill in all chapter and video/document titles');
      return;
    }

    if (isEdit) {
      updateCourse(course)
        .unwrap()
        .then((response) => {
          toast.success(response.message);
          navigate('/dashboard/snai3i-courses/list');
        })
        .catch((error: any) => {
          toast.error(error?.data?.message ?? error?.error.toString());
        });
    } else {
      createCourse(course)
        .unwrap()
        .then((response) => {
          toast.success(response.message);
          navigate('/dashboard/snai3i-courses/list');
        })
        .catch((error: any) => {
          toast.error(error?.data?.message ?? error?.error.toString());
        });
    }
  };

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      e.preventDefault();
    }
  };
  if (isEdit && isGetLoading) return <Fallback />;
  return (
    <section>
      <form onSubmit={handleSubmit}>
        <div className="flex justify-between items-center gap-4 py-2">
          <span className="text-slate-600 text-[25px] font-semibold">
            Create Snai3i Course
          </span>
          <div className="space-x-2">
            <Button
              variant="outline"
              className="font-semibold font-inter rounded-md"
              type="button"
              onClick={() => navigate('/dashboard/snai3i-courses/list')}
            >
              Cancel
            </Button>
            <Button
              type="submit"
              className="bg-amber-500 rounded-md font-semibold font-inter text-white"
              isLoading={isLoading || isGetLoading || isUpdating}
              disabled={isUploading}
            >
              Save
            </Button>
          </div>
        </div>
        <Tabs
          defaultValue="details"
          className="flex flex-col items-center py-2"
        >
          <TabsList className="flex justify-center w-fit">
            <TabsTrigger value="details" className="font-semibold">
              Details
            </TabsTrigger>
            <TabsTrigger value="chapters" className="font-semibold">
              Chapters
            </TabsTrigger>
          </TabsList>
          <TabsContent value="details" className="w-full">
            <Details
              handleKeyDown={handleKeyDown}
              isImageValid={isImageValid}
              setIsImageValid={setIsImageValid}
              isUploading={isUploading}
              setIsUploading={setIsUploading}
            />
          </TabsContent>
          <TabsContent value="chapters" className="w-full">
            <Chapters handleKeyDown={handleKeyDown} />
          </TabsContent>
        </Tabs>
      </form>
    </section>
  );
}

export default CreateSnai3iCourse;