CLASSROOMIO-T-180:Made the card stay at the bottom of the Landingpage
CLASSROOMIO-T-180: Subtle improvements Merge branch 'CLASSROOMIO-T-180' of https://gitlab.com/thenextgreat/classroomio into CLASSROOMIO-T-180 CLASSROOMIO-T-180:Used a single component for the card CLASSROOMIO-T-180:Used a single component for the card CLASSROOMIO-T-180:Fixed a bug in the intersection observer CLASSROOMIO-T-180:Fixed a bug in the intersection observer CLASSROOMIO-T-180:Made the card stay at the bottom CLASSROOMIO-T-180:Used a single component for the card CLASSROOMIO-T-180:Used a single component for the card CLASSROOMIO-T-180:Fixed a bug in the intersection observer CLASSROOMIO-T-180:Fixed a bug in the intersection observer Merge branch 'main' into CLASSROOMIO-T-180 CLASSROOMIO-T-180:Made the card stay at the bottom Co-authored-by: Ifeanyi Nwosu <ifeanyi@digdippa.com> Co-authored-by: Rotimi Best <rotimiibitoyeemma@gmail.com> Merge-request: CLASSROOMIO-MR-79 Merged-by: Best Admin <best@digdippa.com>
This commit is contained in:
committed by
Space Cloud
co-authored by
Rotimi Best
parent
07b92fbe92
commit
ce2b12c417
@@ -147,7 +147,7 @@
|
||||
<aside
|
||||
class={`${
|
||||
show ? '-translate-x-[100%] fixed md:absolute z-[50]' : 'translate-x-0 fixed md:relative z-[50]'
|
||||
}left-0 transition w-[350px] min-w-[300px] bg-gray-100 dark:bg-neutral-800 h-full border border-l-0 border-t-0 border-b-0 border-r-1`}
|
||||
}left-0 z-[50] transition w-[90vw] min-w-[300px] max-w-[350px] bg-gray-100 dark:bg-neutral-800 h-full border border-l-0 border-t-0 border-b-0 border-r-1`}
|
||||
>
|
||||
<div class="toggler rounded-full shadow-lg absolute">
|
||||
<IconButton
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
export function observeIntersection(node, callback, options = {}) {
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
callback(true);
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
});
|
||||
}, options);
|
||||
|
||||
observer.observe(node);
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
observer.unobserve(node);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
export let editMode = false;
|
||||
export let courseData: Course;
|
||||
export let startCoursePayment = false;
|
||||
export let mobile = false;
|
||||
|
||||
let calculatedCost = 0;
|
||||
let discount = 0;
|
||||
@@ -63,48 +64,89 @@
|
||||
/>
|
||||
|
||||
<!-- Pricing Details -->
|
||||
<aside
|
||||
class="{className} price-container lg:sticky {editMode
|
||||
? 'lg:top-0'
|
||||
: 'lg:top-10'} lg:shadow-2xl lg:rounded-lg m-h-fit bg-neutral-800"
|
||||
>
|
||||
<div class="p-10">
|
||||
<!-- Pricing -->
|
||||
<div class="mb-6">
|
||||
<p class="dark:text-white font-medium text-lg">
|
||||
{formatter?.format(calculatedCost) || calculatedCost}
|
||||
{#if isFree}
|
||||
<span class="text-sm">(Free)</span>
|
||||
{/if}
|
||||
</p>
|
||||
{#if courseData?.metadata?.showDiscount}
|
||||
<p class="dark:text-white font-light text-sm text-gray-500">
|
||||
{discount}% Discount.
|
||||
<span class="line-through"
|
||||
>{formatter?.format(courseData?.cost || 0) || courseData.cost}</span
|
||||
>
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{#if mobile}
|
||||
<div
|
||||
class="sticky w-full flex items-center justify-center transition duration-300 h-fit bottom-0 lg:hidden bg-gray-50 dark:bg-neutral-800"
|
||||
>
|
||||
<aside
|
||||
class="price-container sticky lg:hidden {editMode
|
||||
? 'lg:bottom-2'
|
||||
: 'lg:top-10'} lg:shadow-2xl lg:rounded-lg m-h-fit bg-gray-50 dark:bg-neutral-800 z-0 {className}"
|
||||
>
|
||||
<div class="flex items-center justify-center gap-3 px-3 py-3">
|
||||
<!-- Pricing -->
|
||||
<div class=" text-center">
|
||||
<p class="dark:text-white font-medium text-sm flex items-center gap-1">
|
||||
{formatter?.format(calculatedCost) || calculatedCost}
|
||||
{#if isFree}
|
||||
<span class="text-xs">(Free)</span>
|
||||
{/if}
|
||||
</p>
|
||||
{#if courseData?.metadata?.showDiscount}
|
||||
<p class="dark:text-white font-light text-sm text-gray-500">
|
||||
{discount}% Discount.
|
||||
<span class="line-through"
|
||||
>{formatter?.format(courseData?.cost || 0) || courseData.cost}</span
|
||||
>
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Call To Action Buttons -->
|
||||
<div class="flex flex-col w-full items-center">
|
||||
<PrimaryButton
|
||||
label={isFree ? 'Join Course' : 'Buy Now'}
|
||||
className="w-full sm:w-full py-3 mb-3"
|
||||
onClick={handleJoinCourse}
|
||||
/>
|
||||
<p class="dark:text-white font-light text-sm text-gray-500">Early bird offer. Buy ASAP</p>
|
||||
</div>
|
||||
<!-- Call To Action Buttons -->
|
||||
<div class="flex flex-col w-full h-full items-center">
|
||||
<PrimaryButton
|
||||
label={isFree ? 'Join Course' : 'Buy Now'}
|
||||
className="w-full sm:w-full h-[40px]"
|
||||
onClick={handleJoinCourse}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
{:else}
|
||||
<aside
|
||||
class="price-container lg:sticky {editMode
|
||||
? 'lg:top-0'
|
||||
: 'lg:top-10'} lg:shadow-2xl lg:rounded-lg m-h-fit dark:bg-neutral-800 {className}"
|
||||
>
|
||||
<div class="p-2 lg:p-10">
|
||||
<!-- Pricing -->
|
||||
<div class="mb-6">
|
||||
<p class="dark:text-white font-medium text-lg">
|
||||
{formatter?.format(calculatedCost) || calculatedCost}
|
||||
{#if isFree}
|
||||
<span class="text-sm">(Free)</span>
|
||||
{/if}
|
||||
</p>
|
||||
{#if courseData?.metadata?.showDiscount}
|
||||
<p class="dark:text-white font-light text-sm text-gray-500">
|
||||
{discount}% Discount.
|
||||
<span class="line-through"
|
||||
>{formatter?.format(courseData?.cost || 0) || courseData.cost}</span
|
||||
>
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Gift Container -->
|
||||
{#if courseData?.metadata?.reward?.show}
|
||||
<div class="p-10 flex items-center flex-col border-t border-b border-gray-300">
|
||||
{@html get(courseData, 'metadata.reward.description', '')}
|
||||
<!-- Call To Action Buttons -->
|
||||
<div class="flex flex-col w-full items-center">
|
||||
<PrimaryButton
|
||||
label={isFree ? 'Join Course' : 'Buy Now'}
|
||||
className="w-full sm:w-full py-3 mb-3"
|
||||
onClick={handleJoinCourse}
|
||||
/>
|
||||
<p class="dark:text-white font-light text-sm text-gray-500">Early bird offer. Buy ASAP</p>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</aside>
|
||||
|
||||
<!-- Gift Container -->
|
||||
{#if courseData?.metadata?.reward?.show}
|
||||
<div class="p-10 flex items-center flex-col border-t border-b border-gray-300">
|
||||
{@html get(courseData, 'metadata.reward.description', '')}
|
||||
</div>
|
||||
{/if}
|
||||
</aside>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
.banner {
|
||||
@@ -141,18 +183,30 @@
|
||||
}
|
||||
|
||||
.price-container {
|
||||
width: 405px;
|
||||
min-width: 330px;
|
||||
width: 90%;
|
||||
max-width: 405px;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
@media screen and (min-width: 768px) {
|
||||
.price-container {
|
||||
width: 50%;
|
||||
height: fit-content;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1024px) {
|
||||
.price-container {
|
||||
width: 350px;
|
||||
min-width: 250px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1280px) {
|
||||
.price-container {
|
||||
width: 405px;
|
||||
min-width: 330px;
|
||||
height: fit-content;
|
||||
}
|
||||
}
|
||||
.course-content {
|
||||
max-width: 608px;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
// import paystack from 'paystack';
|
||||
import get from 'lodash/get';
|
||||
import { onMount } from 'svelte';
|
||||
import { observeIntersection } from './components/IntersectionObserver';
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import pluralize from 'pluralize';
|
||||
import { page } from '$app/stores';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -42,6 +43,8 @@
|
||||
let averageRating = 0;
|
||||
let totalRatings = 0;
|
||||
let startCoursePayment = false;
|
||||
let isVisible = false;
|
||||
let observer;
|
||||
|
||||
// initialize the expandDescription array with 'false' values for each review.
|
||||
let expandDescription = Array(reviews.length).fill(false);
|
||||
@@ -75,6 +78,14 @@
|
||||
|
||||
onMount(() => {
|
||||
window.onhashchange = locationHashChanged;
|
||||
const targetNode = document.querySelector('.target-component');
|
||||
observer = observeIntersection(targetNode, (inView) => {
|
||||
isVisible = inView;
|
||||
});
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
observer?.destroy();
|
||||
});
|
||||
|
||||
$: video = get(courseData, 'metadata.videoUrl');
|
||||
@@ -110,7 +121,7 @@
|
||||
</p>
|
||||
<PrimaryButton
|
||||
label="Start Course"
|
||||
className="px-6 py-5 mt-6 sm:w-fit"
|
||||
className="px-6 py-5 mt-6 sm:w-fit hidden md:block"
|
||||
onClick={() => {
|
||||
startCoursePayment = true;
|
||||
}}
|
||||
@@ -162,11 +173,12 @@
|
||||
<!-- Body -->
|
||||
<div class="bg-white dark:bg-black w-full">
|
||||
<div
|
||||
class="py-8 lg:w-11/12 w-full m-2 lg:m-auto flex flex-col-reverse lg:flex-row items-center lg:items-start justify-between max-w-[1200px]"
|
||||
class="lg:py-8 lg:w-11/12 w-full mx-0 my-2 lg:m-auto flex flex-col-reverse lg:flex-row items-center lg:items-start justify-between max-w-[1200px]"
|
||||
>
|
||||
<!-- Course Details -->
|
||||
<div class="course-content w-full p-3 lg:w-10/12 lg:mr-10">
|
||||
<!-- Navigation -->
|
||||
|
||||
<nav
|
||||
class="flex items-center border-b border-gray-300 py-3 sticky top-0 {!editMode &&
|
||||
'lg:top-11'} bg-white dark:bg-neutral-800"
|
||||
@@ -175,7 +187,7 @@
|
||||
<a
|
||||
href="{$page.url.pathname}{navItem.key}"
|
||||
class="{navItem.key === activeNav &&
|
||||
'active text-primary-700'} rounded-lg px-2 mr-6 text-slate-700 font-normal hover:bg-neutral-600 hover:text-slate-900 dark:text-white"
|
||||
'active text-primary-700'} rounded-lg px-2 mr-6 text-slate-700 font-normal hover:bg-neutral-600 hover:text-slate-900 dark:text-white z-0"
|
||||
>
|
||||
{navItem.label}
|
||||
</a>
|
||||
@@ -416,8 +428,22 @@
|
||||
</div>
|
||||
|
||||
<!-- Pricing Details -->
|
||||
<PricingSection {courseData} {editMode} bind:startCoursePayment />
|
||||
<PricingSection
|
||||
{courseData}
|
||||
{editMode}
|
||||
bind:startCoursePayment
|
||||
className="target-component"
|
||||
/>
|
||||
</div>
|
||||
{#if !isVisible}
|
||||
<PricingSection
|
||||
{courseData}
|
||||
{editMode}
|
||||
bind:startCoursePayment
|
||||
mobile={true}
|
||||
className="w-full"
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user