course landing page improvements

This commit is contained in:
Rotimi Best
2023-10-30 04:52:00 +00:00
parent 64a058ebc8
commit d6472a54ca
18 changed files with 189 additions and 112 deletions
@@ -47,6 +47,7 @@
} }
$: onCompletion($completion); $: onCompletion($completion);
$: prompt = defaultPrompt;
</script> </script>
<div class="{className} relative z-[100]"> <div class="{className} relative z-[100]">
+15 -5
View File
@@ -1,4 +1,12 @@
<div class="root"> <script lang="ts">
export let disableCenteredContent = false;
export let className = '';
</script>
<div
class="root {!className.includes('opacity') && 'opacity-100'} {!disableCenteredContent &&
'center'} {className}"
>
<slot /> <slot />
</div> </div>
@@ -8,15 +16,17 @@
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
display: flex;
position: fixed; position: fixed;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.3); background-color: rgba(0, 0, 0, 0.3);
-webkit-tap-highlight-color: transparent; -webkit-tap-highlight-color: transparent;
color: #fff; color: #fff;
z-index: 1201; z-index: 1201;
opacity: 1;
transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
} }
.center {
display: flex;
align-items: center;
justify-content: center;
}
</style> </style>
@@ -1,17 +1,13 @@
<script lang="ts"> <script lang="ts">
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import ArrowUpRightIcon from '$lib/components/Icons/ArrowTopRight.svelte'; import ArrowUpRightIcon from '$lib/components/Icons/ArrowTopRight.svelte';
import { currentOrg } from '$lib/utils/store/org'; import { currentOrgDomain } from '$lib/utils/store/org';
import { isMobile } from '$lib/utils/store/useMobile'; import { isMobile } from '$lib/utils/store/useMobile';
export let className = ''; export let className = '';
</script> </script>
<a <a href={$currentOrgDomain} target="_blank" class="{className} ml-2 hover:no-underline">
href={`https://${$currentOrg.siteName}.classroomio.com`}
target="_blank"
class="{className} ml-2 hover:no-underline"
>
<PrimaryButton> <PrimaryButton>
{#if !$isMobile} {#if !$isMobile}
View site View site
@@ -16,7 +16,7 @@
import { currentOrgPath } from '$lib/utils/store/org'; import { currentOrgPath } from '$lib/utils/store/org';
import { isObject } from '$lib/utils/functions/isObject'; import { isObject } from '$lib/utils/functions/isObject';
import { lessons } from '../Lesson/store/lessons'; import { lessons } from '../Lesson/store/lessons';
import { currentOrg } from '$lib/utils/store/org'; import { currentOrg, currentOrgDomain } from '$lib/utils/store/org';
import { snackbar } from '$lib/components/Snackbar/store'; import { snackbar } from '$lib/components/Snackbar/store';
import UploadWidget from '$lib/components/UploadWidget/index.svelte'; import UploadWidget from '$lib/components/UploadWidget/index.svelte';
import { handleOpenWidget } from '$lib/components/CourseLandingPage/store'; import { handleOpenWidget } from '$lib/components/CourseLandingPage/store';
@@ -24,14 +24,17 @@
let isSaving = false; let isSaving = false;
let isLoading = false; let isLoading = false;
let isDeleting = false; let isDeleting = false;
let errors = {}; let errors: {
let avatar; title: string | undefined;
description: string | undefined;
} = { title: undefined, description: undefined };
let avatar: string | undefined;
function widgetControl() { function widgetControl() {
$handleOpenWidget.open = true; $handleOpenWidget.open = true;
} }
function getLessonOrder(id) { function getLessonOrder(id: string) {
const index = $lessons.findIndex((lesson) => lesson.id === id); const index = $lessons.findIndex((lesson) => lesson.id === id);
if (index < 9) { if (index < 9) {
return '0' + (index + 1); return '0' + (index + 1);
@@ -172,7 +175,6 @@
$: $settings.course_description = $course.description; $: $settings.course_description = $course.description;
$: $settings.course_title = $course.title; $: $settings.course_title = $course.title;
$: $settings.allow_new_students = $settings.is_published;
$: setDefault($course); $: setDefault($course);
</script> </script>
@@ -238,11 +240,7 @@
<div class=""> <div class="">
<p class="text-md">Course Link</p> <p class="text-md">Course Link</p>
{#if $course.slug} {#if $course.slug}
<CodeSnippet <CodeSnippet wrapText type="multi" code={`${$currentOrgDomain}/course/${$course.slug}`} />
wrapText
type="multi"
code={`https://${$currentOrg.siteName}.classroomio.com/course/${$course.slug}`}
/>
{:else} {:else}
<CodeSnippet code="Setup landing page to get course link" /> <CodeSnippet code="Setup landing page to get course link" />
{/if} {/if}
@@ -256,23 +254,12 @@
</Column> </Column>
<Column sm={8} md={8} lg={8}> <Column sm={8} md={8} lg={8}>
<Toggle size="sm" bind:toggled={$settings.grading}> <Toggle size="sm" bind:toggled={$settings.grading}>
<span slot="labelA" style="color: gray">Disable</span> <span slot="labelA" style="color: gray">Disabled</span>
<span slot="labelB" style="color: gray">Enable</span> <span slot="labelB" style="color: gray">Enabled</span>
</Toggle>
</Column>
</Row>
<Row class="flex lg:flex-row flex-col py-7 border-bottom-c">
<Column sm={8} md={8} lg={8}>
<SectionTitle>Allow New Students</SectionTitle>
<p>Allow new students to access this course</p>
</Column>
<Column sm={8} md={8} lg={8}>
<Toggle size="sm" bind:toggled={$settings.allow_new_students}>
<span slot="labelA" style="color: gray">Disable</span>
<span slot="labelB" style="color: gray">Enable</span>
</Toggle> </Toggle>
</Column> </Column>
</Row> </Row>
<Row class="flex lg:flex-row flex-col py-7 border-bottom-c"> <Row class="flex lg:flex-row flex-col py-7 border-bottom-c">
<Column sm={8} md={8} lg={8}> <Column sm={8} md={8} lg={8}>
<SectionTitle>Order Lessons Tab</SectionTitle> <SectionTitle>Order Lessons Tab</SectionTitle>
@@ -289,8 +276,8 @@
</Column> </Column>
<Column sm={8} md={8} lg={8}> <Column sm={8} md={8} lg={8}>
<Toggle size="sm" bind:toggled={$settings.lesson_download}> <Toggle size="sm" bind:toggled={$settings.lesson_download}>
<span slot="labelA" style="color: gray">Disable</span> <span slot="labelA" style="color: gray">Disabled</span>
<span slot="labelB" style="color: gray">Enable</span> <span slot="labelB" style="color: gray">Enabled</span>
</Toggle> </Toggle>
</Column> </Column>
</Row> </Row>
@@ -301,8 +288,8 @@
</Column> </Column>
<Column sm={8} md={8} lg={8}> <Column sm={8} md={8} lg={8}>
<PrimaryButton <PrimaryButton
variant={VARIANTS.LINK} variant={VARIANTS.OUTLINED}
label="Download Course" label="Download"
onClick={downloadCourse} onClick={downloadCourse}
isDisabled={isLoading} isDisabled={isLoading}
{isLoading} {isLoading}
@@ -310,6 +297,19 @@
</Column> </Column>
</Row> </Row>
<Row class="flex lg:flex-row flex-col py-7 border-bottom-c">
<Column sm={8} md={8} lg={8}>
<SectionTitle>Allow New Students</SectionTitle>
<p>Allow new students to access this course</p>
</Column>
<Column sm={8} md={8} lg={8}>
<Toggle size="sm" bind:toggled={$settings.allow_new_students}>
<span slot="labelA" style="color: gray">Disabled</span>
<span slot="labelB" style="color: gray">Enabled</span>
</Toggle>
</Column>
</Row>
<!-- Publish Course --> <!-- Publish Course -->
<Row class="flex lg:flex-row flex-col py-7 border-bottom-c"> <Row class="flex lg:flex-row flex-col py-7 border-bottom-c">
<Column sm={8} md={8} lg={8}> <Column sm={8} md={8} lg={8}>
@@ -317,7 +317,13 @@
<p>This determines if your course displays on your landing page</p> <p>This determines if your course displays on your landing page</p>
</Column> </Column>
<Column sm={8} md={8} lg={8}> <Column sm={8} md={8} lg={8}>
<Toggle size="sm" bind:toggled={$settings.is_published}> <Toggle
size="sm"
bind:toggled={$settings.is_published}
on:toggle={(e) => {
$settings.allow_new_students = e.detail.toggled;
}}
>
<span slot="labelA" style="color: gray">Unpublished</span> <span slot="labelA" style="color: gray">Unpublished</span>
<span slot="labelB" style="color: gray">Published</span> <span slot="labelB" style="color: gray">Published</span>
</Toggle> </Toggle>
@@ -53,7 +53,7 @@
$: setFormatter(courseData.currency); $: setFormatter(courseData.currency);
$: discount = get(courseData, 'metadata.discount', 0); $: discount = get(courseData, 'metadata.discount', 0);
$: calculatedCost = calcDisc(discount, courseData.cost || 0, courseData.metadata.showDiscount); $: calculatedCost = calcDisc(discount, courseData.cost || 0, !!courseData.metadata.showDiscount);
$: isFree = isCourseFree(calculatedCost); $: isFree = isCourseFree(calculatedCost);
</script> </script>
@@ -77,18 +77,24 @@
<div class="flex items-center justify-center gap-3 px-3 py-3"> <div class="flex items-center justify-center gap-3 px-3 py-3">
<!-- Pricing --> <!-- Pricing -->
<div class=" text-center"> <div class=" text-center">
<p class="dark:text-white font-medium text-sm flex items-center gap-1"> {#if courseData?.metadata?.allowNewStudent}
{formatter?.format(calculatedCost) || calculatedCost} <p class="dark:text-white font-medium text-sm flex items-center gap-1">
{#if isFree} {formatter?.format(calculatedCost) || calculatedCost}
<span class="text-xs">(Free)</span> {#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} {/if}
</p> {:else}
{#if courseData?.metadata?.showDiscount} <p class="dark:text-white text-lg">
<p class="dark:text-white font-light text-sm text-gray-500"> This course is currently not accepting new students.
{discount}% Discount.
<span class="line-through"
>{formatter?.format(courseData?.cost || 0) || courseData.cost}</span
>
</p> </p>
{/if} {/if}
</div> </div>
@@ -99,7 +105,7 @@
label={isFree ? 'Join Course' : 'Buy Now'} label={isFree ? 'Join Course' : 'Buy Now'}
className="w-full sm:w-full h-[40px]" className="w-full sm:w-full h-[40px]"
onClick={handleJoinCourse} onClick={handleJoinCourse}
isDisabled={!editMode && !courseData.metadata.allowNewStudent} isDisabled={!courseData.metadata.allowNewStudent}
/> />
</div> </div>
</div> </div>
@@ -114,18 +120,24 @@
<div class="p-2 lg:p-10"> <div class="p-2 lg:p-10">
<!-- Pricing --> <!-- Pricing -->
<div class="mb-6"> <div class="mb-6">
<p class="dark:text-white font-medium text-lg"> {#if courseData?.metadata?.allowNewStudent}
{formatter?.format(calculatedCost) || calculatedCost} <p class="dark:text-white font-medium text-lg">
{#if isFree} {formatter?.format(calculatedCost) || calculatedCost}
<span class="text-sm">(Free)</span> {#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} {/if}
</p> {:else}
{#if courseData?.metadata?.showDiscount} <p class="dark:text-white text-lg">
<p class="dark:text-white font-light text-sm text-gray-500"> This course is currently not accepting new students.
{discount}% Discount.
<span class="line-through"
>{formatter?.format(courseData?.cost || 0) || courseData.cost}</span
>
</p> </p>
{/if} {/if}
</div> </div>
@@ -136,9 +148,11 @@
label={isFree ? 'Join Course' : 'Buy Now'} label={isFree ? 'Join Course' : 'Buy Now'}
className="w-full sm:w-full py-3 mb-3" className="w-full sm:w-full py-3 mb-3"
onClick={handleJoinCourse} onClick={handleJoinCourse}
isDisabled={!editMode && !courseData.metadata.allowNewStudent} isDisabled={!courseData.metadata.allowNewStudent}
/> />
<p class="dark:text-white font-light text-sm text-gray-500">Early bird offer. Buy ASAP</p> {#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}
</div> </div>
</div> </div>
@@ -128,9 +128,10 @@
label="Start Course" label="Start Course"
className="px-6 py-5 mt-6 sm:w-fit hidden md:block" className="px-6 py-5 mt-6 sm:w-fit hidden md:block"
onClick={() => { onClick={() => {
if (editMode) return;
startCoursePayment = true; startCoursePayment = true;
}} }}
isDisabled={!editMode && !courseData.metadata.allowNewStudent} isDisabled={!courseData.metadata.allowNewStudent}
/> />
</div> </div>
@@ -202,7 +203,7 @@
<a <a
href="{$page.url.pathname}{navItem.key}" href="{$page.url.pathname}{navItem.key}"
class="{navItem.key === activeNav && class="{navItem.key === activeNav &&
'active text-primary-700'} rounded-lg px-2 mr-6 text-slate-700 font-normal hover:bg-neutral-600 dark:hover:text-slate-900 dark:text-white z-0" 'active text-primary-700'} rounded-lg px-2 mr-6 text-slate-700 font-normal hover:bg-gray-200 dark:hover:text-slate-900 dark:text-white z-0"
> >
{navItem.label} {navItem.label}
</a> </a>
+1 -1
View File
@@ -36,7 +36,7 @@
{#if isAIEnabled} {#if isAIEnabled}
<CustomPromptBtn <CustomPromptBtn
defaultPrompt={initAIPrompt} bind:defaultPrompt={initAIPrompt}
alignPopover={aiAlignPopover} alignPopover={aiAlignPopover}
handleInsert={(v) => { handleInsert={(v) => {
value = v; value = v;
+6 -6
View File
@@ -1,4 +1,4 @@
<script> <script lang="ts">
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import InformationIcon from 'carbon-icons-svelte/lib/Information.svelte'; import InformationIcon from 'carbon-icons-svelte/lib/Information.svelte';
import WarningIcon from 'carbon-icons-svelte/lib/Warning.svelte'; import WarningIcon from 'carbon-icons-svelte/lib/Warning.svelte';
@@ -8,11 +8,11 @@
import { SNACKBAR_SEVERITY, SNACKBAR_SEVERITY_COLOR } from './constants'; import { SNACKBAR_SEVERITY, SNACKBAR_SEVERITY_COLOR } from './constants';
import { snackbarStore, snackbarStoreInitialState } from './store'; import { snackbarStore, snackbarStoreInitialState } from './store';
let severityColor; let severityColor: string;
let timeoutId; let timeoutId: NodeJS.Timeout | undefined;
function handleClose() { function handleClose() {
if (typeof $snackbarStore.handleClose === 'number') { if (typeof $snackbarStore.handleClose === 'function') {
$snackbarStore.handleClose(); $snackbarStore.handleClose();
} }
@@ -21,11 +21,11 @@
...snackbarStoreInitialState ...snackbarStoreInitialState
})); }));
clearTimeout(timeoutId); clearTimeout(timeoutId);
timeoutId = null; timeoutId = undefined;
} }
// When open is true trigger autoHideDuration // When open is true trigger autoHideDuration
function handleOpen(open) { function handleOpen(open: boolean) {
if (!open) { if (!open) {
return; return;
} }
+1 -1
View File
@@ -109,7 +109,7 @@ export async function uploadAvatar(courseId: string, avatar: string) {
export async function updateCourse( export async function updateCourse(
courseId: Course['id'], courseId: Course['id'],
avatar: string | undefined, avatar: string | undefined,
course: Course course: Partial<Course>
) { ) {
if (avatar && courseId) { if (avatar && courseId) {
const filename = `course/${courseId + Date.now()}.webp`; const filename = `course/${courseId + Date.now()}.webp`;
@@ -5,8 +5,9 @@ import { goto } from '$app/navigation';
import { supabase } from '$lib/utils/functions/supabase'; import { supabase } from '$lib/utils/functions/supabase';
import { orgs, currentOrg, orgAudience, orgTeam } from '$lib/utils/store/org'; import { orgs, currentOrg, orgAudience, orgTeam } from '$lib/utils/store/org';
import { ROLE, ROLE_LABEL } from '$lib/utils/constants/roles'; import { ROLE, ROLE_LABEL } from '$lib/utils/constants/roles';
import type { CurrentOrg, OrgTeamMember, OrgAudience } from '$lib/utils/types/org';
export async function getOrgTeam(orgId) { export async function getOrgTeam(orgId: string) {
const { data, error } = await supabase const { data, error } = await supabase
.from('organizationmember') .from('organizationmember')
.select( .select(
@@ -24,9 +25,22 @@ export async function getOrgTeam(orgId) {
) )
.eq('organization_id', orgId) .eq('organization_id', orgId)
.neq('role_id', ROLE.STUDENT) .neq('role_id', ROLE.STUDENT)
.order('id', { ascending: false }); .order('id', { ascending: false })
.returns<
{
id: number;
email: string;
verified: boolean;
role_id: number;
profile: {
id: string;
fullname: string;
email: string;
};
}[]
>();
const team = []; const team: OrgTeamMember[] = [];
if (data?.length) { if (data?.length) {
data.forEach((teamMember) => { data.forEach((teamMember) => {
team.push({ team.push({
@@ -49,7 +63,7 @@ export async function getOrgTeam(orgId) {
}; };
} }
export async function getOrganizations(userId) { export async function getOrganizations(userId: string) {
const { data, error } = await supabase const { data, error } = await supabase
.from('organizationmember') .from('organizationmember')
.select( .select(
@@ -70,9 +84,18 @@ export async function getOrganizations(userId) {
` `
) )
.eq('profile_id', userId) .eq('profile_id', userId)
.order('id', { ascending: false }); .order('id', { ascending: false })
.returns<
{
id: string;
profile_id: string;
role_id: string;
created_at: string;
organization: CurrentOrg;
}[]
>();
const orgsArray = []; const orgsArray: CurrentOrg[] = [];
if (Array.isArray(data) && data.length) { if (Array.isArray(data) && data.length) {
data.forEach((orgMember) => { data.forEach((orgMember) => {
@@ -114,7 +137,7 @@ export async function getOrganizations(userId) {
}; };
} }
export async function getOrgAudience(orgId) { export async function getOrgAudience(orgId: string) {
// get all students who are participants in any course belonging to an org // get all students who are participants in any course belonging to an org
const { data, error } = await supabase const { data, error } = await supabase
.from('profile') .from('profile')
@@ -153,7 +176,7 @@ export async function getOrgAudience(orgId) {
}; };
} }
export async function getCourseBySiteName(siteName) { export async function getCourseBySiteName(siteName: string) {
const { data, error } = await supabase const { data, error } = await supabase
.from('course') .from('course')
.select( .select(
@@ -176,7 +199,7 @@ export async function getCourseBySiteName(siteName) {
return data; return data;
} }
export async function getCurrentOrg(siteName, justGet = false) { export async function getCurrentOrg(siteName: string, justGet = false) {
const { data, error } = await supabase const { data, error } = await supabase
.from('organization') .from('organization')
.select( .select(
@@ -189,16 +212,21 @@ export async function getCurrentOrg(siteName, justGet = false) {
theme theme
` `
) )
.eq('siteName', siteName); .eq('siteName', siteName)
.returns<CurrentOrg[]>();
if (!justGet && (error || isEmpty(data))) { const isDataEmpty = !data?.[0];
if (!justGet && (error || isDataEmpty)) {
console.error('Error getOrganization', error); console.error('Error getOrganization', error);
return goto('/404'); return goto('/404');
} }
if (!justGet) { if (!justGet) {
if (isDataEmpty) return;
currentOrg.set(data[0]); currentOrg.set(data[0]);
} else if (!isEmpty(data)) { } else if (!isDataEmpty) {
return data[0]; return data[0];
} }
} }
+11 -2
View File
@@ -1,7 +1,8 @@
import { writable, derived } from 'svelte/store'; import { writable, derived } from 'svelte/store';
import { dev, browser } from '$app/environment';
import { STEPS } from '../constants/quiz'; import { STEPS } from '../constants/quiz';
import type { Writable } from 'svelte/store'; import type { Writable } from 'svelte/store';
import type { CurrentOrg, OrgTeamMember } from '../types/org'; import type { CurrentOrg, OrgTeamMember, OrgAudience } from '../types/org';
import { ROLE } from '$lib/utils/constants/roles'; import { ROLE } from '$lib/utils/constants/roles';
import type { UserLessonDataType } from '$lib/utils/types'; import type { UserLessonDataType } from '$lib/utils/types';
@@ -17,7 +18,7 @@ export const currentOrg: Writable<CurrentOrg> = writable({
landingpage: {}, landingpage: {},
theme: '' theme: ''
}); });
export const orgAudience = writable([]); export const orgAudience = writable<OrgAudience[]>([]);
export const orgTeam = writable<OrgTeamMember[]>([]); export const orgTeam = writable<OrgTeamMember[]>([]);
export const isOrgAdmin = derived( export const isOrgAdmin = derived(
currentOrg, currentOrg,
@@ -26,6 +27,14 @@ export const isOrgAdmin = derived(
export const currentOrgPath = derived(currentOrg, ($currentOrg) => export const currentOrgPath = derived(currentOrg, ($currentOrg) =>
$currentOrg.siteName ? `/org/${$currentOrg.siteName}` : '' $currentOrg.siteName ? `/org/${$currentOrg.siteName}` : ''
); );
export const currentOrgDomain = derived(currentOrg, ($currentOrg) => {
const browserOrigin = dev && browser && window.location.origin;
return browserOrigin
? browserOrigin
: $currentOrg.siteName
? `https://${$currentOrg.siteName}.classroomio.com`
: '';
});
// Quiz // Quiz
export const createQuizModal = writable({ export const createQuizModal = writable({
+1 -1
View File
@@ -16,7 +16,7 @@ export const user = writable<{
}); });
export const profile = writable<{ export const profile = writable<{
id: string | number | undefined; id: string | undefined;
fullname: string; fullname: string;
avatar_url: string; avatar_url: string;
profile_url?: string; profile_url?: string;
+6 -5
View File
@@ -59,12 +59,12 @@ export interface ExerciseSubmissions {
//=========================================== //===========================================
interface CourseMetadata { interface CourseMetadata {
requirements: string; requirements?: string;
description: string; description?: string;
goals: string; goals?: string;
videoUrl?: ''; videoUrl?: '';
showDiscount: false; showDiscount?: false;
discount: 0; discount?: 0;
paymentLink?: string; paymentLink?: string;
reward?: { reward?: {
show: boolean; show: boolean;
@@ -188,6 +188,7 @@ export interface Course {
is_present: boolean; is_present: boolean;
id: number; id: number;
}[]; }[];
lessons?: Lesson[];
} }
export interface Groupmember { export interface Groupmember {
+8
View File
@@ -21,3 +21,11 @@ export interface OrgTeamMember {
role: string; role: string;
isAdmin: boolean; isAdmin: boolean;
} }
export interface OrgAudience {
id: string;
name: string;
email: string;
avatar_url: string;
date_joined: string;
}
+13 -11
View File
@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { fly } from 'svelte/transition';
import { derived } from 'svelte/store'; import { derived } from 'svelte/store';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { dev, browser } from '$app/environment'; import { dev, browser } from '$app/environment';
@@ -8,9 +9,8 @@
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import { CaptureConsole } from '@sentry/integrations'; import { CaptureConsole } from '@sentry/integrations';
import posthog from 'posthog-js'; import posthog from 'posthog-js';
import { Theme } from 'carbon-components-svelte'; import { Theme, ToastNotification, Loading } from 'carbon-components-svelte';
import type { CarbonTheme } from 'carbon-components-svelte/types/Theme/Theme.svelte'; import type { CarbonTheme } from 'carbon-components-svelte/types/Theme/Theme.svelte';
import { Moon } from 'svelte-loading-spinners';
import LandingNavigation from '$lib/components/Navigation/index.svelte'; import LandingNavigation from '$lib/components/Navigation/index.svelte';
import OrgNavigation from '$lib/components/Navigation/app.svelte'; import OrgNavigation from '$lib/components/Navigation/app.svelte';
import LMSNavigation from '$lib/components/Navigation/lms.svelte'; import LMSNavigation from '$lib/components/Navigation/lms.svelte';
@@ -19,8 +19,6 @@
import Backdrop from '$lib/components/Backdrop/index.svelte'; import Backdrop from '$lib/components/Backdrop/index.svelte';
import OrgSideBar from '$lib/components/Org/SideBar.svelte'; import OrgSideBar from '$lib/components/Org/SideBar.svelte';
import LMSSideBar from '$lib/components/LMS/SideBar.svelte'; import LMSSideBar from '$lib/components/LMS/SideBar.svelte';
// import SideBar from "../components/SideBar/index.svelte";
// import Footer from '$lib/components/Footer/index.svelte';
import Apps from '$lib/components/Apps/index.svelte'; import Apps from '$lib/components/Apps/index.svelte';
import PlayQuiz from '$lib/components/Org/Quiz/Play/index.svelte'; import PlayQuiz from '$lib/components/Org/Quiz/Play/index.svelte';
import { course } from '$lib/components/Course/store'; import { course } from '$lib/components/Course/store';
@@ -177,7 +175,7 @@
// Set user in sentry // Set user in sentry
setSentryUser(); setSentryUser();
const orgRes = await getOrganizations($profile.id); const orgRes = await getOrganizations(profileData.id);
// student redirect // student redirect
if (data.isOrgSite) { if (data.isOrgSite) {
@@ -305,8 +303,16 @@
{:else} {:else}
<main class="dark:bg-black"> <main class="dark:bg-black">
{#if $navigating && $delayedPreloading} {#if $navigating && $delayedPreloading}
<Backdrop> <Backdrop disableCenteredContent={true} className="opacity-90">
<Moon size="60" color="#1d4ed8" unit="px" duration="1s" /> <div class="h-full w-full relative" transition:fly={{ x: -200, duration: 500 }}>
<ToastNotification kind="info-square" class="absolute bottom-5 left-5">
<span slot="title" class="flex items-center">
<span class="mr-2">Redirecting</span>
<Loading withOverlay={false} small />
</span>
<span slot="caption">Taking you to the next page, please wait.</span>
</ToastNotification>
</div>
</Backdrop> </Backdrop>
{/if} {/if}
{#if !hideNavByRoute($page.url.pathname)} {#if !hideNavByRoute($page.url.pathname)}
@@ -351,10 +357,6 @@
{/if} {/if}
</div> </div>
</main> </main>
{#if !['about', ''].includes(path)}
<!-- <Footer /> -->
{/if}
{/if} {/if}
<style> <style>
@@ -1,17 +1,18 @@
<script> <script lang="ts">
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import CourseLandingPage from '$lib/components/CourseLandingPage/index.svelte'; import CourseLandingPage from '$lib/components/CourseLandingPage/index.svelte';
import Editor from '$lib/components/CourseLandingPage/components/Editor/index.svelte'; import Editor from '$lib/components/CourseLandingPage/components/Editor/index.svelte';
import { course } from '$lib/components/Course/store'; import { course } from '$lib/components/Course/store';
import { lessons } from '$lib/components/Course/components/Lesson/store/lessons'; import { lessons } from '$lib/components/Course/components/Lesson/store/lessons';
import type { Course, Lesson } from '$lib/utils/types';
export let data; export let data;
const { courseId } = data; const { courseId } = data;
let courseData = {}; let courseData: Course;
function setCourseData(course = {}, lessons) { function setCourseData(course: Course, lessons: Lesson[]) {
courseData = { ...course, lessons }; courseData = { ...course, lessons };
} }
@@ -23,7 +23,7 @@
triggerSendEmail, triggerSendEmail,
NOTIFICATION_NAME NOTIFICATION_NAME
} from '$lib/utils/services/notification/notification'; } from '$lib/utils/services/notification/notification';
import { currentOrg } from '$lib/utils/store/org'; import { currentOrg, currentOrgDomain } from '$lib/utils/store/org';
import { browser } from '$app/environment'; import { browser } from '$app/environment';
type items = { type items = {
@@ -103,7 +103,7 @@
const { fullname, email } = submissionData?.student; const { fullname, email } = submissionData?.student;
const { title, status_id }: { title: string; status_id: number } = submissionData; const { title, status_id }: { title: string; status_id: number } = submissionData;
const exerciseLink = `${$currentOrg.siteName}.classroomio.com/courses/${courseId}/lessons/${lessonDetails.id}/exercises/${exerciseDetails.id}`; const exerciseLink = `${$currentOrgDomain}/courses/${courseId}/lessons/${lessonDetails.id}/exercises/${exerciseDetails.id}`;
const content = ` const content = `
<p>Hello ${fullname},</p> <p>Hello ${fullname},</p>