CLASSROOMIO-T-146:Made the course page responsive

CLASSROOMIO-T-146:Made updates to the code following the reviews

CLASSROOMIO-T-146:Made updates to the Z-Index

Merge branch 'main' into CLASSROOMIO-T-146

Merge branch 'main' into CLASSROOMIO-T-146

CLASSROOMIO-T-146:Made the course page responsive

CLASSROOMIO-T-146:working on the course page responsiveness

Merge branch 'main' into CLASSROOMIO-T-145

CLASSROOMIO-T-146:Making the course page responsive

CLASSROOMIO-T-145: All done and ready

CLASSROOMIO-T-145: All done and ready

CLASSROOMIO-T-145: Fixed the Z-index issue

Merge branch 'main' into CLASSROOMIO-T-145

CLASSROOMIO-T-145: Finished implementing the responsive design for the Main dashboard and LMS dashboard

Merge branch 'main' into CLASSROOMIO-T-145

CLASSROOMIO-T-144:Updating the dashboard responsiveness ooth for LMS and the Main dashboard

CLASSROOMIO-T-144:Updated the dashboard responsiveness ooth for LMS and the Main dashboard

Merge branch 'main' into CLASSROOMIO-T-145

CLASSROOMIO-T-145:Made the LMS dashboard responsive


Co-authored-by: Ifeanyi Nwosu <ifeanyi@digdippa.com>


