import { useMutation, useQueries, useQuery } from '@tanstack/react-query'; import type { CourseDetailsResponse } from '../../api/course'; import { cn } from '../../lib/classname'; import { isLoggedIn } from '../../lib/jwt'; import { showLoginPopup } from '../../lib/popup'; import { courseProgressOptions } from '../../queries/course-progress'; import { queryClient } from '../../stores/query-client'; import { useEffect, useState } from 'react'; import { httpPost } from '../../lib/query-http'; import { useToast } from '../../hooks/use-toast'; import { CheckCircle2Icon, Loader2Icon, LockIcon } from 'lucide-react'; import { getUrlParams } from '../../lib/browser'; import { billingDetailsOptions } from '../../queries/billing'; import { UpgradePlanModal } from './UpgradePlanModal'; import { UpgradeAndEnroll } from './UpgradeAndEnroll'; type CourseFloatingSidebarProps = { isSticky: boolean; course: CourseDetailsResponse; }; export function CourseFloatingSidebar(props: CourseFloatingSidebarProps) { const { isSticky, course } = props; const { slug } = course; const courseUrl = `${import.meta.env.PUBLIC_COURSE_APP_URL}/${slug}`; const toast = useToast(); const [isLoading, setIsLoading] = useState(true); const [showUpgradePlanModal, setShowUpgradePlanModal] = useState(false); const [showUpgradeAndEnrollModal, setShowUpgradeAndEnrollModal] = useState(false); const { courseProgress, billingDetails, pending: isPending, } = useQueries( { queries: [ { ...courseProgressOptions(slug), enabled: !!isLoggedIn(), }, { ...billingDetailsOptions(), enabled: !!isLoggedIn(), }, ], combine(results) { return { courseProgress: results[0].data, billingDetails: results[1].data, pending: results.some((result) => result.isPending), }; }, }, queryClient, ); const { mutate: enroll, isPending: isEnrolling } = useMutation( { mutationFn: () => { return httpPost(`/v1-enroll-course/${slug}`, {}); }, onSuccess: () => { window.location.href = courseUrl; }, onError: (error) => { console.error(error); toast.error(error?.message || 'Failed to enroll'); }, }, queryClient, ); const hasEnrolled = courseProgress?.startedAt ? true : false; const isPaidUser = billingDetails?.status === 'active'; useEffect(() => { if (!isLoggedIn()) { setIsLoading(false); return; } if (isPending) { return; } setIsLoading(false); const shouldAutoEnroll = getUrlParams()?.e === '1'; if (!hasEnrolled && shouldAutoEnroll) { setShowUpgradeAndEnrollModal(true); } }, [courseProgress, isPending]); const whatYouGet = [ 'Full access to all the courses', 'Personalized access using AI', 'Certificate of Completion', 'Playground for live-coding', 'Challenges / Quizes', ]; return ( <> {showUpgradePlanModal && ( setShowUpgradePlanModal(false)} success={`/learn/${slug}?e=1`} cancel={`/learn/${slug}`} /> )} {showUpgradeAndEnrollModal && }
SQL 101

What you get

    {whatYouGet.map((item, index) => (
  • {item}
  • ))}
); } type CertificateProps = { isLoading: boolean; hasEnrolled: boolean; isCourseComplete: boolean; courseSlug: string; }; export function Certificate(props: CertificateProps) { const { isLoading, hasEnrolled, isCourseComplete, courseSlug } = props; return ( <>

Certificate of Completion

Certificate will be issued on completion

); }