CLASSROOMIO-T-97: Course UI improvement 😁😁😁

This commit is contained in:
Rotimi Best
2023-08-05 04:44:32 +01:00
parent 131bb878ee
commit d542a4f7e3
27 changed files with 258 additions and 319 deletions
+16 -14
View File
@@ -22,6 +22,7 @@
// import Footer from '$lib/components/Footer/index.svelte';
import Apps from '$lib/components/Apps/index.svelte';
import PlayQuiz from '$lib/components/Org/Quiz/Play/index.svelte';
import { course } from '$lib/components/Course/store';
import { isCoursesPage, isOrgPage, isLMSPage, isQuizPage } from '$lib/utils/functions/app';
import showAppsSideBar from '$lib/utils/functions/showAppsSideBar';
import isPublicRoute from '$lib/utils/functions/routes/isPublicRoute';
@@ -71,9 +72,13 @@
const {
data: { session }
} = await supabase.auth.getSession();
const { user: authUser } = session;
const { user: authUser } = session || {};
console.log('Get user profile', authUser);
if (!authUser) {
goto('/login');
}
// Check if user has profile
let {
data: profileData,
@@ -207,16 +212,13 @@
handleResize();
// if (
// !localStorage.getItem('supabase.auth.token') &&
// !isPublicRoute($page.url.pathname)
// ) {
// console.log(
// 'No auth token and is not a public route, redirect to login',
// path
// );
// return goto('/login');
// }
if (
!localStorage.getItem('sb-koxqonvbkeakwvmdegcf-auth-token') &&
!isPublicRoute($page.url.pathname)
) {
console.log('No auth token and is not a public route, redirect to login', path);
return goto('/login');
}
const { data: authListener } = supabase.auth.onAuthStateChange((event, session) => {
// Log key events
@@ -285,9 +287,9 @@
<Moon size="60" color="#1d4ed8" unit="px" duration="1s" />
</Backdrop>
{/if}
{#if !ROUTES_TO_HIDE_NAV.includes($page.url.pathname) && !isCoursesPage(path)}
{#if isOrgPage($page.url.pathname) || $page.url.pathname.includes('profile')}
<OrgNavigation />
{#if !ROUTES_TO_HIDE_NAV.includes($page.url.pathname)}
{#if isOrgPage($page.url.pathname) || $page.url.pathname.includes('profile') || isCoursesPage(path)}
<OrgNavigation bind:title={$course.title} isCoursePage={isCoursesPage(path)} />
{:else if isLMSPage($page.url.pathname)}
<LMSNavigation />
{:else}
-1
View File
@@ -79,7 +79,6 @@
type="email"
placeholder="Enter your email.."
className="mr-3 my-2"
inputClassName="rounded-md"
isRequired={true}
isDisabled={isAdding}
/>
@@ -13,6 +13,8 @@
// import { Tabs, Tab } from 'carbon-components-svelte';
// import TabContent from 'carbon-components-svelte/src/Tabs/TabContent.svelte';
import StudentCertificate from '$lib/components/Course/components/Ceritficate/StudentCertificate/Index.svelte';
import { fetchCourse } from '$lib/utils/services/courses';
export let courseId: string = '';
let isStudent = false;
@@ -15,7 +15,7 @@
import {
fetchSubmissions,
updateSubmission,
updateQuestionAnswer,
updateQuestionAnswer
} from '$lib/utils/services/submissions';
import { formatAnswers } from '$lib/components/Course/function';
import { snackbarStore } from '$lib/components/Snackbar/store';
@@ -33,20 +33,20 @@
id: 1,
title: 'Submitted',
value: 0,
items: [],
items: []
},
{
id: 2,
title: 'In Progress',
value: 0,
items: [],
items: []
},
{
id: 3,
title: 'Graded',
value: 10,
items: [],
},
items: []
}
];
let submissionIdData = {};
let submissionId;
@@ -73,7 +73,7 @@
// Update key mapping for each submission also
submissionIdData[itemToWithNewStatus.id] = {
...submissionIdData[itemToWithNewStatus.id],
status_id: itemToWithNewStatus.statusId,
status_id: itemToWithNewStatus.statusId
};
console.log(
`submissionIdData[itemToWithNewStatus.id]`,
@@ -82,7 +82,7 @@
updateSubmission({
id: itemToWithNewStatus.id,
status_id: itemToWithNewStatus.statusId,
status_id: itemToWithNewStatus.statusId
}).then((res) => console.log('Updated submission', res));
}
}
@@ -118,24 +118,21 @@
});
console.log(`itemToWithNewStatus`, itemToWithNewStatus);
// Move to right column
sections[nextStatusId - 1].items = [
...sections[nextStatusId - 1].items,
itemToWithNewStatus,
];
sections[nextStatusId - 1].items = [...sections[nextStatusId - 1].items, itemToWithNewStatus];
// If something changed
if (itemToWithNewStatus) {
// Update key mapping for each submission also
submissionIdData[itemToWithNewStatus.id] = {
...submissionIdData[itemToWithNewStatus.id],
status_id: itemToWithNewStatus.statusId,
status_id: itemToWithNewStatus.statusId
};
// Update backend
updateSubmission({
id: itemToWithNewStatus.id,
status_id: itemToWithNewStatus.statusId,
total,
total
}).then((res) => console.log('Updated submission', res));
}
}
@@ -146,9 +143,7 @@
let totalPoints = 0;
const updates = Object.keys(questionAnswerByPoint).map((questionId) => {
const questionAnswer = questionAnswers.find(
(answer) => answer.question_id == questionId
);
const questionAnswer = questionAnswers.find((answer) => answer.question_id == questionId);
const point = questionAnswerByPoint[questionId];
@@ -159,7 +154,7 @@
updateSubmission({
id: submissionId,
total: totalPoints,
total: totalPoints
}).then((res) => console.log('Updated submission', res));
$snackbarStore.open = true;
@@ -175,21 +170,11 @@
setCourse(data);
}
const { data: submissions } = await fetchSubmissions(
courseId || $course.id
);
const { data: submissions } = await fetchSubmissions(courseId || $course.id);
const sectionById = {};
for (const submission of submissions) {
const {
id,
created_at,
exercise,
course,
answers,
groupmember,
status_id,
} = submission;
const { id, created_at, exercise, course, answers, groupmember, status_id } = submission;
const isEarly = isSubmissionEarly(created_at, exercise.due_by);
const submissionItem = {
@@ -199,14 +184,14 @@
submittedAt: formatDate(created_at),
exercise: {
id: exercise.id,
title: exercise.title,
title: exercise.title
},
answers,
student: groupmember && groupmember.profile ? groupmember.profile : {},
lesson: {
id: exercise.lesson.id,
title: exercise.lesson.title,
},
title: exercise.lesson.title
}
};
submissionIdData[id] = {
@@ -222,7 +207,7 @@
acc[answer.question_id] = answer.point;
return acc;
}, {}),
}, {})
};
if (Array.isArray(sectionById[status_id])) {
@@ -234,17 +219,13 @@
sections = sections.map((section, index) => ({
...section,
value: Array.isArray(sectionById[index + 1])
? sectionById[index + 1].length
: 0,
items: Array.isArray(sectionById[index + 1])
? sectionById[index + 1]
: [],
value: Array.isArray(sectionById[index + 1]) ? sectionById[index + 1].length : 0,
items: Array.isArray(sectionById[index + 1]) ? sectionById[index + 1] : []
}));
});
$: {
const query = new URLSearchParams($page.url.search)
const query = new URLSearchParams($page.url.search);
submissionId = query.get('submissionId');
openExercise = !!submissionId && submissionIdData[submissionId];
}
@@ -279,7 +260,7 @@
use:dndzone={{
items,
flipDurationMs,
dropTargetStyle: { outline: 'blue' },
dropTargetStyle: { outline: 'blue' }
}}
on:consider={handleDndConsiderCards(idx)}
on:finalize={handleDndFinalizeCards(idx)}
@@ -291,11 +272,9 @@
: 'border-red-700'} w-full my-2 mx-0 rounded-md bg-white dark:bg-gray-800 py-3 px-3"
animate:flip={{ duration: flipDurationMs }}
>
<div
class="flex items-center cursor-pointer text-black mb-2"
on:click={() => {
goto(`${$page.url.pathname}?submissionId=${item.id}`);
}}
<a
class="flex w-full items-center cursor-pointer text-black mb-2"
href={`${$page.url.pathname}?submissionId=${item.id}`}
>
<img
alt="Student avatar"
@@ -305,7 +284,7 @@
<p class="dark:text-white ml-2 text-sm">
{item.student.username}
</p>
</div>
</a>
<a
class="text-blue-700 text-md font-bold"
href="{$page.url.pathname}?submissionId={item.id}"
@@ -314,19 +293,15 @@
</a>
<a
class="flex items-center no-underline hover:underline text-black my-2"
href="{$page.url.pathname.replace(
'submissions',
'lessons'
)}/{item.lesson.id}/exercises/{item.exercise.id}"
href="{$page.url.pathname.replace('submissions', 'lessons')}/{item.lesson
.id}/exercises/{item.exercise.id}"
>
<p class="dark:text-white text-grey text-sm">
#{item.lesson.title}
{`${item.tutor ? 'created by' + item.tutor.name : ''}`}
</p>
</a>
<p
class="dark:text-white text-gray-500 dark:text-white text-xs"
>
<p class="dark:text-white text-gray-500 dark:text-white text-xs">
{item.submittedAt}
</p>
<!-- <div class="badge rounded-md px-2 bg-green-500 text-white">
@@ -306,10 +306,9 @@
{#if question.author.id === $profile.id}
<PrimaryButton
label={isEditMode ? 'Save' : 'Edit'}
variant={VARIANTS.CONTAINED_INFO}
variant={VARIANTS.OUTLINED}
onClick={handleQuestionEdit}
className="py-3 px-6 rounded-sm h-fit"
disablePadding={true}
className="h-fit"
/>
{#if isEditMode}
<PrimaryButton
+19 -42
View File
@@ -26,7 +26,7 @@
let {
data: profileData,
error,
status,
status
} = await supabase.from('profile').select(`*`).eq('id', profileId).single();
if (error && !profileData && status === 406 && $user.currentSession) {
@@ -47,23 +47,19 @@
const updates = {
fullname: currentProfile.fullname,
username: currentProfile.username,
username: currentProfile.username
};
if (avatar) {
const filename = `user/${currentProfile.username + Date.now()}.webp`;
const { data } = await supabase.storage
.from('avatars')
.upload(filename, avatar, {
cacheControl: '3600',
upsert: false,
});
const { data } = await supabase.storage.from('avatars').upload(filename, avatar, {
cacheControl: '3600',
upsert: false
});
if (data && data.Key) {
const { publicURL } = supabase.storage
.from('avatars')
.getPublicUrl(filename);
const { publicURL } = supabase.storage.from('avatars').getPublicUrl(filename);
updates.avatar_url = publicURL;
currentProfile.avatar_url = publicURL;
@@ -71,15 +67,12 @@
avatar = undefined;
}
let { error } = await supabase
.from('profile')
.update(updates)
.match({ id: profileId });
let { error } = await supabase.from('profile').update(updates).match({ id: profileId });
if (isOwner) {
profile.update((_profile) => ({
..._profile,
...updates,
...updates
}));
}
@@ -117,9 +110,7 @@
<title>Profile of {currentProfile.username}</title>
</svelte:head>
<section
class="root w-11/12 mt-3 m-auto flex items-start justify-between flex-col lg:flex-row"
>
<section class="root w-11/12 mt-3 m-auto flex items-start justify-between flex-col lg:flex-row">
{#if currentProfile.id}
<div class="w-full lg:w-1/4 flex items-center flex-col">
<!-- <img
@@ -129,11 +120,7 @@
width="260"
class="rounded-full bg-light-blue-100 mb-4"
/> -->
<UploadImage
bind:avatar
src={currentProfile.avatar_url}
widthHeight="w-60 h-60"
/>
<UploadImage bind:avatar src={currentProfile.avatar_url} widthHeight="w-60 h-60" />
{#if isOwner}
<TextField
@@ -172,19 +159,16 @@
<div class="flex-grow flex flex-wrap mx-3 w-3/5">
<div class="mb-3 w-full">
<h3 class="dark:text-white font-bold text-md m-0">Organizations</h3>
<p class="dark:text-white text-gray-500 text-sm">
This are the organizations you work at
</p>
<p class="dark:text-white text-gray-500 text-sm">This are the organizations you work at</p>
<div class="hidden my-3 py-3 px-4 border shadow-sm rounded-md">
<h4 class="dark:text-white m-0 font-normal">
<a class="text-blue-700 font-bold" href="/courses"> CitiBim </a>
</h4>
<p class="dark:text-white text-gray-500">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Non aliquam
tenetur magnam. Alias cumque quaerat expedita dolores placeat
laboriosam culpa, suscipit veritatis adipisci eius magni obcaecati.
Sequi doloremque blanditiis earum.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Non aliquam tenetur magnam.
Alias cumque quaerat expedita dolores placeat laboriosam culpa, suscipit veritatis
adipisci eius magni obcaecati. Sequi doloremque blanditiis earum.
</p>
<div class="mt-2 flex items-center">
<span class="flex mr-2 items-center">
@@ -199,13 +183,11 @@
<div class="hidden my-2 py-3 px-4 border shadow-sm rounded-md">
<h4 class="dark:text-white m-0 font-normal">
<a class="text-blue-700 font-bold" href="/courses">
Climate Change Group
</a>
<a class="text-blue-700 font-bold" href="/courses"> Climate Change Group </a>
</h4>
<p class="dark:text-white text-gray-500">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo quasi
autem quo possimus illum consequuntur repudiandae nobis error, porro
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo quasi autem quo possimus
illum consequuntur repudiandae nobis error, porro
</p>
<div class="mt-2 flex items-center">
<span class="flex mr-2 items-center">
@@ -218,12 +200,7 @@
</div>
</div>
</div>
<PrimaryButton
className="px-6 py-3"
variant={VARIANTS.CONTAINED_DANGER}
label="Log out"
onClick={logout}
/>
<PrimaryButton variant={VARIANTS.CONTAINED_DANGER} label="Log out" onClick={logout} />
</div>
<!-- {:else if loading}
<Box>