CLASSROOMIO-T-32: Landing page with editor v1
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
<script>
|
||||
import CaretSortDown20 from 'carbon-icons-svelte/lib/CaretSortDown20';
|
||||
|
||||
let isExpanded = true;
|
||||
export let handleClick = () => {};
|
||||
export let label = '';
|
||||
export let hideSortIcon = false;
|
||||
export let isGroupActive = false;
|
||||
// export let subMenuItems = [];
|
||||
|
||||
function onClick() {
|
||||
// isExpanded = !isExpanded;
|
||||
handleClick();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div
|
||||
class="item relative flex items-center {isGroupActive && 'active'}"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
on:click={onClick}
|
||||
>
|
||||
{#if !hideSortIcon}
|
||||
<CaretSortDown20
|
||||
class="carbon-icon-sort {isExpanded ? '' : 'carbon-icon-minimize'}"
|
||||
/>
|
||||
{/if}
|
||||
<span class="font-bold">{label}</span>
|
||||
</div>
|
||||
{#if isExpanded}
|
||||
<div class="flex flex-col">
|
||||
<slot />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:global(svg.carbon-icon-sort) {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 0;
|
||||
}
|
||||
:global(svg.carbon-icon-minimize) {
|
||||
transform: rotate(270deg);
|
||||
top: 13px;
|
||||
left: -6px;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: #cae2f9;
|
||||
border-left: 3px solid var(--main-primary-color);
|
||||
}
|
||||
|
||||
.active span {
|
||||
padding-left: 1.3rem;
|
||||
}
|
||||
|
||||
.item span {
|
||||
padding: 12px 24px;
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
background-color: #cae2f9;
|
||||
}
|
||||
</style>
|
||||
@@ -7,7 +7,7 @@
|
||||
import Settings20 from 'carbon-icons-svelte/lib/Settings20';
|
||||
import ChevronLeft16 from 'carbon-icons-svelte/lib/ChevronLeft16';
|
||||
import ChevronRight16 from 'carbon-icons-svelte/lib/ChevronRight16';
|
||||
import Expandable from '../../../Expandable/index.svelte';
|
||||
import NavExpandable from './NavExpandable.svelte';
|
||||
import PageNav from '../../../PageNav/index.svelte';
|
||||
import IconButton from '../../../IconButton/index.svelte';
|
||||
import Avatar from '../../../Avatar/index.svelte';
|
||||
@@ -152,7 +152,7 @@
|
||||
<div class="navItems">
|
||||
{#each navItems as navItem}
|
||||
{#if !navItem.show || (typeof navItem.show === 'function' && navItem.show())}
|
||||
<Expandable
|
||||
<NavExpandable
|
||||
label={navItem.label}
|
||||
handleClick={handleMainGroupClick(navItem.to)}
|
||||
isGroupActive={(path || $page.path) === navItem.to}
|
||||
@@ -190,7 +190,7 @@
|
||||
</a>
|
||||
{/each}
|
||||
{/if}
|
||||
</Expandable>
|
||||
</NavExpandable>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<script>
|
||||
import ChevronLeft16 from 'carbon-icons-svelte/lib/ChevronLeft16';
|
||||
import ChevronRight16 from 'carbon-icons-svelte/lib/ChevronRight16';
|
||||
import { isMobile } from '../../../../utils/store/useMobile';
|
||||
import IconButton from '../../../IconButton/index.svelte';
|
||||
|
||||
let show = true;
|
||||
</script>
|
||||
|
||||
<section
|
||||
class="root z-10 {!show && 'hide'} {$isMobile ? 'fixed shadow-xl' : 'sticky'}"
|
||||
>
|
||||
{#if show}
|
||||
<div class="relative h-full bg-gray-100">
|
||||
<slot />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="toggler rounded-full shadow-lg absolute bottom-0">
|
||||
<IconButton
|
||||
value="toggle"
|
||||
onClick={() => (show = !show)}
|
||||
size={$isMobile ? 'large' : 'small'}
|
||||
toolTipProps={$isMobile
|
||||
? {}
|
||||
: {
|
||||
title: 'Toggle editor',
|
||||
hotkeys: ['B'],
|
||||
direction: 'right',
|
||||
}}
|
||||
>
|
||||
{#if show}
|
||||
<ChevronLeft16 class="carbon-icon" />
|
||||
{:else}
|
||||
<ChevronRight16 class="carbon-icon" />
|
||||
{/if}
|
||||
</IconButton>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style lang="scss">
|
||||
.root {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 300px;
|
||||
max-width: 300px;
|
||||
top: 0;
|
||||
border-right: 1px solid var(--border-color);
|
||||
background-color: rgb(250, 251, 252);
|
||||
|
||||
&.hide {
|
||||
min-width: 15px;
|
||||
max-width: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.toggler {
|
||||
right: -15px;
|
||||
z-index: 10;
|
||||
border: 1px solid var(--border-color);
|
||||
top: 50px;
|
||||
height: fit-content;
|
||||
background: var(--border-color);
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.root {
|
||||
width: 98%;
|
||||
min-width: unset;
|
||||
max-width: unset;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,38 @@
|
||||
<script>
|
||||
import ChevronRight24 from 'carbon-icons-svelte/lib/ChevronRight24';
|
||||
import Container from './Container.svelte';
|
||||
import Expandable from '../../../Expandable/index.svelte';
|
||||
|
||||
let borderBottomGrey = 'border-r-0 border-b border-l-0 border-gray-300';
|
||||
|
||||
const sections = [
|
||||
{
|
||||
title: 'Header',
|
||||
},
|
||||
{
|
||||
title: 'Requirement',
|
||||
},
|
||||
{
|
||||
title: 'Description',
|
||||
},
|
||||
{
|
||||
title: 'Syllabus',
|
||||
},
|
||||
{
|
||||
title: 'About Us',
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<h3 class="bg-white {borderBottomGrey} p-2">Builder</h3>
|
||||
|
||||
{#each sections as section}
|
||||
<button
|
||||
class="flex items-center justify-between p-2 w-full bg-white border border-b-0 border-gray-300"
|
||||
>
|
||||
<p class="mr-2">{section.title} section</p>
|
||||
<ChevronRight24 class="carbon-class" />
|
||||
</button>
|
||||
{/each}
|
||||
</Container>
|
||||
@@ -0,0 +1,207 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import RecentlyViewed16 from 'carbon-icons-svelte/lib/RecentlyViewed16';
|
||||
import CurrencyDollar16 from 'carbon-icons-svelte/lib/CurrencyDollar16';
|
||||
import Alarm16 from 'carbon-icons-svelte/lib/Alarm16';
|
||||
import { stores } from '@sapper/app';
|
||||
import Expandable from '../Expandable/index.svelte';
|
||||
import PrimaryButton from '../PrimaryButton/index.svelte';
|
||||
import MarkdownRender from '../MarkdownRender/index.svelte';
|
||||
|
||||
let activeNavItem = '';
|
||||
|
||||
const data = {
|
||||
title: 'Online Business Masterclass: Sell Your Own Digital Products',
|
||||
shortDescription:
|
||||
'Create, Launch & Market Your Own Online Business w/ Digital Products such as Online Courses, Coaching, eBooks, Webinars+',
|
||||
cost: {
|
||||
currency: '$',
|
||||
price: '300',
|
||||
},
|
||||
requirement:
|
||||
"You don't need any experience creating an online business or digital product. \nYou don't need an online presence, website, or following - but it will help kickstart your online business if you do.",
|
||||
description:
|
||||
"### Have you ever dreamed of starting your own online business?. \n\nOf course I know that :-) I was just thinking if there is some way to do same as getStaticProps for other components too. I don't think such feature is completely necessary, though. \n### Enroll today and get instant access to. \n\nOf course I know that :-) I was just thinking if there is some way to do same as getStaticProps for other components too. I don't think such feature is completely necessary, though.\n ### You will learn many types of digital marketing:\n\n Of course I know that :-) I was just thinking if there is some way to do same as getStaticProps for other components too. I don't think such feature is completely necessary, though. Hello, thank you for reply. Of course I know that :-) I was just thinking if there is some way to do same as getStaticProps for other components too. I don't think such feature is completely necessary, though. Hello, thank you for reply. Of course I know that :-) I was just thinking if there is some way to do same as getStaticProps for other components too. I don't think such feature is completely necessary, though. Hello, thank you for reply. Of course I know that :-) I was just thinking if there is some way to do same as getStaticProps for other components too. I don't think such feature is completely necessary, though. Hello, thank you for reply. Of course I know that :-) I was just thinking if there is some way to do same as getStaticProps for other components too. I don't think such feature is completely necessary, though.",
|
||||
lessons: [
|
||||
{
|
||||
title: 'What is FinTech?',
|
||||
},
|
||||
{
|
||||
title: 'Payments, Cryptocurrencies and Blockchain',
|
||||
},
|
||||
{
|
||||
title: 'Digital Finance and Alternative Finance',
|
||||
},
|
||||
{
|
||||
title: 'FinTech Regulation and RegTech',
|
||||
},
|
||||
{
|
||||
title: 'Data & TechFin',
|
||||
},
|
||||
],
|
||||
aboutUs: {
|
||||
companyName: 'The Brad School',
|
||||
logoUrl: 'https://img-c.udemycdn.com/user/200_H/19701574_95d1_13.jpg',
|
||||
description:
|
||||
'*Learn creative skills, from absolute beginner to advanced mastery.*\nVideo School exists to help you succeed in life. Each course has been hand-tailored to teach a specific skill from photography and video to art, design and business.\n**Whether you’re trying to learn a new skill from scratch, or want to refresh your memory on something you’ve learned in the past, you’ve come to the right place.**\nEducation makes the world a better place. Make your world better with new skills!\nOur courses can be watched 24/7 wherever you are. Most are fully downloadable so you can take them with you. You can also view them on mobile devices with the Udemy mobile app.\nAll courses have a 30-day money-back guarantee so that you can check it out, make sure it’s the right course for you, and get a refund if it’s not!',
|
||||
},
|
||||
};
|
||||
const navItems = [
|
||||
{
|
||||
label: 'Requirement',
|
||||
key: 'requirement',
|
||||
},
|
||||
{
|
||||
label: 'Description',
|
||||
key: 'description',
|
||||
},
|
||||
{
|
||||
label: 'Syllabus',
|
||||
key: 'syllabus',
|
||||
},
|
||||
{
|
||||
label: 'About Us',
|
||||
key: 'about-us',
|
||||
},
|
||||
];
|
||||
|
||||
const expandableRootClass =
|
||||
'max-w-4xl pt-5 my-3 border-r-0 border-b border-l-0 border-gray-300';
|
||||
const { page } = stores();
|
||||
|
||||
function handleEnrol() {}
|
||||
function handleNavItemClick(navItem) {
|
||||
return () => {
|
||||
activeNavItem = navItem;
|
||||
};
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
activeNavItem = window.location.hash || navItems[0].key;
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.title}</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="w-full bg-white flex flex-col items-center">
|
||||
<section
|
||||
class="w-full flex items-center justify-center bg-gray-900 text-white p-6 pb-10"
|
||||
>
|
||||
<div class="container flex justify-between items-center">
|
||||
<div class="course-description mr-3">
|
||||
<h1>
|
||||
{data.title}
|
||||
</h1>
|
||||
<h5>
|
||||
{data.shortDescription}
|
||||
</h5>
|
||||
<div>
|
||||
<span class="flex items-center">
|
||||
<RecentlyViewed16 class="carbon-icon mr-2" />
|
||||
Last updated 10/2021
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-container bg-white p-3 flex items-start flex-col">
|
||||
<p class="mb-2 text-black text-md flex items-center">
|
||||
<Alarm16 class="carbon-icon active mr-2" />
|
||||
Estimated 8 weeks
|
||||
</p>
|
||||
<p class="mb-2 text-black text-md flex items-center">
|
||||
<CurrencyDollar16 class="carbon-icon active mr-2" />
|
||||
{data.cost.currency}{data.cost.price}
|
||||
</p>
|
||||
<PrimaryButton
|
||||
label="Enrol"
|
||||
onClick={handleEnrol}
|
||||
className="md:w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<nav
|
||||
class="w-full z-10 max-w-4xl flex items-center justify-evenly py-4 px-4 bg-gray-100 mt-4 sticky top-0"
|
||||
>
|
||||
{#each navItems as navItem}
|
||||
<p
|
||||
class="text-md text-gray-900 {activeNavItem === navItem.key &&
|
||||
'font-bold'}"
|
||||
on:click={handleNavItemClick(navItem.key)}
|
||||
>
|
||||
<a href="{$page.path}#{navItem.key}">{navItem.label}</a>
|
||||
</p>
|
||||
{/each}
|
||||
</nav>
|
||||
|
||||
<Expandable
|
||||
id="requirement"
|
||||
title="Requirement"
|
||||
titleClass="text-2xl"
|
||||
rootClass={expandableRootClass}
|
||||
supportsLink={true}
|
||||
>
|
||||
<MarkdownRender content={data.requirement} disableMaxWidth={true} />
|
||||
</Expandable>
|
||||
|
||||
<Expandable
|
||||
id="description"
|
||||
title="Description"
|
||||
titleClass="text-2xl"
|
||||
rootClass={expandableRootClass}
|
||||
supportsLink={true}
|
||||
>
|
||||
<MarkdownRender content={data.description} disableMaxWidth={true} />
|
||||
</Expandable>
|
||||
|
||||
<Expandable
|
||||
id="syllabus"
|
||||
title="Syllabus"
|
||||
titleClass="text-2xl"
|
||||
rootClass={expandableRootClass}
|
||||
supportsLink={true}
|
||||
>
|
||||
{#each data.lessons as lesson, index}
|
||||
<div class="flex items-center my-2">
|
||||
<strong class="mr-2">Lesson {index + 1}. </strong>
|
||||
{lesson.title}
|
||||
</div>
|
||||
{/each}
|
||||
</Expandable>
|
||||
|
||||
<Expandable
|
||||
id="about-us"
|
||||
title="About Us - {data.aboutUs.companyName}"
|
||||
titleClass="text-2xl"
|
||||
rootClass={expandableRootClass}
|
||||
supportsLink={true}
|
||||
>
|
||||
<div class="w-full">
|
||||
<img
|
||||
src={data.aboutUs.logoUrl}
|
||||
alt={data.aboutUs.companyName}
|
||||
height="260"
|
||||
width="260"
|
||||
class="rounded-full m-auto"
|
||||
/>
|
||||
</div>
|
||||
<MarkdownRender content={data.description} disableMaxWidth={true} />
|
||||
</Expandable>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
max-width: 800px;
|
||||
|
||||
.course-description {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.action-container {
|
||||
height: fit-content;
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,66 +1,57 @@
|
||||
<script>
|
||||
import CaretSortDown20 from "carbon-icons-svelte/lib/CaretSortDown20";
|
||||
import { stores } from '@sapper/app';
|
||||
import ChevronDown24 from 'carbon-icons-svelte/lib/ChevronDown24';
|
||||
import ChevronUp24 from 'carbon-icons-svelte/lib/ChevronUp24';
|
||||
import Link24 from 'carbon-icons-svelte/lib/Link24';
|
||||
|
||||
let isExpanded = true;
|
||||
export let handleClick = () => {};
|
||||
export let label = "";
|
||||
export let hideSortIcon = false;
|
||||
export let isGroupActive = false;
|
||||
// export let subMenuItems = [];
|
||||
export let id = '';
|
||||
export let title = '';
|
||||
export let titleClass = '';
|
||||
export let disableContainerPadding = false;
|
||||
export let rootClass = '';
|
||||
export let supportsLink = false;
|
||||
|
||||
function onClick() {
|
||||
// isExpanded = !isExpanded;
|
||||
handleClick();
|
||||
export let isExpanded = true;
|
||||
|
||||
const { page } = stores();
|
||||
|
||||
function handleClick(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
isExpanded = !isExpanded;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div {id} class="w-full bg-white {rootClass}">
|
||||
<div
|
||||
class="item relative flex items-center {isGroupActive && 'active'}"
|
||||
class="w-full relative flex items-center justify-between {!disableContainerPadding &&
|
||||
'p-5'}"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
on:click={onClick}
|
||||
on:click={handleClick}
|
||||
>
|
||||
{#if !hideSortIcon}
|
||||
<CaretSortDown20
|
||||
class="carbon-icon-sort {isExpanded ? '' : 'carbon-icon-minimize'}"
|
||||
/>
|
||||
<p class="font-bold flex items-center {titleClass}">
|
||||
{title}
|
||||
{#if supportsLink}
|
||||
<a
|
||||
class="ml-2"
|
||||
href="{$page.path}#{id}"
|
||||
on:click={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Link24 class="carbon-icon" />
|
||||
</a>
|
||||
{/if}
|
||||
</p>
|
||||
|
||||
{#if isExpanded}
|
||||
<ChevronUp24 class="carbon-icon" />
|
||||
{:else}
|
||||
<ChevronDown24 class="carbon-icon" />
|
||||
{/if}
|
||||
<span class="font-bold">{label}</span>
|
||||
</div>
|
||||
{#if isExpanded}
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col p-5">
|
||||
<slot />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:global(svg.carbon-icon-sort) {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 0;
|
||||
}
|
||||
:global(svg.carbon-icon-minimize) {
|
||||
transform: rotate(270deg);
|
||||
top: 13px;
|
||||
left: -6px;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: #cae2f9;
|
||||
border-left: 3px solid var(--main-primary-color);
|
||||
}
|
||||
|
||||
.active span {
|
||||
padding-left: 1.3rem;
|
||||
}
|
||||
|
||||
.item span {
|
||||
padding: 12px 24px;
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
background-color: #cae2f9;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,10 +2,21 @@
|
||||
import marked from 'marked';
|
||||
|
||||
export let content = '';
|
||||
export let disableMaxWidth = false;
|
||||
</script>
|
||||
|
||||
<article class="m-auto prose prose-sm sm:prose p-2">
|
||||
<article
|
||||
class="m-auto prose prose-sm sm:prose p-2 {disableMaxWidth &&
|
||||
'disable-max-width'}"
|
||||
>
|
||||
{#if !!content}
|
||||
{@html marked(content, { breaks: true, gfm: true })}
|
||||
{/if}
|
||||
</article>
|
||||
|
||||
<style>
|
||||
.disable-max-width {
|
||||
max-width: none !important;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
html {
|
||||
--scrollbarBG: #fff;
|
||||
--thumbBG: #ccc;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
#calendar .grid {
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
}
|
||||
|
||||
function isCoursePage(path) {
|
||||
return /courses\/[a-z 0-9 -]/.test(path);
|
||||
return /course[s]*\/[a-z 0-9 -]/.test(path);
|
||||
}
|
||||
|
||||
function handleResize() {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<script context="module">
|
||||
export async function preload({ params }) {
|
||||
return { slug: params.slug };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import CourseLandingPage from '../../components/CourseLandingPage/index.svelte';
|
||||
import Editor from '../../components/CourseLandingPage/components/Editor/index.svelte';
|
||||
import { isMobile } from '../../utils/store/useMobile';
|
||||
</script>
|
||||
|
||||
<div class="root">
|
||||
<Editor />
|
||||
<div class="rightBar" class:isMobile={$isMobile}>
|
||||
<CourseLandingPage />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.root {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.rightBar {
|
||||
flex-grow: 1;
|
||||
width: calc(100% - 360px);
|
||||
}
|
||||
|
||||
.rightBar.isMobile {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user