Complete questionnaire builder

This commit is contained in:
Ibitoye Rotimi Best
2021-07-06 08:39:17 +03:00
parent c4ed327d36
commit 946d99d273
17 changed files with 227 additions and 108 deletions
@@ -83,10 +83,10 @@
];
onMount(() => {
hotkeys("ctrl+b", function (event, handler) {
hotkeys("b", function (event, handler) {
event.preventDefault();
switch (handler.key) {
case "ctrl+b":
case "b":
show = !show;
break;
}
@@ -128,7 +128,7 @@
onClick={() => (show = !show)}
toolTipProps={{
title: "Toggle sidebar",
hotkeys: ["Ctrl", "B"],
hotkeys: ["B"],
direction: "right",
}}
>
@@ -5,7 +5,7 @@
import TextareaQuestion from "../../../../Question/TextareaQuestion/index.svelte";
import PrimaryButton from "../../../../PrimaryButton/index.svelte";
import Progress from "../../../../Progress/index.svelte";
import { removeDuplicate } from "../../../../../utils/functions/removeDuplicate";
import { QUESTION_TYPE } from "../../../../Question/constants";
export let preview;
@@ -15,6 +15,8 @@
let currentQuestion = {};
let renderProps = {};
let progressValue = 0;
let isAnswerCorrect;
let isFinished;
const { questions, title, description } = $questionnaire;
@@ -22,39 +24,98 @@
currentQuestionIndex += 1;
}
function onSubmit(name, value) {
// if (!value) return;
function onSubmit(id, value) {
const prevAnswer = answers[id] || [];
const formattedAnswer =
typeof value === "string"
? value
: removeDuplicate([...prevAnswer, ...(value || [])]);
answers = {
...answers,
[name]: value,
[id]: formattedAnswer,
};
currentQuestionIndex += 1;
if (isAnswerCorrect) {
currentQuestionIndex += 1;
}
}
function onPrevious() {
currentQuestionIndex -= 1;
}
function getRenderProps(question, questionIndex) {
function wasCorrectAnswerSelected(currentQuestion) {
const isOpenQuesiton = currentQuestion.type === QUESTION_TYPE.TEXTAREA;
if (isOpenQuesiton) {
isAnswerCorrect = true;
return true;
}
const answer = answers[currentQuestion.id];
const formattedAnswers = typeof answer === "string" ? [answer] : answer;
const options = currentQuestion.options;
isAnswerCorrect =
formattedAnswers &&
formattedAnswers.some((answer) => {
if (
!currentQuestion.answers?.length ||
currentQuestion.answers.includes(answer)
) {
return true;
}
return false;
});
return isAnswerCorrect;
}
function getRenderProps(question, questionIndex, answers) {
const isLast = questionIndex === questions.length;
const isOpenQuesiton = question.type === QUESTION_TYPE.TEXTAREA;
return {
title: questionIndex + ". " + question.title,
name: `${question.id}`,
options: question.options,
answers: question.answers,
code: question.code,
defaultValue:
question.type === QUESTION_TYPE.TEXTAREA
? question.value || ""
: answers[question.id] || [],
defaultValue: isOpenQuesiton
? answers[question.id] || ""
: answers[question.id] || [],
onSubmit,
onPrevious,
disablePreviousButton: questionIndex === 1,
isLast: questionIndex === questions.length,
isPreview: preview,
isLast,
isPreview: preview || isFinished,
disabled: wasCorrectAnswerSelected(question) && isFinished,
nextButtonProps: isLast
? {
label: "Finish",
isActive: true,
}
: isOpenQuesiton
? {
label: "Next",
isActive: true,
}
: wasCorrectAnswerSelected(question)
? {
label: "Next",
isActive: true,
disableOptionSelect: true,
}
: {
label: "Check",
isActive: false,
},
};
}
function getProgressValue(currentQuestionIndex) {
if (!currentQuestion) {
if (isFinished) {
return 100;
}
@@ -65,9 +126,16 @@
$: {
currentQuestion = questions[currentQuestionIndex - 1];
if (currentQuestionIndex > 0 && !currentQuestion) {
isFinished = true;
}
if (currentQuestion) {
renderProps = getRenderProps(currentQuestion, currentQuestionIndex);
renderProps = getRenderProps(
currentQuestion,
currentQuestionIndex,
answers
);
}
}
@@ -82,26 +150,17 @@
{#if preview}
{#each questions as currentQuestion, currentQuestionIndex}
{#if currentQuestionIndex === 0}
<div class="mb-2">
<h2 class="my-1">{title}</h2>
<p>{description}</p>
</div>
{:else if !currentQuestion}
<pre>
<code>{JSON.stringify(answers)}</code>
</pre>
{:else if QUESTION_TYPE.RADIO === currentQuestion.type}
{#if QUESTION_TYPE.RADIO === currentQuestion.type}
<RadioQuestion
{...getRenderProps(currentQuestion, currentQuestionIndex)}
{...getRenderProps(currentQuestion, currentQuestionIndex + 1, answers)}
/>
{:else if QUESTION_TYPE.CHECKBOX === currentQuestion.type}
<CheckboxQuestion
{...getRenderProps(currentQuestion, currentQuestionIndex)}
{...getRenderProps(currentQuestion, currentQuestionIndex + 1, answers)}
/>
{:else if QUESTION_TYPE.TEXTAREA === currentQuestion.type}
<TextareaQuestion
{...getRenderProps(currentQuestion, currentQuestionIndex)}
{...getRenderProps(currentQuestion, currentQuestionIndex + 1, answers)}
/>
{/if}
{/each}
@@ -117,10 +176,23 @@
type="button"
/>
</div>
{:else if !currentQuestion}
<pre>
<code>{JSON.stringify(answers)}</code>
</pre>
{:else if isFinished}
<h2 class="text-lg">Congratulations you have completed your task</h2>
{#each questions as currentQuestion, currentQuestionIndex}
{#if QUESTION_TYPE.RADIO === currentQuestion.type}
<RadioQuestion
{...getRenderProps(currentQuestion, currentQuestionIndex + 1, answers)}
/>
{:else if QUESTION_TYPE.CHECKBOX === currentQuestion.type}
<CheckboxQuestion
{...getRenderProps(currentQuestion, currentQuestionIndex + 1, answers)}
/>
{:else if QUESTION_TYPE.TEXTAREA === currentQuestion.type}
<TextareaQuestion
{...getRenderProps(currentQuestion, currentQuestionIndex + 1, answers)}
/>
{/if}
{/each}
{:else if QUESTION_TYPE.RADIO === currentQuestion.type}
<RadioQuestion {...renderProps} />
{:else if QUESTION_TYPE.CHECKBOX === currentQuestion.type}
@@ -11,27 +11,27 @@ export const questionnaire = writable({
questions: [
{
id: "react-founder",
type: QUESTION_TYPE.RADIO,
type: QUESTION_TYPE.CHECKBOX,
title: "Who is the creator of React.js",
options: [
{
id: 1,
id: "1",
value: "Dan Abrahmov",
},
{
id: 2,
id: "2",
value: "Google",
},
{
id: 3,
id: "3",
value: "Facebook",
},
{
id: 4,
id: "4",
value: "Traversy Media",
},
],
answers: [],
answers: ['3'],
},
{
id: "vue-founder",
@@ -44,47 +44,47 @@ export const questionnaire = writable({
`,
options: [
{
id: 1,
id: "1",
value: "Evan Vue",
},
{
id: 2,
id: "2",
value: "Mark Zukerberg",
},
{
id: 3,
id: "3",
value: "Prince Charles",
},
{
id: 4,
id: "4",
value: "Bill Gates",
},
],
answers: [],
answers: ['3'],
},
{
id: "svelte-founder",
type: QUESTION_TYPE.CHECKBOX,
type: QUESTION_TYPE.RADIO,
title: "Who is the creator of Svelte.js",
options: [
{
id: 1,
id: "1",
value: "Hillary Svelte",
},
{
id: 2,
id: "2",
value: "Mircosoft",
},
{
id: 3,
id: "3",
value: "Elevate",
},
{
id: 4,
id: "4",
value: "Coding Train",
},
],
answers: [2],
answers: ["2"],
},
{
id: "angular-founder",
@@ -109,7 +109,7 @@ export function handleAddQuestion() {
answers: [],
options: [
{
id: 1,
id: "1",
value: null,
},
],
@@ -215,7 +215,9 @@ export function handleAnswerSelect(questionId, optionId) {
const selectOption = question.options.find(option => option.id === optionId);
const newAnswers = [];
if (question.answers.includes(selectOption.id)) {
if (question.type === QUESTION_TYPE.RADIO) {
newAnswers.push(optionId)
} else if (question.answers.includes(selectOption.id)) {
newAnswers.push(
...question.answers.filter(answer => answer !== selectOption.id)
)
@@ -1,5 +1,4 @@
<script>
import { onMount } from "svelte";
import PageNav from "../../../PageNav/index.svelte";
import Classwork from "./Classwork.svelte";
import Homework from "./Homework/index.svelte";
@@ -9,10 +8,6 @@
export let path;
export let tab;
export let showLectureHome;
onMount(() => {
console.log("mounted");
});
</script>
{#if showLectureHome}
@@ -1,2 +0,0 @@
import { writable } from "svelte/store";