chore: improve style of lesson card (#177)

* chore: reduce size of lesson card based off customer review

* more styling improvements
This commit is contained in:
Rotimi Best
2024-02-21 18:59:10 +01:00
committed by GitHub
parent 4d312cab18
commit 7f24da00a5
3 changed files with 123 additions and 190 deletions
@@ -28,8 +28,8 @@
is_unlocked: false is_unlocked: false
}; };
function getLessonOrder(id = '') { function getLessonOrder(id = '', fallbackIndex) {
const index = $lessons.findIndex((lesson) => lesson.id === id); const index = fallbackIndex || $lessons.findIndex((lesson) => lesson.id === id);
if (index < 9) { if (index < 9) {
return '0' + (index + 1); return '0' + (index + 1);
} else { } else {
@@ -65,7 +65,7 @@
> >
<div class="mr-5"> <div class="mr-5">
<TextChip <TextChip
value={getLessonOrder(lesson.id || '')} value={getLessonOrder('', $lessons.length)}
size="sm" size="sm"
shape="rounded-full" shape="rounded-full"
className="bg-primary-200 text-primary-600 text-xs" className="bg-primary-200 text-primary-600 text-xs"
@@ -75,6 +75,7 @@
<div class="w-full md:w-4/5"> <div class="w-full md:w-4/5">
<div class="flex flex-row gap-1 md:gap-2"> <div class="flex flex-row gap-1 md:gap-2">
<TextField <TextField
label="Lesson title"
bind:value={lesson.title} bind:value={lesson.title}
autofocus={true} autofocus={true}
className="flex-1 min-w-lg max-w-lg" className="flex-1 min-w-lg max-w-lg"
@@ -21,11 +21,14 @@
</script> </script>
<div <div
class="{hideOnMobile class="header dark:bg-black dark:border-neutral-600 bg-white {!disableSticky &&
? 'hidden lg:flex'
: ''} header dark:bg-black dark:border-neutral-600 bg-white flex items-center justify-between {!disableSticky &&
'sticky'} {paddingClass} {dynamicRootClass}" 'sticky'} {paddingClass} {dynamicRootClass}"
style={overidableStyle} style={overidableStyle}
>
<div
class="{hideOnMobile
? 'hidden lg:flex'
: ''} max-w-4xl m-auto flex items-center justify-between"
> >
{#if !!title} {#if !!title}
{#if isTitleEditable} {#if isTitleEditable}
@@ -91,6 +94,7 @@
{/if} {/if}
<slot name="widget" /> <slot name="widget" />
</div> </div>
</div>
<style> <style>
.header { .header {
@@ -1,37 +1,31 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { dndzone } from 'svelte-dnd-action'; import { dndzone } from 'svelte-dnd-action';
import UnlockedIcon from 'carbon-icons-svelte/lib/Unlocked.svelte';
import LockedIcon from 'carbon-icons-svelte/lib/Locked.svelte';
import SaveIcon from 'carbon-icons-svelte/lib/Save.svelte';
import TrashCanIcon from 'carbon-icons-svelte/lib/TrashCan.svelte';
import Calendar from 'carbon-icons-svelte/lib/Calendar.svelte';
import Video from 'carbon-icons-svelte/lib/Video.svelte';
import WatsonHealthTextAnnotationToggle from 'carbon-icons-svelte/lib/WatsonHealthTextAnnotationToggle.svelte';
import { OverflowMenu, OverflowMenuItem } from 'carbon-components-svelte';
import PageNav from '$lib/components/PageNav/index.svelte'; import PageNav from '$lib/components/PageNav/index.svelte';
import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte'; import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
import Box from '$lib/components/Box/index.svelte'; import Box from '$lib/components/Box/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import IconButton from '$lib/components/IconButton/index.svelte';
import Select from '$lib/components/Form/Select.svelte';
import { updateLesson } from '$lib/utils/services/courses'; import { updateLesson } from '$lib/utils/services/courses';
import CourseContainer from '$lib/components/CourseContainer/index.svelte'; import CourseContainer from '$lib/components/CourseContainer/index.svelte';
import type { Lesson } from '$lib/utils/types';
import { import {
lessons, lessons,
handleSaveLesson, handleDelete,
handleDelete handleSaveLesson
} from '$lib/components/Course/components/Lesson/store/lessons'; } from '$lib/components/Course/components/Lesson/store/lessons';
import { course, group } from '$lib/components/Course/store';
import PageBody from '$lib/components/PageBody/index.svelte'; import PageBody from '$lib/components/PageBody/index.svelte';
import AddLessonModal from '$lib/components/Course/components/Lesson/AddLessonModal.svelte';
import DeleteLessonConfirmation from '$lib/components/Course/components/Lesson/DeleteLessonConfirmation.svelte';
import { handleAddLessonWidget } from '$lib/components/Course/components/Navigation/store';
import { Video, Calendar } from 'carbon-icons-svelte';
import { OverflowMenu, OverflowMenuItem } from 'carbon-components-svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import Select from '$lib/components/Form/Select.svelte';
import TextChip from '$lib/components/Chip/Text.svelte'; import TextChip from '$lib/components/Chip/Text.svelte';
import Avatar from '$lib/components/Apps/components/Poll/components/Avatar.svelte'; import Avatar from '$lib/components/Apps/components/Poll/components/Avatar.svelte';
import AddLessonModal from '$lib/components/Course/components/Lesson/AddLessonModal.svelte'; import { course, group } from '$lib/components/Course/store';
import DateField from '$lib/components/Form/Date.svelte'; import DateField from '$lib/components/Form/Date.svelte';
import DeleteLessonConfirmation from '$lib/components/Course/components/Lesson/DeleteLessonConfirmation.svelte'; import type { Lesson } from '$lib/utils/types';
import { handleAddLessonWidget } from '$lib/components/Course/components/Navigation/store.js';
export let data; export let data;
@@ -42,17 +36,6 @@
const flipDurationMs = 300; const flipDurationMs = 300;
function formatDate(date: string | undefined) {
if (!date) return '';
const d = new Date(date);
const ye = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(d);
const mo = new Intl.DateTimeFormat('en', { month: '2-digit' }).format(d);
const da = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(d);
return `${ye}-${mo}-${da}`;
}
function addLesson() { function addLesson() {
$handleAddLessonWidget.open = true; $handleAddLessonWidget.open = true;
} }
@@ -78,6 +61,17 @@
}); });
} }
function formatDate(date: string | undefined) {
if (!date) return '';
const d = new Date(date);
const ye = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(d);
const mo = new Intl.DateTimeFormat('en', { month: '2-digit' }).format(d);
const da = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(d);
return `${ye}-${mo}-${da}`;
}
function getLessonOrder(id: string) { function getLessonOrder(id: string) {
const index = $lessons.findIndex((lesson) => lesson.id === id); const index = $lessons.findIndex((lesson) => lesson.id === id);
@@ -127,8 +121,9 @@
> >
{#each $lessons as lesson (lesson.id)} {#each $lessons as lesson (lesson.id)}
<div <div
class="sm:min-h-[245px] md:min-h-[100px] lg:min-h-[190px] relative m-auto rounded-md border-2 border-gray-200 py-3 px-5 mb-4 flex items-center dark:bg-neutral-800" class="relative m-auto max-w-xl rounded-md border-2 border-gray-200 p-5 mb-4 flex items-center dark:bg-neutral-800 dark:border-neutral-700 hover:scale-95 transition-all ease-in-out"
> >
<!-- Number Chip -->
<div class="mr-5"> <div class="mr-5">
<TextChip <TextChip
value={getLessonOrder(lesson.id)} value={getLessonOrder(lesson.id)}
@@ -138,16 +133,18 @@
/> />
</div> </div>
<!-- Lesson Content -->
<div class="w-4/5"> <div class="w-4/5">
<!-- Lesson Title -->
{#if lessonEditing === lesson.id} {#if lessonEditing === lesson.id}
<TextField bind:value={lesson.title} autoFocus={true} className="max-w-lg" /> <TextField bind:value={lesson.title} autoFocus={true} className="max-w-lg" />
{:else} {:else}
<h3 class="dark:text-white text-xl m-0 flex items-center"> <h3 class="dark:text-white text-lg m-0 flex items-center">
<a <a
href={isStudent && !lesson.is_unlocked href={isStudent && !lesson.is_unlocked
? $page.url.pathname ? $page.url.pathname
: '/courses/' + $course.id + '/lessons/' + lesson.id} : '/courses/' + $course.id + '/lessons/' + lesson.id}
class="dark:text-white no-underline hover:underline font-semibold text-black {isStudent && class="dark:text-white no-underline hover:underline font-medium text-black {isStudent &&
!lesson.is_unlocked !lesson.is_unlocked
? 'cursor-not-allowed' ? 'cursor-not-allowed'
: ''}" : ''}"
@@ -156,12 +153,8 @@
</a> </a>
</h3> </h3>
{/if} {/if}
<!-- <div class="flex items-center mb-2">
<div class="flex items-center mr-2">
{resources.map((r) => `${r.value} ${r.label}`).join(', ')}
</div>
</div> -->
<!-- Lesson Educator -->
<div <div
class="flex items-start justify-between flex-col lg:flex-row lg:items-center mt-2 w-4/5" class="flex items-start justify-between flex-col lg:flex-row lg:items-center mt-2 w-4/5"
> >
@@ -189,6 +182,7 @@
{/if} {/if}
</div> </div>
<!-- Lesson Date -->
<div class="flex items-center lg:mb-0"> <div class="flex items-center lg:mb-0">
{#if lessonEditing === lesson.id} {#if lessonEditing === lesson.id}
<DateField <DateField
@@ -206,6 +200,7 @@
{/if} {/if}
</div> </div>
<!-- Lesson Call url -->
<div class="flex items-center mb-3 lg:mb-0"> <div class="flex items-center mb-3 lg:mb-0">
{#if lessonEditing === lesson.id} {#if lessonEditing === lesson.id}
<TextField <TextField
@@ -228,69 +223,12 @@
{/if} {/if}
</div> </div>
</div> </div>
<div class="flex flex-row absolute sm:bottom-20 bottom-10 right-10">
<div class="success hidden md:block">
<IconButton
disabled={isStudent}
onClick={() => {
lesson.is_unlocked = !lesson.is_unlocked;
handleSaveLesson(lesson, $course.id);
}}
toolTipProps={isStudent
? undefined
: {
title: `Click to ${lesson.is_unlocked ? 'lock' : 'unlock'}`,
direction: 'left',
hotkeys: []
}}
>
{#if lesson.is_unlocked}
<UnlockedIcon size={24} class="carbon-icon dark:text-white" />
{:else}
<LockedIcon size={24} class="carbon-icon dark:text-white" />
{/if}
</IconButton>
</div> </div>
<!-- 3 dot edit -->
<div class="flex flex-row">
<RoleBasedSecurity allowedRoles={[1, 2]}> <RoleBasedSecurity allowedRoles={[1, 2]}>
<div class="hidden md:block"> <OverflowMenu flipped size="xl" class="absolute top-0 right-0">
{#if lessonEditing === lesson.id}
<IconButton
onClick={() => {
lessonEditing = undefined;
handleSaveLesson(lesson, $course.id);
}}
>
<SaveIcon size={24} class="carbon-icon dark:text-white" />
</IconButton>
{:else}
<IconButton onClick={() => (lessonEditing = lesson.id)}>
<WatsonHealthTextAnnotationToggle
size={32}
class="carbon-icon dark:text-white"
/>
</IconButton>
{/if}
</div>
</RoleBasedSecurity>
<RoleBasedSecurity allowedRoles={[1, 2]}>
<div class="hidden md:block">
<IconButton
onClick={() => {
lessonToDelete = lesson;
openDeleteModal = true;
}}
>
<TrashCanIcon size={24} class="carbon-icon dark:text-white" />
</IconButton>
</div>
</RoleBasedSecurity>
<RoleBasedSecurity allowedRoles={[1, 2]}>
<div class="overflowmenu">
<OverflowMenu size="xl" class="block absolute right-10 bottom-4 pl-4">
<OverflowMenuItem <OverflowMenuItem
disabled={isStudent} disabled={isStudent}
text={lesson.is_unlocked ? 'Lock' : 'Unlock'} text={lesson.is_unlocked ? 'Lock' : 'Unlock'}
@@ -310,13 +248,11 @@
} }
}} }}
/> />
<OverflowMenuItem danger text="Delete" on:click={handleDelete(lesson.id)} /> <OverflowMenuItem danger text="Delete" on:click={() => handleDelete(lesson.id)} />
</OverflowMenu> </OverflowMenu>
</div>
</RoleBasedSecurity> </RoleBasedSecurity>
</div> </div>
</div> </div>
</div>
{:else} {:else}
<Box> <Box>
<div class="flex justify-between flex-col items-center w-[90%] md:w-96"> <div class="flex justify-between flex-col items-center w-[90%] md:w-96">
@@ -344,11 +280,3 @@
{/if} {/if}
</PageBody> </PageBody>
</CourseContainer> </CourseContainer>
<style>
@media (min-width: 760px) {
.overflowmenu {
display: none !important;
}
}
</style>