CLASSROOMIO-T-82: Fix sidebar navs CLASSROOMIO-T-82: Dark Mode Icon Fix CLASSROOMIO-T-82: Icon Dark Mode Final fix CLASSROOMIO-T-82: Dark mode icon fix CLASSROOMIO-T-82: Icon Dark Mode fix Merge branch 'CLASSROOMIO-T-82' of https://gitlab.com/thenextgreat/classroomio into CLASSROOMIO-T-82 CLASSROOMIO-T-82: - Impliment Search Functionality - Dark Mode Fix Merge branch 'main' into CLASSROOMIO-T-82 CLASSROOMIO-T-82: Saving fix and dark mode button bug Merge branch 'main' into CLASSROOMIO-T-82 CLASSROOMIO-T-82: Attendance Redesign CLASSROOMIO-T-82: Redesign Attendance Page Co-authored-by: Rotimi Best <rotimiibitoyeemma@gmail.com> Co-authored-by: tunny17 <tvnji17@gmail.com> Merge-request: CLASSROOMIO-MR-34 Merged-by: Best Admin <best@digdippa.com>
295 lines
8.7 KiB
Svelte
295 lines
8.7 KiB
Svelte
<script>
|
|
import { onMount } from 'svelte';
|
|
import { goto } from '$app/navigation';
|
|
import { page } from '$app/stores';
|
|
import hotkeys from 'hotkeys-js';
|
|
import { browser } from '$app/environment';
|
|
import LockedIcon from 'carbon-icons-svelte/lib/Locked.svelte';
|
|
// import ArrowLeftIcon from 'carbon-icons-svelte/lib/ArrowLeft.svelte';
|
|
import CheckmarkFilled from 'carbon-icons-svelte/lib/CheckmarkFilled.svelte';
|
|
// import SettingsIcon from 'carbon-icons-svelte/lib/Settings.svelte';
|
|
import ChevronLeftIcon from 'carbon-icons-svelte/lib/ChevronLeft.svelte';
|
|
import ChevronRightIcon from 'carbon-icons-svelte/lib/ChevronRight.svelte';
|
|
import NavExpandable from './NavExpandable.svelte';
|
|
import PageNav from '$lib/components/PageNav/index.svelte';
|
|
import IconButton from '$lib/components/IconButton/index.svelte';
|
|
// import Avatar from '$lib/components/Avatar/index.svelte';
|
|
import { getNavItemRoute, getLessonsRoute, getLectureNo } from '$lib/components/Course/function';
|
|
|
|
import TextChip from '$lib/components/Chip/Text.svelte';
|
|
// import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
|
|
import Settings from '../Settings/index.svelte';
|
|
// import { settingsDialog } from '../Settings/store';
|
|
import { lessons } from '../Lesson/store/lessons';
|
|
import { course } from '$lib/components/Course/store';
|
|
import { updateCourse } from '$lib/utils/services/courses';
|
|
import { profile } from '$lib/utils/store/user';
|
|
import { currentOrgPath } from '$lib/utils/store/org';
|
|
import { isMobile } from '$lib/utils/store/useMobile';
|
|
|
|
// export let lessonId;
|
|
export let path;
|
|
export let isStudent = null;
|
|
|
|
let show = null;
|
|
let activeClass = 'bg-gray-200 dark:bg-gray-800';
|
|
let isLessonActive = false;
|
|
|
|
function handleMainGroupClick(href) {
|
|
return () => {
|
|
if ($isMobile) {
|
|
setTimeout(() => (show = false), 500);
|
|
}
|
|
goto(href);
|
|
};
|
|
}
|
|
|
|
let navItems = [];
|
|
|
|
function getHref(item) {
|
|
return item.to;
|
|
// return item.is_unlocked ? item.to : path || $page.url.pathname
|
|
}
|
|
|
|
function handleSaveTitle() {
|
|
updateCourse($course.id, { title: $course.title });
|
|
}
|
|
|
|
function handleMobileChange(isMobile) {
|
|
if (isMobile) show = false;
|
|
else show = true;
|
|
}
|
|
|
|
onMount(() => {
|
|
if (browser) {
|
|
if (localStorage.getItem('hideCourseNav')) {
|
|
show = localStorage.getItem('hideCourseNav') === 'false';
|
|
}
|
|
} else {
|
|
show = true;
|
|
}
|
|
|
|
hotkeys('b', function (event, handler) {
|
|
event.preventDefault();
|
|
switch (handler.key) {
|
|
case 'b':
|
|
show = !show;
|
|
break;
|
|
}
|
|
});
|
|
});
|
|
|
|
$: handleMobileChange($isMobile);
|
|
|
|
$: {
|
|
if (browser) {
|
|
localStorage.setItem('hideCourseNav', `${!show}`);
|
|
}
|
|
}
|
|
|
|
$: isLessonActive = $page.url.pathname.includes('/lessons');
|
|
|
|
$: {
|
|
navItems = [
|
|
{
|
|
label: 'Overview',
|
|
to: getNavItemRoute($course.id),
|
|
hideSortIcon: true
|
|
},
|
|
{
|
|
label: 'Lessons',
|
|
to: getLessonsRoute($course.id),
|
|
hideSortIcon: false,
|
|
isLecture: true
|
|
},
|
|
{
|
|
label: 'Attendance',
|
|
to: getNavItemRoute($course.id, 'attendance'),
|
|
hideSortIcon: true
|
|
},
|
|
{
|
|
label: 'Submissions',
|
|
to: getNavItemRoute($course.id, 'submissions'),
|
|
hideSortIcon: true,
|
|
show() {
|
|
return !isStudent;
|
|
}
|
|
},
|
|
{
|
|
label: 'Marks',
|
|
to: getNavItemRoute($course.id, 'marks'),
|
|
hideSortIcon: true
|
|
},
|
|
// {
|
|
// label: 'Scoreboard',
|
|
// to: getNavItemRoute($course.id, 'scoreboard'),
|
|
// hideSortIcon: true,
|
|
// },
|
|
{
|
|
label: 'People',
|
|
to: getNavItemRoute($course.id, 'people'),
|
|
hideSortIcon: true
|
|
},
|
|
{
|
|
label: 'Certificates',
|
|
to: getNavItemRoute($course.id, 'certificates'),
|
|
hideSortIcon: true
|
|
},
|
|
{
|
|
label: 'Landing Page',
|
|
to: getNavItemRoute($course.id, 'landingpage'),
|
|
hideSortIcon: true,
|
|
show() {
|
|
return !isStudent;
|
|
}
|
|
}
|
|
];
|
|
}
|
|
</script>
|
|
|
|
<Settings />
|
|
|
|
<div class="root z-10 {!show && 'hide'} {$isMobile ? 'fixed shadow-xl' : 'sticky'}">
|
|
{#if show}
|
|
<div class="relative h-full dark:bg-gray-700">
|
|
<!-- <PageNav title="Back to courses" paddingClass="pl-2" titleSize="text-md">
|
|
<slot:fragment slot="image">
|
|
<Avatar src={$course.logo} />
|
|
<IconButton
|
|
value="toggle"
|
|
onClick={() => goto(`${$currentOrgPath}/courses`)}
|
|
size="small"
|
|
contained={true}
|
|
>
|
|
<ArrowLeftIcon size={20} class="carbon-icon dark:text-white" />
|
|
</IconButton>
|
|
</slot:fragment>
|
|
<slot:fragment slot="widget">
|
|
<RoleBasedSecurity allowedRoles={[1, 2]}>
|
|
<IconButton onClick={() => ($settingsDialog.open = !$settingsDialog.open)}>
|
|
<SettingsIcon size={20} class="carbon-icon dark:text-white" />
|
|
</IconButton>
|
|
</RoleBasedSecurity>
|
|
</slot:fragment>
|
|
</PageNav> -->
|
|
<div class="h-full mt-2 overflow-y-auto">
|
|
{#each navItems as navItem}
|
|
{#if !navItem.show || (typeof navItem.show === 'function' && navItem.show())}
|
|
<NavExpandable
|
|
label={navItem.label}
|
|
handleClick={handleMainGroupClick(navItem.to)}
|
|
isGroupActive={(path || $page.url.pathname) === navItem.to}
|
|
isExpanded={isLessonActive}
|
|
total={navItem.isLecture ? ($lessons || []).length : 0}
|
|
>
|
|
{#if navItem.isLecture}
|
|
{#each $lessons as item, index}
|
|
<a
|
|
class="pl-7 w-[95%] text-[0.80rem] mb-1 text-black dark:text-white {isStudent &&
|
|
!item.is_unlocked
|
|
? 'cursor-not-allowed'
|
|
: ''}"
|
|
href={isStudent && !item.is_unlocked
|
|
? $page.url.pathname
|
|
: getLessonsRoute($course.id, item.id)}
|
|
on:click={() => {
|
|
if ($isMobile) {
|
|
setTimeout(() => (show = false), 500);
|
|
}
|
|
}}
|
|
aria-disabled={!item.is_unlocked}
|
|
>
|
|
<div
|
|
class="flex items-center py-3 px-4 rounded hover:bg-gray-200 dark:hover:bg-gray-800 w-full {(
|
|
path || $page.url.pathname
|
|
).includes(item.id) && activeClass}"
|
|
>
|
|
<TextChip
|
|
value={getLectureNo(index + 1)}
|
|
className="bg-blue-200 dark:text-black text-xs mr-2"
|
|
size="sm"
|
|
shape="rounded-full"
|
|
/>
|
|
<span>{item.title}</span>
|
|
<span class="grow" />
|
|
{#if !item.is_unlocked}
|
|
<span class="text-md ml-2" title="This lesson is locked.">
|
|
<LockedIcon class="carbon-icon dark:text-white" />
|
|
</span>
|
|
{:else if item.is_complete}
|
|
<span class="ml-2" title="You have completed this lesson">
|
|
<CheckmarkFilled class="carbon-icon dark:text-white" />
|
|
</span>
|
|
{/if}
|
|
</div>
|
|
</a>
|
|
{/each}
|
|
{/if}
|
|
</NavExpandable>
|
|
{/if}
|
|
{/each}
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
<div class="toggler rounded-full shadow-lg absolute bottom-0">
|
|
<IconButton
|
|
value="toggle"
|
|
onClick={() => (show = !show)}
|
|
size={$isMobile ? 'large' : 'small'}
|
|
color="text-black"
|
|
toolTipProps={$isMobile
|
|
? {}
|
|
: {
|
|
title: 'Toggle sidebar',
|
|
hotkeys: ['B'],
|
|
direction: 'right'
|
|
}}
|
|
>
|
|
{#if show}
|
|
<ChevronLeftIcon size={16} />
|
|
{:else}
|
|
<ChevronRightIcon size={16} />
|
|
{/if}
|
|
</IconButton>
|
|
</div>
|
|
</div>
|
|
|
|
<style lang="scss">
|
|
.root {
|
|
height: calc(100vh - 44px);
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-width: 360px;
|
|
max-width: 360px;
|
|
top: 0;
|
|
border-right: 1px solid var(--border-color);
|
|
background-color: rgb(250, 251, 252);
|
|
|
|
&.hide {
|
|
min-width: 15px;
|
|
max-width: 15px;
|
|
}
|
|
}
|
|
|
|
.footer {
|
|
border-top: 1px solid var(--border-color);
|
|
}
|
|
|
|
.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>
|