Webflow course card clone

This commit is contained in:
Rotimi Best
2023-09-13 06:39:46 +01:00
parent c9fa0b6098
commit ecbd75b00f
7 changed files with 64 additions and 78 deletions
@@ -1,18 +1,14 @@
<script lang="ts"> <script lang="ts">
import Dropdown from '$lib/components/Dropdown/index.svelte'; import { Tag } from 'carbon-components-svelte';
import { copyCourseModal } from '$lib/components/Courses/store'; // import { ROLE } from '$lib/utils/constants/roles';
import { ROLE } from '$lib/utils/constants/roles';
import getCurrencyFormatter from '$lib/utils/functions/getCurrencyFormatter'; import getCurrencyFormatter from '$lib/utils/functions/getCurrencyFormatter';
import OverflowMenuHorizontalIcon from 'carbon-icons-svelte/lib/OverflowMenuHorizontal.svelte';
import ArrowRight from 'carbon-icons-svelte/lib/ArrowRight.svelte';
// import { deleteCourse } from '$lib/utils/services/courses';
export let bannerImage: string | undefined; export let bannerImage: string | undefined;
export let id = ''; export let id = '';
export let slug = ''; export let slug = '';
export let title = ''; export let title = '';
export let description = ''; export let description = '';
export let role_id = ROLE.STUDENT; // export let role_id = ROLE.STUDENT;
export let isPublished = false; export let isPublished = false;
export let cost = 0; export let cost = 0;
export let totalLessons = 0; export let totalLessons = 0;
@@ -22,89 +18,75 @@
let formatter = getCurrencyFormatter(currency); let formatter = getCurrencyFormatter(currency);
function getOptions() { // function getOptions() {
return [ // return [
{ // {
label: 'Make a copy', // label: 'Make a copy',
// Show this option only if user has admin control over this course. // // Show this option only if user has admin control over this course.
show: () => role_id === ROLE.ADMIN || role_id === ROLE.TUTOR, // show: () => role_id === ROLE.ADMIN || role_id === ROLE.TUTOR,
onClick() { // onClick() {
// IIFI of copyCourseModal // // IIFI of copyCourseModal
(() => { // (() => {
$copyCourseModal.id = id; // $copyCourseModal.id = id;
$copyCourseModal.open = true; // $copyCourseModal.open = true;
$copyCourseModal.title = `Copy of ${title}`; // $copyCourseModal.title = `Copy of ${title}`;
})(); // })();
} // }
} // }
// { // // {
// label: 'Delete', // // label: 'Delete',
// show: () => role_id === ROLE.TUTOR, // // show: () => role_id === ROLE.TUTOR,
// onClick() { // // onClick() {
// (async () => { // // (async () => {
// await deleteCourse(id); // // await deleteCourse(id);
// onDelete(id); // // onDelete(id);
// console.log('Deleting'); // // console.log('Deleting');
// })(); // // })();
// } // // }
// } // // }
].filter((option) => option.show()); // ].filter((option) => option.show());
} // }
</script> </script>
<a rel="prefetch" href={isOnLandingPage ? `/course/${slug}` : `/courses/${id}`} class=" text-black"> <a rel="prefetch" href={isOnLandingPage ? `/course/${slug}` : `/courses/${id}`} class=" text-black">
<div <div
class="root w-full md:w-80 border bg-gray-100 dark:bg-gray-800 mb-4 rounded-md hover:shadow-2xl transition ease-in-out relative" class="border border-gray w-full max-w-[400px] relative hover:shadow-lg transition-all ease-in-out"
> >
{#if !isOnLandingPage} <div class="p-4">
<Dropdown options={getOptions()} classNames="absolute top-4 right-4" isIcon={true}> <div class=" mb-5">
<div class="p-1 rounded-full bg-white dark:bg-gray-600"> <img
<OverflowMenuHorizontalIcon size={20} class="carbon-icon dark:text-white" /> class="h-2/5 w-full rounded"
</div> src={bannerImage ?? '/images/classroomio-course-img-template.jpg'}
</Dropdown> alt="Course Logo"
{/if} />
<img </div>
class="h-2/5 w-full rounded-tl rounded-tr"
src={bannerImage ?? '/images/classroomio-course-img-template.jpg'} <h3 class="text-xl dark:text-white title">{title}</h3>
alt="Course Logo" <p class="mt-2 text-sm text-gray-500 dark:text-gray-300 description">
/>
<div class="px-3 py-5">
<h4 class="dark:text-white title text-md font-bold">
{title}
</h4>
<p
class="description text-left text-sm font-small flex flex-col text-gray-500 dark:text-white my-3"
title={description}
>
{description} {description}
</p> </p>
<div class="flex justify-between"> </div>
<p class="dark:text-white">{totalLessons} lessons</p>
<div class="px-4 border border-gray border-b-0 border-l-0 border-r-0 footer">
<p class="text-xs pt-2 pl-2 dark:text-white">{totalLessons} lessons</p>
<p class="text-xs py-2">
{#if isOnLandingPage} {#if isOnLandingPage}
<ArrowRight size={24} class="carbon-class" /> <span class="px-2">{!cost ? 'Free' : formatter.format(cost)}</span>
{:else} {:else}
<div class="rounded dark:text-white bg-{isPublished ? 'green' : 'red'}-200 py-1 px-2"> <Tag type={isPublished ? 'green' : 'cool-gray'}>
{#if isPublished} {#if isPublished}
Published Published
{:else} {:else}
Unpublished Unpublished
{/if} {/if}
</div> </Tag>
{/if} {/if}
</div>
<p class="dark:text-white text-gray-500 text-xs mt-1">
{!cost ? 'free' : formatter.format(cost)}
</p> </p>
</div> </div>
</div> </div>
</a> </a>
<style> <style>
.root {
min-height: 370px;
}
a, a,
a:hover { a:hover {
text-decoration: none; text-decoration: none;
-1
View File
@@ -21,7 +21,6 @@
{#each $courses as courseData} {#each $courses as courseData}
<Card <Card
id={courseData.id} id={courseData.id}
logo={courseData.logo}
bannerImage={courseData.banner_image} bannerImage={courseData.banner_image}
title={courseData.title} title={courseData.title}
description={courseData.description} description={courseData.description}
@@ -305,7 +305,7 @@
{/if} {/if}
{#if $courses.length > 3} {#if $courses.length > 3}
<div class="w-full flex justify-center"> <div class="w-full mt-3 flex justify-center">
<PrimaryButton <PrimaryButton
variant={VARIANTS.OUTLINED} variant={VARIANTS.OUTLINED}
onClick={() => (viewAll = !viewAll)} onClick={() => (viewAll = !viewAll)}
@@ -1,6 +1,6 @@
import { PUBLIC_ROUTES } from '$lib/utils/constants/routes'; import { PUBLIC_ROUTES } from '$lib/utils/constants/routes';
export default (route) => { export default (route = '') => {
return PUBLIC_ROUTES.some((publicRoute) => { return PUBLIC_ROUTES.some((publicRoute) => {
const regex = new RegExp(publicRoute, 'g'); const regex = new RegExp(publicRoute, 'g');
return regex.test(route); return regex.test(route);
@@ -0,0 +1,3 @@
export default (path: string): boolean => {
return ['login', 'signup', 'onboarding'].some((r) => path.includes(r)) || path === '';
};
+5 -1
View File
@@ -90,7 +90,11 @@ export async function getOrganizations(userId) {
}); });
orgs.set(orgsArray); orgs.set(orgsArray);
currentOrg.set(orgsArray[0]);
const _cOrg = get(currentOrg);
if (!_cOrg.siteName) {
currentOrg.set(orgsArray[0]);
}
} }
return { return {
+4 -6
View File
@@ -36,6 +36,7 @@
import { currentOrg } from '$lib/utils/store/org'; import { currentOrg } from '$lib/utils/store/org';
import { setTheme } from '$lib/utils/functions/theme'; import { setTheme } from '$lib/utils/functions/theme';
import hideNavByRoute from '$lib/utils/functions/routes/hideNavByRoute'; import hideNavByRoute from '$lib/utils/functions/routes/hideNavByRoute';
import shouldRedirectOnAuth from '$lib/utils/functions/routes/shouldRedirectOnAuth';
import AddOrgModal from '$lib/components/Org/AddOrgModal/AddOrgModal.svelte'; import AddOrgModal from '$lib/components/Org/AddOrgModal/AddOrgModal.svelte';
import '../app.postcss'; import '../app.postcss';
@@ -174,10 +175,7 @@
goto(ROUTE.ONBOARDING); goto(ROUTE.ONBOARDING);
} else if (params.has('redirect')) { } else if (params.has('redirect')) {
goto(params.get('redirect') || ''); goto(params.get('redirect') || '');
} else if ( } else if (shouldRedirectOnAuth(path)) {
['login', 'signup', 'onboarding', 'invite'].some((r) => path.includes(r)) ||
path === '' // for home page
) {
// By default redirect to first organization // By default redirect to first organization
goto(`/org/${orgRes.currentOrg.siteName}`); goto(`/org/${orgRes.currentOrg.siteName}`);
} }
@@ -317,14 +315,14 @@
{#if !isQuizPage($page.url.pathname)} {#if !isQuizPage($page.url.pathname)}
<OrgSideBar /> <OrgSideBar />
{/if} {/if}
<div class="org-slot bg-white dark:bg-gray-800 w-full"> <div class="org-slot w-full bg-white dark:bg-gray-800">
<slot /> <slot />
</div> </div>
</div> </div>
{:else if isLMSPage($page.url.pathname)} {:else if isLMSPage($page.url.pathname)}
<div class="org-root w-full flex items-center justify-between"> <div class="org-root w-full flex items-center justify-between">
<LMSSideBar /> <LMSSideBar />
<div class="org-slot bg-white dark:bg-gray-800 w-full"> <div class="org-slot w-full bg-white dark:bg-gray-800">
<slot /> <slot />
</div> </div>
</div> </div>