Merge-request: CLASSROOMIO-MR-73
Merged-by: Best Admin <best@digdippa.com>
This commit is contained in:
emmanuel
2023-09-14 20:59:51 +00:00
committed by Space Cloud
parent be619ae6bd
commit f3f8a00809
24 changed files with 520 additions and 520 deletions
+5
View File
@@ -14,6 +14,11 @@ html {
#calendar .grid { #calendar .grid {
--sc-theme-calendar-colors-background-highlight: var(--main-primary-color); --sc-theme-calendar-colors-background-highlight: var(--main-primary-color);
} }
html .dark {
--scrollbarBG: #1f2937;
}
* { * {
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: var(--thumbBG) var(--scrollbarBG); scrollbar-color: var(--thumbBG) var(--scrollbarBG);
+40 -3
View File
@@ -6,12 +6,15 @@
import SendAlt from 'carbon-icons-svelte/lib/SendAlt.svelte'; import SendAlt from 'carbon-icons-svelte/lib/SendAlt.svelte';
import ChartPie from 'carbon-icons-svelte/lib/ChartPie.svelte'; import ChartPie from 'carbon-icons-svelte/lib/ChartPie.svelte';
import IconButton from '$lib/components/IconButton/index.svelte'; import IconButton from '$lib/components/IconButton/index.svelte';
import Settings from 'carbon-icons-svelte/lib/Settings.svelte';
import { apps } from './store';
import QandA from './components/QandA/index.svelte'; import QandA from './components/QandA/index.svelte';
import LiveChat from './components/LiveChat/index.svelte'; import LiveChat from './components/LiveChat/index.svelte';
import Notes from './components/Notes/index.svelte'; import Notes from './components/Notes/index.svelte';
import Poll from './components/Poll/index.svelte'; import Poll from './components/Poll/index.svelte';
import APPS_CONSTANTS from './constants'; import APPS_CONSTANTS from './constants';
import { OverflowMenu, OverflowMenuItem } from 'carbon-components-svelte';
let selectedApp; let selectedApp;
@@ -48,8 +51,21 @@
}); });
</script> </script>
<div class="root"> <div class={`root ${$apps.open ? 'open dark:bg-slate-800' : 'close dark:bg-slate-800'}`}>
<div class="apps"> <div class={`apps`}>
<div class="lg:hidden">
<IconButton
buttonClassName="lg:hidden"
toolTipProps={{ title: 'Settings', hotkeys: ['A', '0'] }}
onClick={() => {
handleAppClick;
$apps.dropdown = !$apps.dropdown;
}}
>
<Settings size={24} class="carbon-icon dark:text-white lg:hidden" />
</IconButton>
</div>
<IconButton <IconButton
toolTipProps={{ title: 'Live Chat', hotkeys: ['A', '1'] }} toolTipProps={{ title: 'Live Chat', hotkeys: ['A', '1'] }}
value={APPS_CONSTANTS.APPS.LIVE_CHAT} value={APPS_CONSTANTS.APPS.LIVE_CHAT}
@@ -104,7 +120,7 @@
<style lang="scss"> <style lang="scss">
.root { .root {
height: 93vh; height: calc(100vh - 48px);
position: sticky; position: sticky;
top: 0; top: 0;
border-left: 1px solid var(--border-color); border-left: 1px solid var(--border-color);
@@ -129,4 +145,25 @@
overflow: auto; overflow: auto;
} }
} }
@media screen and (max-width: 1024px) {
.root {
position: absolute;
height: calc(100vh - 109px);
top: 109px;
right: 0;
z-index: 999;
}
.open {
position: absolute;
transform: translateX(0);
transition: all 0.2s ease-in-out;
}
.close {
position: absolute;
transform: translateX(100%);
display: none;
transition: all 0.2s ease-in-out;
}
}
</style> </style>
+6
View File
@@ -0,0 +1,6 @@
import { writable } from 'svelte/store';
export const apps = writable({
open: false,
dropdown: false
});
@@ -45,8 +45,8 @@
</svelte:head> </svelte:head>
<main class="md:-ml-4 md:-mr-4 px-2"> <main class="md:-ml-4 md:-mr-4 px-2">
<div class="flex-1 flex flex-col md:flex-row justify-between gap-3 w-full mb-3 h-4/5"> <div class="flex-1 flex flex-col lg:flex-row justify-between gap-3 w-full mb-3 h-4/5">
<section class="w-full md:w-2/5 h-full"> <section class="w-full lg:w-2/5 h-full">
<strong class="my-2 text-base font-semibold text-black dark:text-gray-100" <strong class="my-2 text-base font-semibold text-black dark:text-gray-100"
>Certificate settings</strong >Certificate settings</strong
> >
@@ -99,7 +99,7 @@
</div> </div>
</section> </section>
<section <section
class="bg-gray-100 dark:bg-gray-700 flex justify-center items-center rounded-md w-full md:w-3/5" class="bg-gray-100 dark:bg-gray-700 flex justify-center items-center rounded-md w-full lg:w-3/5"
> >
<div class="certificate-container flex justify-center items-center h-5/6"> <div class="certificate-container flex justify-center items-center h-5/6">
{#if $course.certificate_theme === 'professional'} {#if $course.certificate_theme === 'professional'}
@@ -55,7 +55,7 @@
<Modal <Modal
onClose={() => (openModal = false)} onClose={() => (openModal = false)}
bind:open={openModal} bind:open={openModal}
width="w-[60%]" width="w-[80%] md:w-[60%]"
containerClass="overflow-hidden" containerClass="overflow-hidden"
modalHeading="Add New Lesson" modalHeading="Add New Lesson"
> >
@@ -165,8 +165,8 @@
<p class="dark:text-white mt-4 text-sm">Created Jul 3, 2021</p> <p class="dark:text-white mt-4 text-sm">Created Jul 3, 2021</p>
</a> </a>
{:else} {:else}
<Box className="mt-3"> <Box className="mt-3 text-center">
<div class="flex justify-between flex-col items-center w-96"> <div class="flex justify-between flex-col items-center w-[80%] md:w-96">
<img src="/images/empty-exercise-icon.svg" alt="Exercise" class="my-2.5 mx-auto" /> <img src="/images/empty-exercise-icon.svg" alt="Exercise" class="my-2.5 mx-auto" />
<h2 class="text-xl my-1.5 font-normal">No exercises added for this lesson</h2> <h2 class="text-xl my-1.5 font-normal">No exercises added for this lesson</h2>
<p class="text-sm text-center text-slate-500"> <p class="text-sm text-center text-slate-500">
@@ -11,13 +11,15 @@
const onChange = (tab) => () => (currentTab = tab); const onChange = (tab) => () => (currentTab = tab);
</script> </script>
<section class="w-full h-full flex flex-row items-start gap-3"> <section class="w-full h-full flex flex-col md:flex-row items-start gap-3">
<div class="flex-1 flex-col"> <div class="flex flex-row md:flex-col gap-2 items-center">
<p class="text-sm font-normal text-start text-[#4F4B4B] dark:text-[#b0a9a9] mb-3">Add By</p> <p class="text-sm font-normal text-start text-[#4F4B4B] dark:text-[#b0a9a9] mb-3 w-full">
Add By
</p>
{#each tabs as item (item.value)} {#each tabs as item (item.value)}
<button <button
on:click={onChange(item.value)} on:click={onChange(item.value)}
class={`w-full px-4 py-3 my-5 border ${ class={`w-full px-4 py-3 my-1 border ${
currentTab === item.value currentTab === item.value
? 'border border-[#0233BD] bg-[#F5F8FE] dark:text-black' ? 'border border-[#0233BD] bg-[#F5F8FE] dark:text-black'
: 'border border-gray-200' : 'border border-gray-200'
@@ -197,13 +197,13 @@
<Modal <Modal
{onClose} {onClose}
bind:open={$uploadCourseVideoStore.isModalOpen} bind:open={$uploadCourseVideoStore.isModalOpen}
width="w-4/5 h-[566px]" width="w-4/5 w-[90%] h-[80%] md:h-[566px]"
modalHeading="Add a Video" modalHeading="Add a Video"
> >
<VideoUploader {lessonId} /> <VideoUploader {lessonId} />
</Modal> </Modal>
<h1 class="text-4xl mt-0"> <h1 class="text-4xl mt-0 capitalize">
{lessonTitle} {lessonTitle}
</h1> </h1>
@@ -386,7 +386,7 @@
</article> </article>
{/if} {/if}
{:else} {:else}
<Box> <Box className="text-center">
<img src="/no-video.svg" alt="Video not found" /> <img src="/no-video.svg" alt="Video not found" />
<h3 class="text-xl font-normal dark:text-white py-2"> <h3 class="text-xl font-normal dark:text-white py-2">
No note, video or slide added for this lesson yet No note, video or slide added for this lesson yet
@@ -24,6 +24,7 @@
import { updateCourse } from '$lib/utils/services/courses'; import { updateCourse } from '$lib/utils/services/courses';
import { NavClasses } from '$lib/utils/constants/reusableClass'; import { NavClasses } from '$lib/utils/constants/reusableClass';
import { isMobile } from '$lib/utils/store/useMobile'; import { isMobile } from '$lib/utils/store/useMobile';
import { menu } from '$lib/components/Org/store';
// export let lessonId; // export let lessonId;
export let path; export let path;
@@ -32,12 +33,14 @@
let show = null; let show = null;
let isLessonActive = false; let isLessonActive = false;
const toggleSidebar = () => {
$menu.hidden = !$menu.hidden;
};
function handleMainGroupClick(href) { function handleMainGroupClick(href) {
return () => { return () => {
if ($isMobile) {
setTimeout(() => (show = false), 500);
}
goto(href); goto(href);
toggleSidebar();
}; };
} }
@@ -146,145 +149,66 @@
<Settings /> <Settings />
<div class="root z-10 {!show && 'hide'} {$isMobile ? 'fixed shadow-xl' : 'sticky'}"> <aside
{#if show} class={`${
<div class="relative h-full dark:bg-gray-800"> $menu.hidden
<!-- <PageNav title="Back to courses" paddingClass="pl-2" titleSize="text-md"> ? '-translate-x-[100%] absolute md:translate-x-0 md:relative z-[40]'
<slot:fragment slot="image"> : 'translate-x-0 absolute md:relative z-[40]'
<Avatar src={$course.logo} /> } transition w-[250px] min-w-[250px] bg-gray-100 dark:bg-gray-800 h-[calc(100vh-48px)] border border-l-0 border-t-0 border-b-0 border-r-1`}
<IconButton >
value="toggle" <div class="h-full flex flex-col">
onClick={() => goto(`${$currentOrgPath}/courses`)} <ul class="my-5">
size="small" {#each navItems as navItem}
contained={true} {#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}
> >
<ArrowLeftIcon size={20} class="carbon-icon dark:text-white" /> {#if navItem.isLecture}
</IconButton> {#each $lessons as item, index}
</slot:fragment> <a
<slot:fragment slot="widget"> class="pl-7 w-[95%] text-[0.80rem] mb-1 text-black dark:text-white {isStudent &&
<RoleBasedSecurity allowedRoles={[1, 2]}> !item.is_unlocked
<IconButton onClick={() => ($settingsDialog.open = !$settingsDialog.open)}> ? 'cursor-not-allowed'
<SettingsIcon size={20} class="carbon-icon dark:text-white" /> : ''}"
</IconButton> href={isStudent && !item.is_unlocked
</RoleBasedSecurity> ? $page.url.pathname
</slot:fragment> : getLessonsRoute($course.id, item.id)}
</PageNav> --> on:click={toggleSidebar}
<div class="h-full py-3 overflow-y-auto"> aria-disabled={!item.is_unlocked}
{#each navItems as navItem} >
{#if !navItem.show || (typeof navItem.show === 'function' && navItem.show())} <div
<NavExpandable class="flex items-center py-3 px-4 {NavClasses.item} {(
label={navItem.label} path || $page.url.pathname
handleClick={handleMainGroupClick(navItem.to)} ).includes(item.id) && NavClasses.active}"
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 <TextChip
class="flex items-center py-3 px-4 {NavClasses.item} {( value={getLectureNo(index + 1)}
path || $page.url.pathname className="bg-primary-200 text-primary-600 text-xs mr-2"
).includes(item.id) && NavClasses.active}" size="sm"
> shape="rounded-full"
<TextChip />
value={getLectureNo(index + 1)} <span>{item.title}</span>
className="bg-primary-200 text-primary-600 text-xs mr-2" <span class="grow" />
size="sm" {#if !item.is_unlocked}
shape="rounded-full" <span class="text-md ml-2" title="This lesson is locked.">
/> <LockedIcon class="carbon-icon dark:text-white" />
<span>{item.title}</span> </span>
<span class="grow" /> {:else if item.is_complete}
{#if !item.is_unlocked} <span class="ml-2" title="You have completed this lesson">
<span class="text-md ml-2" title="This lesson is locked."> <CheckmarkFilled class="carbon-icon dark:text-white" />
<LockedIcon class="carbon-icon dark:text-white" /> </span>
</span> {/if}
{:else if item.is_complete} </div>
<span class="ml-2" title="You have completed this lesson"> </a>
<CheckmarkFilled class="carbon-icon dark:text-white" /> {/each}
</span> {/if}
{/if} </NavExpandable>
</div> {/if}
</a> {/each}
{/each} </ul>
{/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>
</div> </aside>
<style lang="scss">
.root {
height: calc(100vh - 48px);
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>
@@ -145,7 +145,7 @@
<Modal <Modal
onClose={resetForm} onClose={resetForm}
bind:open={$invitationModal.open} bind:open={$invitationModal.open}
width="w-2/5" width="w-4/5 md:w-2/5"
maxWidth="max-w-lg" maxWidth="max-w-lg"
modalHeading="Invite people" modalHeading="Invite people"
> >
@@ -16,9 +16,7 @@
export let isFetching = false; export let isFetching = false;
$: { $: {
const user = $group.people.find( const user = $group.people.find((person) => person.profile_id === $profile.id);
(person) => person.profile_id === $profile.id
);
if (user) { if (user) {
isStudent = user.role_id === 3; isStudent = user.role_id === 3;
@@ -58,6 +56,6 @@
} }
.rightBar.isMobile { .rightBar.isMobile {
margin-left: 10px; /* margin-left: 10px; */
} }
</style> </style>
@@ -7,36 +7,12 @@
export let show = true; export let show = true;
</script> </script>
<section <section class="root z-10">
class="root z-10 {!show && 'hide'} {$isMobile ? 'fixed shadow-xl' : 'sticky'}"
>
{#if show} {#if show}
<div class="relative h-full bg-white dark:bg-gray-800"> <div class="relative h-full bg-white dark:bg-gray-800">
<slot /> <slot />
</div> </div>
{/if} {/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 editor',
hotkeys: ['B'],
direction: 'right',
}}
>
{#if show}
<ChevronLeftIcon size={16} />
{:else}
<ChevronRightIcon size={16} />
{/if}
</IconButton>
</div>
</section> </section>
<style lang="scss"> <style lang="scss">
@@ -50,11 +26,6 @@
left: 0; left: 0;
border-right: 1px solid var(--border-color); border-right: 1px solid var(--border-color);
background-color: rgb(250, 251, 252); background-color: rgb(250, 251, 252);
&.hide {
min-width: 15px;
max-width: 15px;
}
} }
.toggler { .toggler {
@@ -67,10 +38,5 @@
} }
@media (max-width: 760px) { @media (max-width: 760px) {
.root {
width: 98%;
min-width: unset;
max-width: unset;
}
} }
</style> </style>
@@ -18,13 +18,16 @@
import { VARIANTS } from '$lib/components/PrimaryButton/constants'; import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import { updateCourse } from '$lib/utils/services/courses'; import { updateCourse } from '$lib/utils/services/courses';
import generateSlug from '$lib/utils/functions/generateSlug'; import generateSlug from '$lib/utils/functions/generateSlug';
import ChevronLeftIcon from 'carbon-icons-svelte/lib/ChevronLeft.svelte';
import { isMobile } from '$lib/utils/store/useMobile';
export let course; export let course;
export let courseId; export let courseId;
let borderBottomGrey = 'border-r-0 border-b border-l-0 border-gray-300'; let borderBottomGrey = 'border-r-0 border-b border-l-0 border-gray-300';
let loading = false; let loading = false;
let show = false;
const sections = [ const sections = [
{ {
key: 1, key: 1,
@@ -115,69 +118,112 @@
} }
</script> </script>
<Container show={true}> <aside
<!-- Publish Header Section --> class={`${
{#if !selectedSection} show ? '-translate-x-[100%] fixed z-[9999]' : 'translate-x-0 fixed z-[9999]'
<div class="flex justify-between items-center px-2 w-full"> } left-0 transition w-[280px] min-w-[280px] bg-gray-100 dark:bg-gray-800 h-full border border-l-0 border-t-0 border-b-0 border-r-1`}
<CloseButton onClick={handleClose} /> >
<div class="flex items-center"> <div class="toggler rounded-full shadow-lg absolute">
<PrimaryButton <IconButton
label="Save" value="toggle"
type="button" onClick={() => (show = !show)}
className="mr-1" size={$isMobile ? 'large' : 'small'}
variant={VARIANTS.OUTLINED} color="text-black"
onClick={handleSave} toolTipProps={$isMobile
isLoading={loading} ? {}
/> : {
<PrimaryButton label="Publish" type="button" onClick={handlePublish} isDisabled={loading} /> title: 'Toggle editor',
<IconButton onClick={handlePreview} disabled={loading || !course.slug}> direction: 'right'
<ArrowUpRightIcon size={24} class="carbon-icon dark:text-white" title="Preview" /> }}
</IconButton> >
</div> {#if show}
</div> <ChevronRightIcon size={16} />
<div class="flex justify-between items-center px-2 w-full mb-2"> {:else}
<h3 class="dark:text-white">Page Builder</h3> <ChevronLeftIcon size={16} />
</div>
{#each sections as section}
<button
class="w-full flex items-center justify-between px-2 py-3 border border-b-0 border-gray-300"
on:click={handleSectionSelect(section.key)}
>
<p class="dark:text-white mr-2">{section.title} section</p>
<ChevronRightIcon size={24} class="carbon-class" />
</button>
{/each}
{:else}
<!-- Title -->
<div class="flex items-center {borderBottomGrey} w-full">
<IconButton onClick={handleClose}>
<ArrowLeftIcon size={24} class="carbon-icon dark:text-white" title="Go back" />
</IconButton>
<h3 class="dark:text-white">{selectedSection.title}</h3>
</div>
<div class="title-content p-2 overflow-y-auto">
{#if selectedSection.key === 1}
<HeaderForm bind:course />
{:else if selectedSection.key === 2}
<RequirementForm bind:course />
{:else if selectedSection.key === 3}
<DescriptionForm bind:course />
{:else if selectedSection.key === 4}
<GoalsForm bind:course />
{:else if selectedSection.key === 5}
<ReviewsForm bind:course />
{:else if selectedSection.key === 6}
<InstructorForm bind:course />
{:else if selectedSection.key === 7}
<PricingForm bind:course />
{/if} {/if}
</div> </IconButton>
{/if} </div>
</Container> <div class="h-full flex flex-col">
{#if !selectedSection}
<div class="flex justify-between items-center px-2 w-full">
<CloseButton onClick={handleClose} />
<div class="flex items-center">
<PrimaryButton
label="Save"
type="button"
className="mr-1"
variant={VARIANTS.OUTLINED}
onClick={handleSave}
isLoading={loading}
/>
<PrimaryButton
label="Publish"
type="button"
onClick={handlePublish}
isDisabled={loading}
/>
<IconButton onClick={handlePreview} disabled={loading || !course.slug}>
<ArrowUpRightIcon size={24} class="carbon-icon dark:text-white" title="Preview" />
</IconButton>
</div>
</div>
<div class="flex justify-between items-center px-2 w-full mb-2">
<h3 class="dark:text-white">Page Builder</h3>
</div>
{#each sections as section}
<button
class="w-full flex items-center justify-between px-2 py-3 border border-b-0 border-gray-300"
on:click={handleSectionSelect(section.key)}
>
<p class="dark:text-white mr-2">{section.title} section</p>
<ChevronRightIcon size={24} class="carbon-class" />
</button>
{/each}
{:else}
<!-- Title -->
<div class="flex items-center {borderBottomGrey} w-full">
<IconButton onClick={handleClose}>
<ArrowLeftIcon size={24} class="carbon-icon dark:text-white" title="Go back" />
</IconButton>
<h3 class="dark:text-white">{selectedSection.title}</h3>
</div>
<div class="title-content p-2 overflow-y-auto">
{#if selectedSection.key === 1}
<HeaderForm bind:course />
{:else if selectedSection.key === 2}
<RequirementForm bind:course />
{:else if selectedSection.key === 3}
<DescriptionForm bind:course />
{:else if selectedSection.key === 4}
<GoalsForm bind:course />
{:else if selectedSection.key === 5}
<ReviewsForm bind:course />
{:else if selectedSection.key === 6}
<InstructorForm bind:course />
{:else if selectedSection.key === 7}
<PricingForm bind:course />
{/if}
</div>
{/if}
</div>
</aside>
<style> <style>
.title-content { .title-content {
height: 90%; height: 90%;
} }
.toggler {
right: -15px;
z-index: 10;
border: 1px solid var(--border-color);
top: 50px;
height: fit-content;
background: var(--border-color);
}
@media screen and (max-width: 767px) {
.toggler {
right: -25px;
}
}
</style> </style>
@@ -38,7 +38,7 @@
</script> </script>
<!-- Pricing Details --> <!-- Pricing Details -->
<aside class="{className} price-container md:sticky md:top-0 md:shadow-2xl md:rounded-lg m-h-fit"> <aside class="{className} price-container lg:sticky lg:top-0 lg:shadow-2xl lg:rounded-lg m-h-fit">
<div class="p-10"> <div class="p-10">
<!-- Pricing --> <!-- Pricing -->
<div class="mb-6"> <div class="mb-6">
@@ -120,9 +120,9 @@
height: fit-content; height: fit-content;
} }
@media (max-width: 768px) { @media screen and (min-width: 768px) and (max-width: 1024px) {
.price-container { .price-container {
width: 100%; width: 405px;
min-width: unset; min-width: unset;
} }
} }
@@ -164,12 +164,14 @@
{/if} {/if}
</div> </div>
</header> </header>
<PricingSection className="md:hidden" {courseData} /> <!-- <PricingSection className="md:hidden" {courseData} /> -->
<!-- Body --> <!-- Body -->
<div class="bg-white dark:bg-gray-800 w-full"> <div class="bg-white dark:bg-gray-800 w-full">
<div class="py-8 lg:w-10/12 w-full m-2 lg:m-auto flex justify-between"> <div
class="py-8 lg:w-11/12 w-full m-2 lg:m-auto flex flex-col-reverse lg:flex-row items-center lg:items-start justify-between"
>
<!-- Course Details --> <!-- Course Details -->
<div class="course-content w-full p-3 md:w-9/12 md:mr-14"> <div class="course-content w-full p-3 lg:w-10/12 lg:mr-14">
<!-- Navigation --> <!-- Navigation -->
<nav class="flex items-center border-b border-gray-300 pb-3"> <nav class="flex items-center border-b border-gray-300 pb-3">
{#each NAV_ITEMS as navItem} {#each NAV_ITEMS as navItem}
@@ -416,7 +418,7 @@
</div> </div>
<!-- Pricing Details --> <!-- Pricing Details -->
<PricingSection className="hidden md:block" {courseData} /> <PricingSection {courseData} />
</div> </div>
</div> </div>
</div> </div>
@@ -464,7 +466,7 @@
} }
.course-content { .course-content {
max-width: 608px; max-width: 800px;
} }
nav { nav {
+2 -2
View File
@@ -6,7 +6,7 @@
</script> </script>
<div class="w-full flex flex-col"> <div class="w-full flex flex-col">
<div class="flex items-center border-b-2 w-full"> <div class="flex items-center border-b-2 w-full overflow-x-auto">
{#each tabs as tab} {#each tabs as tab}
{#if !tab.icon && !tab.badgeValue} {#if !tab.icon && !tab.badgeValue}
<button <button
@@ -32,7 +32,7 @@
: 'dark:bg-gray-500 dark:text-white'} dark:bg-transparent font-semibold focus:outline-none w-24 text-left py-3 mr-10" : 'dark:bg-gray-500 dark:text-white'} dark:bg-transparent font-semibold focus:outline-none w-24 text-left py-3 mr-10"
on:click={onChange(tab.value)} on:click={onChange(tab.value)}
> >
<div class="grid grid-cols-4 gap-3 items-center"> <div class="grid grid-cols-5 md:grid-cols-4 gap-5 md:gap-3 items-center">
{#if tab.icon} {#if tab.icon}
<svelte:component this={tab.icon} /> <svelte:component this={tab.icon} />
{/if} {/if}
+2 -2
View File
@@ -315,14 +315,14 @@
{#if !isQuizPage($page.url.pathname)} {#if !isQuizPage($page.url.pathname)}
<OrgSideBar /> <OrgSideBar />
{/if} {/if}
<div class="org-slot w-full bg-white dark:bg-gray-800"> <div class="org-slot bg-white dark:bg-gray-800 w-full">
<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 w-full bg-white dark:bg-gray-800"> <div class="org-slot bg-white dark:bg-gray-800 w-full">
<slot /> <slot />
</div> </div>
</div> </div>
+70 -67
View File
@@ -138,77 +138,80 @@
<CourseContainer bind:isStudent> <CourseContainer bind:isStudent>
<PageNav title="Attendance" /> <PageNav title="Attendance" />
<PageBody width="w-full max-w-6xl md:w-11/12">
<section class="mx-9 my-5"> <section class="flex items-center mx-2 lg:mx-9 my-5">
<div class="flex flex-row items-center justify-between"> <div
<div class="flex"> class="flex flex-col lg:flex-row items-start gap-2 lg:items-center justify-between w-full"
<p class="flex items-center mr-5"> >
<Checkbox checked disabled /> Present <div class="flex">
</p> <p class="flex items-center mr-5">
<p class="flex items-center"> <Checkbox checked disabled /> Present
<Checkbox disabled /> Absent </p>
</p> <p class="flex items-center">
<Checkbox disabled /> Absent
</p>
</div>
<div>
<Search
class="dark:text-slate-950"
placeholder="Search students"
bind:value={searchValue}
/>
</div>
</div> </div>
<div> </section>
<Search
class="dark:text-slate-950"
placeholder="Search students"
bind:value={searchValue}
/>
</div>
</div>
</section>
<section class="my-5 mx-9"> <section class="my-5 mx-2 lg:mx-9">
<StructuredList class="m-0"> <StructuredList class="m-0 relative">
<!-- Moved the lesson headers outside the students loop --> <!-- Moved the lesson headers outside the students loop -->
<StructuredListHead class="bg-primary-100"> <StructuredListHead class="bg-primary-100">
<StructuredListRow head class="mx-7"> <StructuredListRow head class="mx-7">
<StructuredListCell head class="text-primary-600 py-3">Student</StructuredListCell> <StructuredListCell head class="text-primary-600 py-3">Student</StructuredListCell>
{#each $lessons as lesson, index} {#each $lessons as lesson, index}
<StructuredListCell head class="text-primary-600 py-3" <StructuredListCell head class="text-primary-600 py-3"
>Lesson 0{getLectureNo(index + 1)}</StructuredListCell >Lesson 0{getLectureNo(index + 1)}</StructuredListCell
> >
{/each}
</StructuredListRow>
</StructuredListHead>
{#each searchStudents(searchValue) as student}
<StructuredListBody>
<StructuredListRow>
<StructuredListCell>
<div class="w-1/4 flex items-center">
<p class="dark:text-white font-semibold">
{student.profile.fullname}
</p>
</div>
</StructuredListCell>
{#each $lessons as lesson}
<StructuredListCell class="">
<Checkbox
class={isStudent && 'cursor-not-allowed'}
disabled={isStudent}
checked={$attendance[student.id]
? $attendance[student.id][lesson.id]
? $attendance[student.id][lesson.id].is_present
: false
: false}
on:change={(e) => handleAttendanceChange(e, student, lesson)}
/>
</StructuredListCell>
{/each} {/each}
</StructuredListRow> </StructuredListRow>
</StructuredListBody> </StructuredListHead>
{/each}
</StructuredList> {#each searchStudents(searchValue) as student}
{#if students.length === 0} <StructuredListBody>
<div> <StructuredListRow>
<Box> <StructuredListCell>
<div class="w-1/4 flex items-center">
<p class="dark:text-white font-semibold">
{student.profile.fullname}
</p>
</div>
</StructuredListCell>
{#each $lessons as lesson}
<StructuredListCell class="">
<Checkbox
class={isStudent && 'cursor-not-allowed'}
disabled={isStudent}
checked={$attendance[student.id]
? $attendance[student.id][lesson.id]
? $attendance[student.id][lesson.id].is_present
: false
: false}
on:change={(e) => handleAttendanceChange(e, student, lesson)}
/>
</StructuredListCell>
{/each}
</StructuredListRow>
</StructuredListBody>
{/each}
</StructuredList>
{#if students.length === 0}
<Box className="h-[300px] w-full">
<AudioConsoleIcon size={32} class="carbon-icon w-80" /> <AudioConsoleIcon size={32} class="carbon-icon w-80" />
<h3 class="text-3xl text-gray-500 dark:text-white">No Student Added</h3> <h3 class="text-3xl text-gray-500 dark:text-white text-center">No Student Added</h3>
</Box> </Box>
</div> {/if}
{/if} {#if students.length !== 0}
<Pagination totalItems={10} pageSizes={[10, 15, 20]} /> <Pagination totalItems={10} pageSizes={[10, 15, 20]} />
</section> {/if}
</section>
</PageBody>
</CourseContainer> </CourseContainer>
@@ -30,12 +30,12 @@
</script> </script>
<div <div
class="root absolute inset-0 flex justify-center items-center z-50 bg-white" class="absolute inset-0 z-50 bg-white"
in:fly={{ y: 500, duration: 500 }} in:fly={{ y: 500, duration: 500 }}
out:fly={{ y: 500, duration: 500 }} out:fly={{ y: 500, duration: 500 }}
> >
<Editor {courseId} bind:course={courseData} /> <Editor {courseId} bind:course={courseData} />
<div class="rightBar" class:isMobile={$isMobile}> <div class="rightBar">
<CourseLandingPage bind:courseData /> <CourseLandingPage bind:courseData />
</div> </div>
</div> </div>
@@ -43,13 +43,8 @@
<style> <style>
.rightBar { .rightBar {
flex-grow: 1; flex-grow: 1;
width: calc(100% - 360px); width: 100%;
overflow: auto;
height: 100%; height: 100%;
overflow: auto; overflow-y: auto;
}
.rightBar.isMobile {
margin-left: 10px;
} }
</style> </style>
+2 -2
View File
@@ -321,12 +321,12 @@
</div> </div>
{:else} {:else}
<Box> <Box>
<div class="flex justify-between flex-col items-center w-96"> <div class="flex justify-between flex-col items-center w-[90%] md:w-96">
<img src="/images/empty-lesson-icon.svg" alt="Lesson" class="my-2.5 mx-auto" /> <img src="/images/empty-lesson-icon.svg" alt="Lesson" class="my-2.5 mx-auto" />
<h2 class="text-xl my-1.5 font-normal">No lessons yet</h2> <h2 class="text-xl my-1.5 font-normal">No lessons yet</h2>
<p class="text-sm text-center text-slate-500"> <p class="text-sm text-center text-slate-500">
Share your knowledge with the world by creating engaging lessons. Start by clicking on Share your knowledge with the world by creating engaging lessons. Start by clicking on
the New Lesson button. the Add button.
</p> </p>
</div> </div>
</Box> </Box>
@@ -4,17 +4,19 @@
import { fetchCourse, fetchLesson } from '$lib/utils/services/courses'; import { fetchCourse, fetchLesson } from '$lib/utils/services/courses';
import CheckmarkOutlineIcon from 'carbon-icons-svelte/lib/CheckmarkOutline.svelte'; import CheckmarkOutlineIcon from 'carbon-icons-svelte/lib/CheckmarkOutline.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants.js'; import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import { Loading } from 'carbon-components-svelte'; import { Loading } from 'carbon-components-svelte';
import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte'; import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
import PageNav from '$lib/components/PageNav/index.svelte'; import PageNav from '$lib/components/PageNav/index.svelte';
import PageBody from '$lib/components/PageBody/index.svelte'; import PageBody from '$lib/components/PageBody/index.svelte';
import Materials from '$lib/components/Course/components/Lesson/Materials/index.svelte'; import Materials from '$lib/components/Course/components/Lesson/Materials/index.svelte';
import Exercises from '$lib/components/Course/components/Lesson/Exercises/index.svelte'; import Exercises from '$lib/components/Course/components/Lesson/Exercises/index.svelte';
import MODES from '$lib/utils/constants/mode.js'; import MODES from '$lib/utils/constants/mode';
import { setCourse, course } from '$lib/components/Course/store'; import { setCourse, course } from '$lib/components/Course/store';
import Download from 'carbon-icons-svelte/lib/Download.svelte'; import Download from 'carbon-icons-svelte/lib/Download.svelte';
import OverflowMenuVertical from 'carbon-icons-svelte/lib/OverflowMenuVertical.svelte';
import { apps } from '$lib/components/Apps/store';
import IconButton from '$lib/components/IconButton/index.svelte';
import { import {
lesson, lesson,
lessons, lessons,
@@ -144,6 +146,10 @@
})); }));
} }
const toggleApps = () => {
$apps.open = !$apps.open;
};
function toggleMode() { function toggleMode() {
prevMode = mode; prevMode = mode;
mode = mode === MODES.edit ? MODES.view : MODES.edit; mode = mode === MODES.edit ? MODES.view : MODES.edit;
@@ -176,9 +182,20 @@
<svelte:fragment slot="widget"> <svelte:fragment slot="widget">
<RoleBasedSecurity allowedRoles={[1, 2]}> <RoleBasedSecurity allowedRoles={[1, 2]}>
{#if data.isMaterialsTabActive} {#if data.isMaterialsTabActive}
<div class="flex items-center"> <div class="lg:hidden">
<IconButton onClick={toggleApps} buttonClassName="">
<OverflowMenuVertical size={24} />
</IconButton>
</div>
<div
class={`flex-row ${
$apps.dropdown && $apps.open
? 'absolute lg:relative top-[85px] lg:top-0 right-14 lg:right-0 z-40 dark:bg-gray-800 p-3 lg:p-0'
: 'hidden'
} lg:flex items-center`}
>
<PrimaryButton <PrimaryButton
className="mr-2" className="mb-2 lg:mb-0 mr-2"
variant={VARIANTS.OUTLINED} variant={VARIANTS.OUTLINED}
onClick={downloadLesson} onClick={downloadLesson}
{isLoading} {isLoading}
@@ -207,7 +224,7 @@
<PageBody> <PageBody>
<Materials lessonId={data.lessonId} {mode} {prevMode} {toggleMode} bind:isSaving /> <Materials lessonId={data.lessonId} {mode} {prevMode} {toggleMode} bind:isSaving />
<div class="w-full flex flex-row-reverse"> <div class="w-full flex flex-row-reverse mt-10">
<PrimaryButton <PrimaryButton
onClick={markLessonComplete} onClick={markLessonComplete}
isLoading={isMarkingComplete} isLoading={isMarkingComplete}
+15 -33
View File
@@ -8,10 +8,7 @@
import { ROLE } from '$lib/utils/constants/roles'; import { ROLE } from '$lib/utils/constants/roles';
import { setCourse, course, group } from '$lib/components/Course/store'; import { setCourse, course, group } from '$lib/components/Course/store';
import { lessons } from '$lib/components/Course/components/Lesson/store/lessons'; import { lessons } from '$lib/components/Course/components/Lesson/store/lessons';
import { import { fetchCourse, fetchExercisesByMarks } from '$lib/utils/services/courses';
fetchCourse,
fetchExercisesByMarks,
} from '$lib/utils/services/courses';
import { getLectureNo } from '$lib/components/Course/function'; import { getLectureNo } from '$lib/components/Course/function';
import { fetchMarks } from '$lib/utils/services/marks'; import { fetchMarks } from '$lib/utils/services/marks';
import { profile } from '$lib/utils/store/user'; import { profile } from '$lib/utils/store/user';
@@ -19,10 +16,8 @@
export let data; export let data;
const { courseId } = data; const { courseId } = data;
let borderBottomGrey = let borderBottomGrey = 'border-r-0 border-t-0 border-b border-l-0 border-gray-300';
'border-r-0 border-t-0 border-b border-l-0 border-gray-300'; let borderleftGrey = 'border-r-0 border-t-0 border-b-0 border-l border-gray-300';
let borderleftGrey =
'border-r-0 border-t-0 border-b-0 border-l border-gray-300';
let students = []; let students = [];
let isStudent = false; let isStudent = false;
@@ -52,11 +47,11 @@
if (studentMarksByExerciseId[groupmember_id]) { if (studentMarksByExerciseId[groupmember_id]) {
studentMarksByExerciseId[groupmember_id] = { studentMarksByExerciseId[groupmember_id] = {
...studentMarksByExerciseId[groupmember_id], ...studentMarksByExerciseId[groupmember_id],
[exercise_id]: total_points_gotten, [exercise_id]: total_points_gotten
}; };
} else { } else {
studentMarksByExerciseId[groupmember_id] = { studentMarksByExerciseId[groupmember_id] = {
[exercise_id]: total_points_gotten, [exercise_id]: total_points_gotten
}; };
} }
}); });
@@ -70,11 +65,11 @@
if (lessonMapping[lesson_id]) { if (lessonMapping[lesson_id]) {
lessonMapping[lesson_id] = { lessonMapping[lesson_id] = {
...lessonMapping[lesson_id], ...lessonMapping[lesson_id],
[exercise_id]: { title: exercise_title, points }, [exercise_id]: { title: exercise_title, points }
}; };
} else { } else {
lessonMapping[lesson_id] = { lessonMapping[lesson_id] = {
[exercise_id]: { title: exercise_title, points }, [exercise_id]: { title: exercise_title, points }
}; };
} }
}); });
@@ -82,20 +77,16 @@
$: { $: {
students = isStudent students = isStudent
? $group.people.filter( ? $group.people.filter((person) => !!person.profile && person.profile.id === $profile.id)
(person) => !!person.profile && person.profile.id === $profile.id : $group.people.filter((person) => !!person.profile && person.role_id === ROLE.STUDENT);
)
: $group.people.filter(
(person) => !!person.profile && person.role_id === ROLE.STUDENT
);
} }
</script> </script>
<CourseContainer bind:isStudent> <CourseContainer bind:isStudent>
<PageNav title="Marks" /> <PageNav title="Marks" />
<PageBody width="w-11/12"> <PageBody width="w-full max-w-6xl md:w-11/12">
<div class="table rounded-md border border-gray-300 w-auto"> <div class="table rounded-md border border-gray-300 w-full">
<div class="flex items-center {borderBottomGrey}"> <div class="flex items-center {borderBottomGrey}">
<div class="box flex items-center p-3"> <div class="box flex items-center p-3">
<p class="dark:text-white w-40">Student</p> <p class="dark:text-white w-40">Student</p>
@@ -111,8 +102,7 @@
> >
{#each Object.keys(lessonMapping[lesson.id]) as exerciseId, index} {#each Object.keys(lessonMapping[lesson.id]) as exerciseId, index}
<p <p
class="col text-sm dark:text-white {index && class="col text-sm dark:text-white {index && borderleftGrey}"
borderleftGrey}"
title={lessonMapping[lesson.id][exerciseId].title} title={lessonMapping[lesson.id][exerciseId].title}
> >
{lessonMapping[lesson.id][exerciseId].title} {lessonMapping[lesson.id][exerciseId].title}
@@ -129,9 +119,7 @@
</div> </div>
{#each students as student} {#each students as student}
<div <div class="flex relative items-center p-3 cursor-pointer {borderBottomGrey}">
class="flex relative items-center p-3 cursor-pointer {borderBottomGrey}"
>
<div class="w-40 flex items-center"> <div class="w-40 flex items-center">
<img <img
alt="Student avatar" alt="Student avatar"
@@ -143,11 +131,7 @@
{student.profile.fullname} {student.profile.fullname}
</p> </p>
<p class="dark:text-white"> <p class="dark:text-white">
{`${ {`${student.assigned_student_id ? '#' + student.assigned_student_id : '-'}`}
student.assigned_student_id
? '#' + student.assigned_student_id
: '-'
}`}
</p> </p>
</div> </div>
</div> </div>
@@ -176,9 +160,7 @@
{:else} {:else}
<Box> <Box>
<AudioConsoleIcon size={32} class="carbon-icon w-80" /> <AudioConsoleIcon size={32} class="carbon-icon w-80" />
<h3 class="text-3xl text-gray-500 dark:text-white"> <h3 class="text-3xl text-gray-500 dark:text-white">No Student Added</h3>
No Student Added
</h3>
</Box> </Box>
{/each} {/each}
</div> </div>
+141 -129
View File
@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import TextChip from '$lib/components/Chip/Text.svelte'; import TextChip from '$lib/components/Chip/Text.svelte';
import ComingSoon from '$lib/components/ComingSoon/index.svelte'; import ComingSoon from '$lib/components/ComingSoon/index.svelte';
import Filter from 'carbon-icons-svelte/lib/Filter.svelte';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import copy from 'copy-to-clipboard'; import copy from 'copy-to-clipboard';
import { import {
@@ -17,6 +18,7 @@
import { fetchCourse, deleteGroupMember, updatedGroupMember } from '$lib/utils/services/courses'; import { fetchCourse, deleteGroupMember, updatedGroupMember } from '$lib/utils/services/courses';
import TrashCanIcon from 'carbon-icons-svelte/lib/TrashCan.svelte'; import TrashCanIcon from 'carbon-icons-svelte/lib/TrashCan.svelte';
import PageNav from '$lib/components/PageNav/index.svelte'; import PageNav from '$lib/components/PageNav/index.svelte';
import PageBody from '$lib/components/PageBody/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import Select from '$lib/components/Form/Select.svelte'; import Select from '$lib/components/Form/Select.svelte';
import IconButton from '$lib/components/IconButton/index.svelte'; import IconButton from '$lib/components/IconButton/index.svelte';
@@ -135,138 +137,148 @@
</RoleBasedSecurity> </RoleBasedSecurity>
</slot:fragment> </slot:fragment>
</PageNav> </PageNav>
<section class="my-5 mx-9"> <PageBody width="w-full max-w-6xl md:w-11/12">
<div class="flex flex-row flex-end justify-end items-center mb-7"> <section class="my-5 mx-2 md:mx-9">
<div class="mr-5 w-80"> <div
<Search class="flex flex-col md:flex-row flex-end gap-2 justify-end items-start md:items-center mb-7"
class="dark:text-slate-950 border-0 bg-zinc-100 w-full"
placeholder="Search people"
bind:value={searchValue}
/>
</div>
<div class="mb-3">
<Select bind:value={filterBy} options={ROLES} className="dark:text-black mt-3 w-20" />
<!-- <select bind:value={filterBy} class="mt-3">
{#each ROLES as option}
<option value={option.value}>{option.label}</option>
{/each}
</select> -->
</div>
<RoleBasedSecurity allowedRoles={[1, 2]}>
<p class="dark:text-white hidden lg:block text-lg w-20" />
</RoleBasedSecurity>
</div>
<StructuredList class="m-0">
<StructuredListHead
class="bg-slate-100 dark:bg-neutral-800 dark:border-2 dark:border-neutral-800"
> >
<StructuredListRow head class="mx-7"> <div class="max-w-[320px]">
<StructuredListCell head class="text-primary-700 py-3 dark:text-white" <Search
>Name</StructuredListCell class="dark:text-slate-950 border-0 bg-zinc-100 w-full"
> placeholder="Search people"
<StructuredListCell head class="text-primary-700 py-3 dark:text-white" bind:value={searchValue}
>Role</StructuredListCell />
> </div>
<StructuredListCell head class="text-primary-700 py-3 dark:text-white" <div class="mb-3">
>Action</StructuredListCell <Select
> bind:value={filterBy}
<RoleBasedSecurity allowedRoles={[1, 2]}> options={ROLES}
<p class="dark:text-white hidden lg:block text-lg w-20" /> className="dark:text-black mt-3 max-w-[80px]"
</RoleBasedSecurity> />
</StructuredListRow> <!-- <select bind:value={filterBy} class="mt-3">
</StructuredListHead> {#each ROLES as option}
<option value={option.value}>{option.label}</option>
{/each}
</select> -->
</div>
<RoleBasedSecurity allowedRoles={[1, 2]}>
<p class="dark:text-white hidden lg:block text-lg w-20" />
</RoleBasedSecurity>
</div>
{#each filterPeople(searchValue, people) as person} <StructuredList class="m-0">
<StructuredListBody> <StructuredListHead
<StructuredListRow class="relative"> class="bg-slate-100 dark:bg-neutral-800 dark:border-2 dark:border-neutral-800"
<!-- first column --> >
<StructuredListCell class="w-3/6"> <StructuredListRow head class="mx-7">
{#if person.profile} <StructuredListCell head class="text-primary-700 py-3 dark:text-white"
<div class="flex items-center absolute bottom-3"> >Name</StructuredListCell
<Avatar >
src={person.profile.avatar_url} <StructuredListCell head class="text-primary-700 py-3 dark:text-white"
name={person.profile.fullname} >Role</StructuredListCell
width="w-8" >
height="h-8" <StructuredListCell head class="text-primary-700 py-3 dark:text-white"
className="mr-3" >Action</StructuredListCell
/> >
<div class="flex items-center"> <RoleBasedSecurity allowedRoles={[1, 2]}>
<div class="mr-2"> <p class="dark:text-white hidden lg:block text-lg w-20" />
<p class="dark:text-white text-base font-normal"> </RoleBasedSecurity>
{person.profile.fullname} </StructuredListRow>
</p> </StructuredListHead>
<p class="text-xs text-primary-600">
{getEmail(person)} {#each filterPeople(searchValue, people) as person}
</p> <StructuredListBody>
</div> <StructuredListRow class="relative">
<RoleBasedSecurity allowedRoles={[1, 2]}> <!-- first column -->
<div class="hidden lg:flex lg:justify-between lg:items-center mr-2"> <StructuredListCell class="w-4/6 md:w-3/6">
<CopyButton text={getEmail(person)} feedback="Copied Email to clipboard" /> {#if person.profile}
<div class="flex items-start lg:items-center">
<Avatar
src={person.profile.avatar_url}
name={person.profile.fullname}
width="w-8"
height="h-8"
className="mr-3"
/>
<div class="flex flex-col lg:flex-row items-start lg:items-center">
<div class="mr-2">
<p class="dark:text-white text-base font-normal">
{person.profile.fullname}
</p>
<p class="text-xs text-primary-600 line-clamp-1">
{getEmail(person)}
</p>
</div> </div>
</RoleBasedSecurity> <div class="flex items-center">
{#if person.profile_id == $profile.id} <RoleBasedSecurity allowedRoles={[1, 2]}>
<ComingSoon label="You" /> <CopyButton
text={getEmail(person)}
feedback="Copied Email to clipboard"
/>
</RoleBasedSecurity>
{#if person.profile_id == $profile.id}
<ComingSoon label="You" />
{/if}
</div>
</div>
</div>
{:else}
<div class="flex items-start lg:items-center w-2/4">
<TextChip
value={person.email.substring(0, 2).toUpperCase()}
className="bg-primary-200 text-black font-semibold text-xs mr-3"
shape="rounded-full"
/>
<a
href="mailto:{person.email}"
class="text-md text-primary-600 mr-2 dark:text-white"
>
{person.email}
</a>
<div class="flex items-center justify-between">
<RoleBasedSecurity allowedRoles={[1, 2]}>
<CopyButton text={getEmail(person)} feedback="Copied Email to clipboard" />
</RoleBasedSecurity>
<TextChip
value="Pending"
className="text-xs bg-yellow-200 text-yellow-700 h-fit"
size="sm"
/>
</div>
</div>
{/if}
</StructuredListCell>
<!-- second column -->
<StructuredListCell class="w-1/4 px-3">
<p class=" dark:text-white font-normal text-center text-base w-1/4">
{ROLE_LABEL[person.role_id]}
</p>
</StructuredListCell>
<!-- third column -->
<StructuredListCell class="p-0 w-1/4">
<RoleBasedSecurity allowedRoles={[1, 2]}>
<div class="hidden lg:flex lg:justify-between lg:items-center w-20">
{#if person.profile_id !== $profile.id}
<IconButton
onClick={() => {
member = person;
$deleteMemberModal.open = true;
}}
>
<TrashCanIcon size={16} class="carbon-icon dark:text-white" />
</IconButton>
{/if} {/if}
</div> </div>
</div> </RoleBasedSecurity>
{:else} </StructuredListCell>
<div class="flex items-center w-2/4 absolute bottom-3"> </StructuredListRow>
<TextChip </StructuredListBody>
value={person.email.substring(0, 2).toUpperCase()} {/each}
className="bg-primary-200 text-black font-semibold text-xs mr-3" </StructuredList>
shape="rounded-full" <!-- <Pagination totalItems={10} pageSizes={[10, 15, 20]} /> -->
/> </section>
<a </PageBody>
href="mailto:{person.email}"
class="text-md text-primary-600 mr-2 dark:text-white"
>
{person.email}
</a>
<RoleBasedSecurity allowedRoles={[1, 2]}>
<div class="hidden lg:flex lg:justify-between lg:items-center w-20">
<CopyButton text={getEmail(person)} feedback="Copied Email to clipboard" />
</div>
</RoleBasedSecurity>
<TextChip
value="Pending"
className="text-xs bg-yellow-200 text-yellow-700 h-fit"
size="sm"
/>
</div>
{/if}
</StructuredListCell>
<!-- second column -->
<StructuredListCell class="w-1/4 py-4 px-3">
<p class="dark:text-white font-normal text-base w-1/4 my-auto">
{ROLE_LABEL[person.role_id]}
</p>
</StructuredListCell>
<!-- third column -->
<StructuredListCell class="p-0 w-1/4">
<RoleBasedSecurity allowedRoles={[1, 2]}>
<div class="hidden lg:flex lg:justify-between lg:items-center w-20">
{#if person.profile_id !== $profile.id}
<IconButton
onClick={() => {
member = person;
$deleteMemberModal.open = true;
}}
>
<TrashCanIcon size={16} class="carbon-icon dark:text-white" />
</IconButton>
{/if}
</div>
</RoleBasedSecurity>
</StructuredListCell>
</StructuredListRow>
</StructuredListBody>
{/each}
</StructuredList>
<Pagination totalItems={10} pageSizes={[10, 15, 20]} />
</section>
</CourseContainer> </CourseContainer>
@@ -244,8 +244,8 @@
<CourseContainer> <CourseContainer>
<PageNav title="Submitted Exercises" /> <PageNav title="Submitted Exercises" />
<PageBody width="w-11/12 overflow-x-auto overflow-y-hidden"> <PageBody width="w-full max-w-6xl md:w-11/12 overflow-x-auto">
<div class="flex items-center w-full"> <div class="flex items-center w-full overflow-x-scroll">
{#each sections as { id, title, items }, idx (id)} {#each sections as { id, title, items }, idx (id)}
<div <div
class="section rounded-md bg-gray-100 dark:bg-gray-800 border border-gray-50 p-3 h-80 mr-3 overflow-hidden" class="section rounded-md bg-gray-100 dark:bg-gray-800 border border-gray-50 p-3 h-80 mr-3 overflow-hidden"
@@ -301,7 +301,7 @@
{`${item.tutor ? 'created by' + item.tutor.name : ''}`} {`${item.tutor ? 'created by' + item.tutor.name : ''}`}
</p> </p>
</a> </a>
<p class="dark:text-white text-gray-500 dark:text-white text-xs"> <p class="dark:text-white text-gray-500 text-xs">
{item.submittedAt} {item.submittedAt}
</p> </p>
<!-- <div class="badge rounded-md px-2 bg-green-500 text-white"> <!-- <div class="badge rounded-md px-2 bg-green-500 text-white">
@@ -324,10 +324,15 @@
.section { .section {
max-width: 355px; max-width: 355px;
min-width: 355px; min-width: 355px;
height: 80vh; height: 75vh;
} }
.content { .content {
height: 95%; height: 95%;
} }
@media screen and (max-width: 768px) {
.section {
min-width: 250px;
}
}
</style> </style>