2022-12-30 13:08:54 +01:00
|
|
|
<script lang="ts">
|
2023-09-15 08:26:26 +01:00
|
|
|
import get from 'lodash/get';
|
2023-08-02 19:35:27 +01:00
|
|
|
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
|
|
|
|
import getCurrencyFormatter from '$lib/utils/functions/getCurrencyFormatter';
|
2023-09-14 23:04:51 +01:00
|
|
|
import { isCourseFree } from '$lib/utils/functions/course';
|
2023-09-15 08:26:26 +01:00
|
|
|
import { getStudentInviteLink } from '$lib/utils/functions/course';
|
|
|
|
|
import { currentOrg } from '$lib/utils/store/org';
|
|
|
|
|
import { goto } from '$app/navigation';
|
|
|
|
|
import PaymentModal from './PaymentModal.svelte';
|
|
|
|
|
import type { Course } from '$lib/utils/types';
|
|
|
|
|
import { ROLE } from '$lib/utils/constants/roles';
|
2022-12-30 13:08:54 +01:00
|
|
|
|
|
|
|
|
export let className = '';
|
2023-09-14 23:04:51 +01:00
|
|
|
export let editMode = false;
|
2023-09-15 08:26:26 +01:00
|
|
|
export let courseData: Course;
|
|
|
|
|
export let startCoursePayment = false;
|
2023-09-26 11:08:24 +00:00
|
|
|
export let mobile = false;
|
2022-12-30 13:08:54 +01:00
|
|
|
|
|
|
|
|
let calculatedCost = 0;
|
|
|
|
|
let discount = 0;
|
|
|
|
|
let formatter: Intl.NumberFormat | undefined;
|
2023-09-14 23:04:51 +01:00
|
|
|
let isFree = false;
|
2022-12-30 13:08:54 +01:00
|
|
|
|
2023-09-26 23:29:50 +01:00
|
|
|
function calcDisc(percent: number, cost: number, showDiscount: boolean) {
|
|
|
|
|
if (!percent || !showDiscount) return cost;
|
2023-09-04 09:09:09 +00:00
|
|
|
const discountAmount = (percent / 100) * cost;
|
|
|
|
|
const discountedPrice = cost - discountAmount;
|
|
|
|
|
return Math.round(discountedPrice);
|
2022-12-30 13:08:54 +01:00
|
|
|
}
|
|
|
|
|
|
2023-09-14 23:04:51 +01:00
|
|
|
function handleJoinCourse() {
|
|
|
|
|
if (editMode) return;
|
|
|
|
|
|
|
|
|
|
if (isFree) {
|
2023-09-15 08:26:26 +01:00
|
|
|
const link = getStudentInviteLink(courseData, $currentOrg.siteName);
|
|
|
|
|
goto(link);
|
2023-09-14 23:04:51 +01:00
|
|
|
} else {
|
2023-09-15 08:26:26 +01:00
|
|
|
startCoursePayment = true;
|
2023-09-14 23:04:51 +01:00
|
|
|
}
|
|
|
|
|
}
|
2022-12-30 13:08:54 +01:00
|
|
|
|
|
|
|
|
function setFormatter(currency: string | undefined) {
|
|
|
|
|
if (!currency) return;
|
2023-01-03 09:26:08 +01:00
|
|
|
formatter = getCurrencyFormatter(currency);
|
2022-12-30 13:08:54 +01:00
|
|
|
}
|
|
|
|
|
|
2023-09-15 08:26:26 +01:00
|
|
|
function getTeacherEmail(group: Course['group']) {
|
|
|
|
|
const firstTutor = group?.members?.find((m) => m.role_id === ROLE.TUTOR);
|
|
|
|
|
|
|
|
|
|
return firstTutor?.profile?.email || '';
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-30 13:08:54 +01:00
|
|
|
$: setFormatter(courseData.currency);
|
2023-09-26 23:29:50 +01:00
|
|
|
|
2022-12-30 13:08:54 +01:00
|
|
|
$: discount = get(courseData, 'metadata.discount', 0);
|
2023-10-30 04:52:00 +00:00
|
|
|
$: calculatedCost = calcDisc(discount, courseData.cost || 0, !!courseData.metadata.showDiscount);
|
2023-09-14 23:04:51 +01:00
|
|
|
$: isFree = isCourseFree(calculatedCost);
|
2022-12-30 13:08:54 +01:00
|
|
|
</script>
|
|
|
|
|
|
2023-09-15 08:26:26 +01:00
|
|
|
<PaymentModal
|
|
|
|
|
bind:open={startCoursePayment}
|
|
|
|
|
paymentLink={get(courseData, 'metadata.paymentLink', '')}
|
|
|
|
|
courseName={courseData.title}
|
|
|
|
|
teacherEmail={getTeacherEmail(courseData.group)}
|
|
|
|
|
/>
|
|
|
|
|
|
2022-12-30 13:08:54 +01:00
|
|
|
<!-- Pricing Details -->
|
2023-09-26 11:08:24 +00:00
|
|
|
{#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">
|
2023-10-30 04:52:00 +00:00
|
|
|
{#if courseData?.metadata?.allowNewStudent}
|
|
|
|
|
<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>
|
2023-09-26 11:08:24 +00:00
|
|
|
{/if}
|
2023-10-30 04:52:00 +00:00
|
|
|
{:else}
|
|
|
|
|
<p class="dark:text-white text-lg">
|
|
|
|
|
This course is currently not accepting new students.
|
2023-09-26 11:08:24 +00:00
|
|
|
</p>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
2022-12-30 13:08:54 +01:00
|
|
|
|
2023-09-26 11:08:24 +00:00
|
|
|
<!-- Call To Action Buttons -->
|
|
|
|
|
<div class="flex flex-col w-full h-full items-center">
|
|
|
|
|
<PrimaryButton
|
2023-11-04 17:53:59 +00:00
|
|
|
label={isFree ? 'Enroll Now' : 'Buy Now'}
|
2023-09-26 11:08:24 +00:00
|
|
|
className="w-full sm:w-full h-[40px]"
|
|
|
|
|
onClick={handleJoinCourse}
|
2023-10-30 04:52:00 +00:00
|
|
|
isDisabled={!courseData.metadata.allowNewStudent}
|
2023-09-26 11:08:24 +00:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</aside>
|
2022-12-30 13:08:54 +01:00
|
|
|
</div>
|
2023-09-26 11:08:24 +00:00
|
|
|
{: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">
|
2023-10-30 04:52:00 +00:00
|
|
|
{#if courseData?.metadata?.allowNewStudent}
|
|
|
|
|
<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>
|
2023-09-26 11:08:24 +00:00
|
|
|
{/if}
|
2023-10-30 04:52:00 +00:00
|
|
|
{:else}
|
|
|
|
|
<p class="dark:text-white text-lg">
|
|
|
|
|
This course is currently not accepting new students.
|
2023-09-26 11:08:24 +00:00
|
|
|
</p>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
2022-12-30 13:08:54 +01:00
|
|
|
|
2023-09-26 11:08:24 +00:00
|
|
|
<!-- Call To Action Buttons -->
|
|
|
|
|
<div class="flex flex-col w-full items-center">
|
|
|
|
|
<PrimaryButton
|
2023-11-04 17:53:59 +00:00
|
|
|
label={isFree ? 'Enroll Now' : 'Buy Now'}
|
2023-09-26 11:08:24 +00:00
|
|
|
className="w-full sm:w-full py-3 mb-3"
|
|
|
|
|
onClick={handleJoinCourse}
|
2023-10-30 04:52:00 +00:00
|
|
|
isDisabled={!courseData.metadata.allowNewStudent}
|
2023-09-26 11:08:24 +00:00
|
|
|
/>
|
2023-10-30 04:52:00 +00:00
|
|
|
{#if courseData?.metadata?.showDiscount && courseData.metadata.allowNewStudent}
|
|
|
|
|
<p class="dark:text-white font-light text-sm text-gray-500">Early bird offer. Buy ASAP</p>
|
|
|
|
|
{/if}
|
2023-09-26 11:08:24 +00:00
|
|
|
</div>
|
2022-12-30 13:08:54 +01:00
|
|
|
</div>
|
2023-09-26 11:08:24 +00:00
|
|
|
|
|
|
|
|
<!-- 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}
|
2022-12-30 13:08:54 +01:00
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
|
.banner {
|
|
|
|
|
background-color: #040f2d;
|
|
|
|
|
min-height: 472px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.author {
|
|
|
|
|
color: #7888b7;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.banner-image {
|
|
|
|
|
max-width: 559px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.backdrop {
|
|
|
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.active {
|
|
|
|
|
position: relative;
|
|
|
|
|
display: inline-block;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.active::after {
|
|
|
|
|
position: absolute;
|
|
|
|
|
content: '';
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 3px;
|
|
|
|
|
background-color: var(--main-primary-color);
|
|
|
|
|
display: block;
|
|
|
|
|
bottom: -14px;
|
|
|
|
|
left: 0px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.price-container {
|
2023-09-26 11:08:24 +00:00
|
|
|
width: 90%;
|
|
|
|
|
max-width: 405px;
|
2022-12-30 13:08:54 +01:00
|
|
|
height: fit-content;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-26 11:08:24 +00:00
|
|
|
@media screen and (min-width: 768px) {
|
|
|
|
|
.price-container {
|
|
|
|
|
width: 50%;
|
|
|
|
|
height: fit-content;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@media screen and (min-width: 1024px) {
|
2022-12-30 13:08:54 +01:00
|
|
|
.price-container {
|
2023-09-24 13:20:04 +00:00
|
|
|
width: 350px;
|
|
|
|
|
min-width: 250px;
|
2022-12-30 13:08:54 +01:00
|
|
|
}
|
|
|
|
|
}
|
2023-09-26 11:08:24 +00:00
|
|
|
@media screen and (min-width: 1280px) {
|
|
|
|
|
.price-container {
|
|
|
|
|
width: 405px;
|
|
|
|
|
min-width: 330px;
|
|
|
|
|
height: fit-content;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-30 13:08:54 +01:00
|
|
|
.course-content {
|
|
|
|
|
max-width: 608px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:global(.list ul li) {
|
|
|
|
|
margin-left: 1rem;
|
|
|
|
|
list-style-type: disc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:global(.plyr) {
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
}
|
|
|
|
|
</style>
|