CLASSROOMIO-T-36: Student authentication flow

Co-authored-by: Rotimi Best <[email protected]>

Merge-request: CLASSROOMIO-MR-12
Merged-by: Digdippa Team <[email protected]>
This commit is contained in:
Rotimi Best
2023-05-16 04:31:45 +00:00
committed by Space Cloud
co-authored by Rotimi Best
parent 8d0f1e4de1
commit 68e1dbb1b5
12 changed files with 387 additions and 38 deletions
+44
View File
@@ -0,0 +1,44 @@
<svg
width="25"
height="24"
viewBox="0 0 25 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="dark"
>
<path
d="M16.9999 2H8.99991C8.46948 2 7.96077 2.21071 7.58569 2.58579C7.21062 2.96086 6.99991 3.46957 6.99991 4V20C6.99991 20.5304 7.21062 21.0391 7.58569 21.4142C7.96077 21.7893 8.46948 22 8.99991 22H20.9999C21.5303 22 22.039 21.7893 22.4141 21.4142C22.7892 21.0391 22.9999 20.5304 22.9999 20V8L16.9999 2Z"
stroke="#7A797D"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M16.9999 2V8H22.9999"
stroke="#7A797D"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M18.9999 13H10.9999"
stroke="#7A797D"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M18.9999 17H10.9999"
stroke="#7A797D"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M12.9999 9H11.9999H10.9999"
stroke="#7A797D"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+119
View File
@@ -0,0 +1,119 @@
<script>
import { stores } from '@sapper/app';
import Help from 'carbon-icons-svelte/lib/Help20';
import TextChip from '../../components/Chip/Text.svelte';
import OrgSelector from '../../components/OrgSelector/OrgSelector.svelte';
import HomeIcon from '../../components/Icons/HomeIcon.svelte';
import CourseIcon from '../../components/Icons/CourseIcon.svelte';
import ExerciseIcon from '../../components/Icons/ExerciseIcon.svelte';
import Avatar from '../../components/Avatar/index.svelte';
import { currentOrg } from '../../utils/store/org';
import { profile } from '../../utils/store/user';
let activeClass = 'bg-gray-200 dark:bg-gray-500';
let { page } = stores();
function isActive(pagePath, itemPath) {
const pageLinkItems = pagePath.split('/');
const itemLinkItems = itemPath.split('/');
if (itemLinkItems.length !== pageLinkItems.length) {
return false;
}
return pagePath.includes(itemPath);
}
</script>
<aside class="root bg-gray-100 dark:bg-gray-700 h-full">
<div class="h-full flex flex-col">
<div class="border-b border-gray-200 pt-5 px-4">
{#if $currentOrg.avatar_url}
<Avatar
src={$currentOrg.avatar_url}
name={$currentOrg.name}
shape="rounded-md"
width="w-7"
height="h-7"
/>
{:else}
<TextChip
value={$currentOrg.shortName}
className="bg-blue-200 font-bold"
/>
{/if}
<OrgSelector />
<ul class="my-5">
<a href="/lms" class="text-black">
<li
class="flex items-center py-3 px-4 mb-2 rounded hover:bg-gray-200 dark:hover:bg-gray-500 {isActive(
$page.path,
`/lms`
) && activeClass}"
>
<HomeIcon />
<p class="dark:text-white ml-2">Home</p>
</li>
</a>
<a href="/lms/mylearning" class="text-black">
<li
class="flex items-center py-3 px-4 mb-2 rounded hover:bg-gray-200 dark:hover:bg-gray-500 {isActive(
$page.path,
`/lms/mylearning`
) && activeClass}"
>
<CourseIcon />
<p class="dark:text-white ml-2">My Learning</p>
</li>
</a>
<a href="/lms/exercises" class="text-black">
<li
class="flex items-center py-3 px-4 mb-2 rounded hover:bg-gray-200 dark:hover:bg-gray-500 {isActive(
$page.path,
`/lms/exercises`
) && activeClass}"
>
<ExerciseIcon />
<p class="dark:text-white ml-2">Exercises</p>
</li>
</a>
</ul>
</div>
<span class="flex-grow" />
<ul class="my-5 pb-5 px-4">
<a href="/lms" class="text-black">
<li
class="flex items-center py-3 px-4 mb-2 rounded hover:bg-gray-200 dark:hover:bg-gray-500"
>
<Help class="carbon-icon" />
<p class="dark:text-white ml-2">Help</p>
</li>
</a>
<a href="/lms/settings" class="text-black">
<li
class="flex items-center py-3 px-4 mb-2 rounded hover:bg-gray-200 dark:hover:bg-gray-500 {isActive(
$page.path,
`/lms/settings`
) && activeClass}"
>
<Avatar
src={$profile.avatar_url}
name={$profile.username}
width="w-7"
height="h-7"
/>
<p class="dark:text-white ml-2">Settings</p>
</li>
</a>
</ul>
</div>
</aside>
<style>
.root {
width: 250px;
}
</style>
+28 -20
View File
@@ -1,6 +1,7 @@
<script>
import { goto } from '@sapper/app';
import { goto, stores } from '@sapper/app';
import { user } from '../../utils/store/user';
import { isCoursePage } from '../../utils/functions/app';
import PrimaryButton from '../PrimaryButton/index.svelte';
import { VARIANTS } from '../PrimaryButton/constants';
@@ -9,13 +10,16 @@
export let logo = '/logo-192.png';
export let orgName = 'ClassroomIO';
let { page } = stores();
let navClass = '';
const redirect = isCoursePage($page.path) ? `?redirect=${$page.path}` : '';
$: navClass = ['discussion'].includes(segment) ? 'hide' : '';
</script>
<nav
class="{navClass} flex w-full p-2 border-t-0 border-r-0 border-b border-l-0 border-gray-300"
class="{navClass} bg-white sticky top-0 z-50 flex w-full p-2 border-t-0 border-r-0 border-b border-l-0 border-gray-300"
>
<ul class="flex w-full items-center">
<div class="logo">
@@ -76,24 +80,28 @@
<span class="flex-grow" />
<li>
{#if !disableLogin}
<div class="flex">
<PrimaryButton
label="Login"
variant={VARIANTS.NONE}
className="py-3 px-6 mx-2 app-background-color"
onClick={() => goto('/login')}
/>
<PrimaryButton
label="Sign Up"
variant={VARIANTS.CONTAINED}
className="py-3 px-6 mx-2"
onClick={() => goto('/signup')}
/>
</div>
{/if}
</li>
{#if $user.isLoggedIn}
<li><a class="block" href="/lms"> Go to LMS </a></li>
{:else}
<li>
{#if !disableLogin}
<div class="flex">
<PrimaryButton
label="Login"
variant={VARIANTS.NONE}
className="py-3 px-6 mx-2 app-background-color"
onClick={() => goto('/login' + redirect)}
/>
<PrimaryButton
label="Sign Up"
variant={VARIANTS.CONTAINED}
className="py-3 px-6 mx-2"
onClick={() => goto('/signup' + redirect)}
/>
</div>
{/if}
</li>
{/if}
<!-- <li class="hidden">
<a
class="flex items-center"
+102
View File
@@ -0,0 +1,102 @@
<script>
import { stores } from '@sapper/app';
import NotificationIcon from 'carbon-icons-svelte/lib/Notification20';
import Moon from 'carbon-icons-svelte/lib/Moon16';
import Sun from 'carbon-icons-svelte/lib/Sun16';
import IconButton from '../IconButton/index.svelte';
import { appStore } from '../../utils/store/app';
import { toggleBodyByTheme } from '../../utils/functions/app';
export let navClass = '';
const { page } = stores();
function toggleTheme() {
$appStore.isDark = !$appStore.isDark;
toggleBodyByTheme($appStore.isDark);
localStorage.setItem('theme', $appStore.isDark ? 'dark' : '');
}
</script>
<nav class="{navClass} flex w-full p-2 md:px-6 bg-blue-600">
<ul class="flex w-full items-center">
<div class="">
<a
href={$page.path}
title="Go to ClassroomIO Home"
id="logo"
class="text-lg"
>
ClassroomIO
</a>
</div>
<span class="flex-grow" />
<li>
<NotificationIcon class="text-white mr-2" />
</li>
<li>
<IconButton size="small" onClick={toggleTheme}>
{#if $appStore.isDark}
<Sun class="text-white" />
{:else}
<Moon class="text-white" />
{/if}
</IconButton>
</li>
<li />
</ul>
</nav>
<style>
ul {
padding: 0;
}
/* clearfix */
ul::after {
content: '';
display: block;
clear: both;
}
/* li.new-question {
margin-top: 10px;
} */
a {
text-decoration: none;
color: #fff;
font-weight: 700;
}
/* [aria-current] {
color: var(--main-primary-color);
position: relative;
display: inline-block;
}
[aria-current]::after {
position: absolute;
content: '';
width: calc(100% - 3em);
height: 2px;
background-color: var(--main-primary-color);
display: block;
bottom: -17px;
} */
@media only screen and (max-width: 1002px) {
nav.hide {
display: none;
}
ul {
align-items: center;
}
a {
padding: 0 0.5em;
}
}
</style>
+1 -1
View File
@@ -99,7 +99,7 @@
</div>
<span class="flex-grow" />
<ul class="my-5 pb-5 px-4">
<a href="/help" class="text-black">
<a href="/org" class="text-black">
<li
class="flex items-center py-3 px-4 mb-2 rounded hover:bg-gray-200 dark:hover:bg-gray-500"
>