CLASSROOMIO-T-79: Implement empty state pages

Co-authored-by: Rotimi Best <rotimiibitoyeemma@gmail.com>


Merge-request: CLASSROOMIO-MR-32
Merged-by: Best Admin <best@digdippa.com>
This commit is contained in:
Rotimi Best
2023-08-02 21:17:17 +00:00
committed by Space Cloud
co-authored by Rotimi Best
parent 8ae0bffc34
commit 60d0c6d837
14 changed files with 161 additions and 209 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
</script>
<div
class="{className} w-full h-80 flex items-center justify-center flex-col border rounded border-gray-200"
class="{className} w-full h-[517px] flex items-center justify-center flex-col border rounded border-gray-200"
>
<slot />
</div>
@@ -9,16 +9,14 @@
import CheckboxQuestion from '$lib/components/Question/CheckboxQuestion/index.svelte';
import TextareaQuestion from '$lib/components/Question/TextareaQuestion/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import Box from '$lib/components/Box/index.svelte';
import RoleBasedSecurity from '$lib/components/RoleBasedSecurity/index.svelte';
import Progress from '$lib/components/Progress/index.svelte';
import { removeDuplicate } from '$lib/utils/functions/removeDuplicate';
import { QUESTION_TYPE } from '$lib/components/Question/constants';
import { STATUS } from './constants';
import { getPropsForQuestion, filterOutDeleted } from './functions';
import {
formatAnswers,
getGroupMemberId,
} from '$lib/components/Course/function';
import { formatAnswers, getGroupMemberId } from '$lib/components/Course/function';
import { submitExercise } from '$lib/utils/services/courses';
import { fetchSubmission } from '$lib/utils/services/submissions';
import { profile } from '$lib/utils/store/user';
@@ -42,21 +40,18 @@
const prevAnswer = answers[id] || [];
const formattedAnswer =
typeof value === 'string'
? value
: removeDuplicate([...prevAnswer, ...(value || [])]);
typeof value === 'string' ? value : removeDuplicate([...prevAnswer, ...(value || [])]);
$questionnaireMetaData.answers = {
...answers,
[id]: formattedAnswer,
[id]: formattedAnswer
};
if (moveToNextQuestion) {
$questionnaireMetaData.currentQuestionIndex += 1;
}
const isFinished =
!questions[$questionnaireMetaData.currentQuestionIndex - 1];
const isFinished = !questions[$questionnaireMetaData.currentQuestionIndex - 1];
console.log(`isFinished`, isFinished);
console.log(
`$questionnaireMetaData.currentQuestionIndex`,
@@ -87,11 +82,7 @@
return 100;
}
return (
Math.round(
((currentQuestionIndex - 1) / $questionnaire.questions.length) * 100
) || 0
);
return Math.round(((currentQuestionIndex - 1) / $questionnaire.questions.length) * 100) || 0;
}
function getTotalPossibleGrade() {
@@ -113,7 +104,7 @@
const args = {
exerciseId,
courseId,
submittedBy: getGroupMemberId(people, profileId),
submittedBy: getGroupMemberId(people, profileId)
};
const { data } = await fetchSubmission(args);
hasSubmission = true;
@@ -123,31 +114,26 @@
$questionnaireMetaData.answers = formatAnswers({
questions: $questionnaire.questions,
answers: submission.answers,
answers: submission.answers
});
$questionnaireMetaData.totalPossibleGrade = getTotalPossibleGrade();
$questionnaireMetaData.currentQuestionIndex =
$questionnaire.questions.length;
$questionnaireMetaData.currentQuestionIndex = $questionnaire.questions.length;
$questionnaireMetaData.isFinished = true;
$questionnaireMetaData.status = submission.status_id;
$questionnaireMetaData.finalTotalGrade = 0;
$questionnaireMetaData.grades = submission.answers.reduce(
(acc, answer) => {
acc[answer.question_id] = answer.point;
$questionnaireMetaData.finalTotalGrade += answer.point;
$questionnaireMetaData.grades = submission.answers.reduce((acc, answer) => {
acc[answer.question_id] = answer.point;
$questionnaireMetaData.finalTotalGrade += answer.point;
return acc;
},
{}
);
return acc;
}, {});
}
}
$: {
currentQuestion =
$questionnaire.questions[$questionnaireMetaData.currentQuestionIndex - 1];
currentQuestion = $questionnaire.questions[$questionnaireMetaData.currentQuestionIndex - 1];
if ($questionnaireMetaData.currentQuestionIndex > 0 && !currentQuestion) {
$questionnaireMetaData.isFinished = true;
}
@@ -182,16 +168,15 @@
questionnaireMetaData={$questionnaireMetaData}
/>
{:else if !$questionnaire.questions.length}
<div
class="w-4/5 h-40 m-auto flex items-center justify-center text-center border-2 border-gray-200 rounded-md"
>
<h3 class="dark:text-white text-2xl">
No questions added. <br />
<Box>
<img src="/images/empty-exercise-icon.svg" alt="Exercise svg" class="my-2.5" />
<h2 class="text-xl my-1.5">No question added for this exercise</h2>
<p class="text-sm text-center px-44">
<RoleBasedSecurity allowedRoles={[1, 2]}>
Click the <span class="text-blue-700">Edit</span> button to add.
</RoleBasedSecurity>
</h3>
</div>
</p>
</Box>
{:else if $questionnaireMetaData.currentQuestionIndex === 0}
<div>
<h2 class="my-1">{$questionnaire.title}</h2>
@@ -219,12 +204,7 @@
{@html marked($questionnaire.description || 'No desription')}
</article>
<PrimaryButton
onClick={handleStart}
label="Start"
className="my-5 float-right"
type="button"
/>
<PrimaryButton onClick={handleStart} label="Start" className="my-5 float-right" type="button" />
</div>
{:else if $questionnaireMetaData.isFinished}
<div class="flex items-center justify-between">
@@ -1,7 +1,6 @@
<script>
import { goto } from '$app/navigation';
import { onMount } from 'svelte';
import AudioConsoleIcon from 'carbon-icons-svelte/lib/AudioConsole.svelte';
import Box from '$lib/components/Box/index.svelte';
import { Moon } from 'svelte-loading-spinners';
import Backdrop from '$lib/components/Backdrop/index.svelte';
@@ -26,19 +25,19 @@
let newExercise = {
id: 1,
title: '',
description: '',
description: ''
};
async function handleAddExercise() {
const { data, error } = await createExercise({
title: newExercise.title,
lesson_id: lessonId,
lesson_id: lessonId
});
console.log(`data, error `, data, error);
lesson.update((_lesson) => ({
..._lesson,
exercises: [..._lesson.exercises, data[0]],
exercises: [..._lesson.exercises, data[0]]
}));
handleCancelAddExercise();
@@ -49,7 +48,7 @@
newExercise = {
id: $lesson.exercises.length + 1,
title: '',
description: '',
description: ''
};
}
@@ -133,41 +132,20 @@
{/if}
{#if exerciseId}
<Exercise
{exerciseId}
{goBack}
refetchExercise={() => getExercise(exerciseId)}
/>
<Exercise {exerciseId} {goBack} refetchExercise={() => getExercise(exerciseId)} />
{:else}
<Modal
onClose={handleCancelAddExercise}
bind:open
modalHeading="Create an Exercise"
width="w-80"
>
<TextField
bind:value={newExercise.title}
autofocus={true}
placeholder="Exercise name"
/>
<Modal onClose={handleCancelAddExercise} bind:open modalHeading="Create an Exercise" width="w-80">
<TextField bind:value={newExercise.title} autofocus={true} placeholder="Exercise name" />
<div class="mt-5 flex items-center">
<PrimaryButton
className="px-6 py-3"
label="Submit"
onClick={handleAddExercise}
/>
<PrimaryButton className="px-6 py-3" label="Submit" onClick={handleAddExercise} />
</div>
</Modal>
<PageBody>
<slot:fragment slot="header">
<RoleBasedSecurity allowedRoles={[1, 2]}>
<PrimaryButton
className="mr-2"
label="Add"
onClick={() => (open = !open)}
/>
<PrimaryButton className="mr-2" label="Add" onClick={() => (open = !open)} />
</RoleBasedSecurity>
</slot:fragment>
@@ -181,11 +159,15 @@
<p class="dark:text-white mt-4 text-sm">Created Jul 3, 2021</p>
</a>
{:else}
<Box>
<AudioConsoleIcon size={32} class="carbon-icon w-80" />
<h3 class="text-3xl text-gray-500 dark:text-white">
No Exercise Added
</h3>
<Box className="mt-3">
<div class="flex justify-between flex-col items-center w-96">
<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>
<p class="text-sm text-center text-slate-500">
Share your knowledge with the world by creating engaging exercises. Add an exercise
now.
</p>
</div>
</Box>
{/each}
</div>
@@ -8,11 +8,7 @@
import Box from '$lib/components/Box/index.svelte';
import EditContent from '$lib/components/EditContent/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import {
lesson,
handleUpdateLessonMaterials,
isLessonDirty,
} from '../store/lessons';
import { lesson, handleUpdateLessonMaterials, isLessonDirty } from '../store/lessons';
import * as CONSTANTS from './constants';
export let mode = MODES.view;
@@ -42,10 +38,7 @@
} else if (tab.value === 2) {
badgeValue = !!note ? 1 : 0;
} else {
badgeValue =
typeof video_url === 'string' && !!video_url
? video_url.split(',').length
: 0;
badgeValue = typeof video_url === 'string' && !!video_url ? video_url.split(',').length : 0;
}
tab.badgeValue = badgeValue;
@@ -81,8 +74,14 @@
/>
{:else}
<Box>
<h3 class="text-3xl text-gray-500 dark:text-white">No slide added</h3>
<img alt="Slide not found" src="/notfound.webp" class="w-80" />
<div class="flex justify-between flex-col items-center w-96">
<img src="/images/empty-slide-icon.svg" alt="No Slide" class="my-2.5 mx-auto" />
<h2 class="text-xl my-1.5 font-normal">No slides yet</h2>
<p class="text-sm text-center text-slate-500">
Share your knowledge with the world by creating engaging slides. Add your slide's link
now.
</p>
</div>
</Box>
{/if}
</TabContent>
@@ -99,8 +98,13 @@
<MarkdownRender content={$lesson.materials.note} />
{:else}
<Box>
<h3 class="text-3xl text-gray-500 dark:text-white">No note added</h3>
<img alt="Lesson note not found" src="/notfound.webp" class="w-80" />
<div class="flex justify-between flex-col items-center w-96">
<img src="/images/empty-note-icon.svg" alt="No Note" class="my-2.5 mx-auto" />
<h2 class="text-xl my-1.5 font-normal">No Notes yet</h2>
<p class="text-sm text-center text-slate-500">
Share your knowledge with the world by creating engaging notes. Add your notes now.
</p>
</div>
</Box>
{/if}
</TabContent>
@@ -129,10 +133,14 @@
{/each}
{:else}
<Box>
<h3 class="text-3xl text-gray-500 dark:text-white">
No youtube video added
</h3>
<img alt="Video not found" src="/notfound.webp" class="w-80" />
<div class="flex justify-between flex-col items-center w-96">
<img src="/images/empty-video-icon.svg" alt="No Video" class="my-2.5 mx-auto" />
<h2 class="text-xl my-1.5 font-normal">No videos yet</h2>
<p class="text-sm text-center text-slate-500">
Share your knowledge with the world by creating engaging videos. Add your video link
now.
</p>
</div>
</Box>
{/if}
</TabContent>