mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-30 04:30:01 +02:00
Add course video on the course landing page
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||||
import { ArrowRightIcon } from 'lucide-react';
|
import { ArrowRightIcon, Play } from 'lucide-react';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { cn } from '../../lib/classname';
|
import { cn } from '../../lib/classname';
|
||||||
import {
|
import {
|
||||||
@@ -14,6 +14,7 @@ import { CourseLoginPopup } from '../AuthenticationFlow/CourseLoginPopup';
|
|||||||
import { useToast } from '../../hooks/use-toast';
|
import { useToast } from '../../hooks/use-toast';
|
||||||
import { httpPost } from '../../lib/query-http';
|
import { httpPost } from '../../lib/query-http';
|
||||||
import { deleteUrlParam, getUrlParams } from '../../lib/browser';
|
import { deleteUrlParam, getUrlParams } from '../../lib/browser';
|
||||||
|
import { VideoModal } from '../VideoModal';
|
||||||
|
|
||||||
export const SQL_COURSE_SLUG = 'sql';
|
export const SQL_COURSE_SLUG = 'sql';
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ export function BuyButton(props: BuyButtonProps) {
|
|||||||
const { variant = 'main' } = props;
|
const { variant = 'main' } = props;
|
||||||
|
|
||||||
const [isLoginPopupOpen, setIsLoginPopupOpen] = useState(false);
|
const [isLoginPopupOpen, setIsLoginPopupOpen] = useState(false);
|
||||||
|
const [isVideoModalOpen, setIsVideoModalOpen] = useState(false);
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
|
||||||
const { data: coursePricing, isLoading: isLoadingCourse } = useQuery(
|
const { data: coursePricing, isLoading: isLoadingCourse } = useQuery(
|
||||||
@@ -164,6 +166,12 @@ export function BuyButton(props: BuyButtonProps) {
|
|||||||
return (
|
return (
|
||||||
<div className="relative flex w-full flex-col items-center gap-2 md:w-auto">
|
<div className="relative flex w-full flex-col items-center gap-2 md:w-auto">
|
||||||
{courseLoginPopup}
|
{courseLoginPopup}
|
||||||
|
{isVideoModalOpen && (
|
||||||
|
<VideoModal
|
||||||
|
videoId="6S1CcF-ngeQ"
|
||||||
|
onClose={() => setIsVideoModalOpen(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={onBuyClick}
|
onClick={onBuyClick}
|
||||||
disabled={isLoadingPricing}
|
disabled={isLoadingPricing}
|
||||||
@@ -200,8 +208,14 @@ export function BuyButton(props: BuyButtonProps) {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{!isLoadingPricing && (
|
{!isLoadingPricing && (
|
||||||
<span className="absolute top-full translate-y-2.5 text-sm text-yellow-400">
|
<span className="absolute top-full z-50 flex w-[300px] translate-y-3 flex-row items-center justify-center text-sm text-yellow-400">
|
||||||
Lifetime access <span className="mx-1">·</span> Free updates
|
Lifetime access <span className="mx-2">·</span>{' '}
|
||||||
|
<button
|
||||||
|
onClick={() => setIsVideoModalOpen(true)}
|
||||||
|
className="flex cursor-pointer flex-row items-center gap-1.5 underline underline-offset-4 hover:text-yellow-500"
|
||||||
|
>
|
||||||
|
<Play className="size-3 fill-current" /> Watch Video (3 min)
|
||||||
|
</button>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
28
src/components/VideoModal.tsx
Normal file
28
src/components/VideoModal.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { Modal } from './Modal';
|
||||||
|
|
||||||
|
type VideoModalProps = {
|
||||||
|
videoId: string;
|
||||||
|
onClose: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function VideoModal(props: VideoModalProps) {
|
||||||
|
const { videoId, onClose } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
onClose={onClose}
|
||||||
|
wrapperClassName="w-[90vw] max-w-4xl h-auto"
|
||||||
|
bodyClassName="p-0 bg-black"
|
||||||
|
overlayClassName="items-start md:items-center"
|
||||||
|
>
|
||||||
|
<div className="relative w-full pt-[56.25%]">
|
||||||
|
<iframe
|
||||||
|
className="absolute inset-0 h-full w-full"
|
||||||
|
src={`https://www.youtube.com/embed/${videoId}?autoplay=1`}
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||||
|
allowFullScreen
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
Reference in New Issue
Block a user