From 2cb3bf9562f578a807d1cb5e39cd31b2a342251b Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Tue, 1 Jul 2025 02:25:33 +0100 Subject: [PATCH] Purchase banner --- .../SQLCourseVariant/PurchaseBanner.tsx | 100 +++++++--- .../SQLCourseVariant/SQLCourseVariantPage.tsx | 184 +++++++++--------- 2 files changed, 169 insertions(+), 115 deletions(-) diff --git a/src/components/SQLCourseVariant/PurchaseBanner.tsx b/src/components/SQLCourseVariant/PurchaseBanner.tsx index ddcc16495..ab1a9bcbd 100644 --- a/src/components/SQLCourseVariant/PurchaseBanner.tsx +++ b/src/components/SQLCourseVariant/PurchaseBanner.tsx @@ -1,33 +1,85 @@ import { CheckIcon, Star } from 'lucide-react'; import { BuyButton } from './BuyButton'; import { Rating } from '../Rating/Rating'; +import { cn } from '../../lib/classname'; +import { useEffect, useRef, useState } from 'react'; export function PurchaseBanner() { - return ( -
-
- {[ - '7-Day Money-Back Guarantee', - 'Lifetime access & updates' - ].map((text, index) => ( - - - {text} + const bannerRef = useRef(null); + + const [isOutOfView, setIsOutOfView] = useState(false); + + useEffect(() => { + const handleScroll = () => { + if (!bannerRef.current) return; + + const bannerRect = bannerRef.current.getBoundingClientRect(); + const bannerBottom = bannerRect.bottom; + + // Banner is out of view when its bottom is above the viewport + setIsOutOfView(bannerBottom < 0); + }; + + window.addEventListener('scroll', handleScroll); + handleScroll(); // Check initial state + + return () => { + window.removeEventListener('scroll', handleScroll); + }; + }, []); + + const Banner = (props: { + className?: string; + ref?: React.RefObject; + }) => { + return ( +
+
+ {['7-Day Money-Back Guarantee', 'Lifetime access & updates'].map( + (text, index) => ( + + + {text} + + ), + )} +
+ +
+ +
+ +
+ + + + 4.9 avg. Review - ))} +
- -
- -
- -
- - - - 4.9 avg. Review - -
-
+ ); + }; + return ( + <> + + + ); } diff --git a/src/components/SQLCourseVariant/SQLCourseVariantPage.tsx b/src/components/SQLCourseVariant/SQLCourseVariantPage.tsx index 779210c05..bf6aeb12b 100644 --- a/src/components/SQLCourseVariant/SQLCourseVariantPage.tsx +++ b/src/components/SQLCourseVariant/SQLCourseVariantPage.tsx @@ -1,7 +1,8 @@ import { BrainIcon, CodeIcon, - FileQuestionIcon, NotebookTextIcon + FileQuestionIcon, + NotebookTextIcon, } from 'lucide-react'; import { Spotlight } from '../SQLCourse/Spotlight'; import { RoadmapLogoIcon } from '../ReactIcons/RoadmapLogo'; @@ -19,105 +20,106 @@ import { sqlCourseChapters } from '../SQLCourse/SQLCoursePage'; export function SQLCourseVariantPage() { return ( - <> -
-
-
- +
+
+
+ -
- - - -
-

- Master SQL Queries -

-

- Complete course with AI Tutor, real-world challenges and more -

-
-
- -

- Get certified for SQL queries and ready to deploy your - newly-gained skill in 30 days. Perfect for developers, data - analysts, and anyone working with data. Level up risk-free with a - 7-day money-back guarantee. -

- -
-
-
- {[ - { Icon: NotebookTextIcon, text: '55+ Lessons' }, - { Icon: FileQuestionIcon, text: '100+ Challenges' }, - { Icon: BrainIcon, text: 'AI Tutor' }, - { Icon: CodeIcon, text: 'Integrated IDE' }, - ].map(({ Icon, text }, index) => ( -
- - {text} -
- ))} -
- - -
- - +
+ + + +
+

+ Master SQL Queries +

+

+ Complete course with AI Tutor, real-world challenges and more +

- +

+ Get certified for SQL queries and ready to deploy your newly-gained + skill in 30 days. Perfect for developers, data analysts, and anyone + working with data. Level up risk-free with a 7-day money-back + guarantee. +

- +
+
+
+ {[ + { Icon: NotebookTextIcon, text: '55+ Lessons' }, + { Icon: FileQuestionIcon, text: '100+ Challenges' }, + { Icon: BrainIcon, text: 'AI Tutor' }, + { Icon: CodeIcon, text: 'Integrated IDE' }, + ].map(({ Icon, text }, index) => ( +
+ + {text} +
+ ))} +
- + +
- - - - -
- {sqlCourseChapters.map((chapter, index) => ( - - ))} -
- - - -
- -
- - - -
+ + + + + + + + + + + +
+ {sqlCourseChapters.map((chapter, index) => ( + + ))} +
+ + + +
+ +
+ + + +
- +
); }