Complete questionnaire builder
This commit is contained in:
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user