CLASSROOMIO-T-32: Landing page with editor v1

This commit is contained in:
Rotimi Best
2022-01-03 20:28:35 +02:00
parent 88cfadba3e
commit 7d7d68594b
10 changed files with 476 additions and 54 deletions
@@ -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>
+40 -49
View File
@@ -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>
+12 -1
View File
@@ -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>
+1
View File
@@ -7,6 +7,7 @@
html {
--scrollbarBG: #fff;
--thumbBG: #ccc;
scroll-behavior: smooth;
}
#calendar .grid {
+1 -1
View File
@@ -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() {
+34
View File
@@ -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>