Questionnaire progress, preview questions, select answer
This commit is contained in:
@@ -5,9 +5,13 @@
|
||||
handleRemoveOption,
|
||||
handleRemoveQuestion,
|
||||
handleCode,
|
||||
handleAnswerSelect,
|
||||
} from "./store/index";
|
||||
import Delete24 from "carbon-icons-svelte/lib/Delete24";
|
||||
import AddFilled24 from "carbon-icons-svelte/lib/AddFilled24";
|
||||
import CheckmarkFilled24 from "carbon-icons-svelte/lib/CheckmarkFilled24";
|
||||
import CheckmarkOutline24 from "carbon-icons-svelte/lib/CheckmarkOutline24";
|
||||
// import Subtract24 from "carbon-icons-svelte/lib/Subtract24";
|
||||
|
||||
import TextField from "../../../../Form/TextField.svelte";
|
||||
import TextArea from "../../../../Form/TextArea.svelte";
|
||||
@@ -104,45 +108,71 @@
|
||||
{/if}
|
||||
|
||||
<div class="flex flex-col mt-2">
|
||||
{#each question.options as option}
|
||||
{#if QUESTION_TYPE.RADIO === question.type}
|
||||
{#if QUESTION_TYPE.RADIO === question.type}
|
||||
{#each question.options as option}
|
||||
<RadioItem
|
||||
isEditable={true}
|
||||
name={question.title || "radio-name"}
|
||||
bind:label={option.value}
|
||||
>
|
||||
<div slot="iconbutton">
|
||||
<div slot="iconbutton" class="flex items-center">
|
||||
<IconButton
|
||||
value={option.id}
|
||||
onClick={handleRemoveOption(question.id, option.id)}
|
||||
>
|
||||
<Delete24 class="carbon-icon" />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
value={option.id}
|
||||
onClick={handleAnswerSelect(question.id, option.id)}
|
||||
buttonClassName={question.answers.includes(option.id) &&
|
||||
"success"}
|
||||
>
|
||||
{#if question.answers.includes(option.id)}
|
||||
<CheckmarkFilled24 class="carbon-icon" />
|
||||
{:else}
|
||||
<CheckmarkOutline24 class="carbon-icon" />
|
||||
{/if}
|
||||
</IconButton>
|
||||
</div>
|
||||
</RadioItem>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
{#if QUESTION_TYPE.CHECKBOX === question.type}
|
||||
{#if QUESTION_TYPE.CHECKBOX === question.type}
|
||||
{#each question.options as option}
|
||||
<Checkbox
|
||||
isEditable={true}
|
||||
name={question || "checkbox-name"}
|
||||
bind:label={option.value}
|
||||
>
|
||||
<div slot="iconbutton">
|
||||
<div slot="iconbutton" class="flex items-center">
|
||||
<IconButton
|
||||
value={option.id}
|
||||
onClick={handleRemoveOption(question.id, option.id)}
|
||||
>
|
||||
<Delete24 class="carbon-icon" />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
value={option.id}
|
||||
onClick={handleAnswerSelect(question.id, option.id)}
|
||||
buttonClassName={question.answers.includes(option.id) &&
|
||||
"success"}
|
||||
>
|
||||
{#if question.answers.includes(option.id)}
|
||||
<CheckmarkFilled24 class="carbon-icon" />
|
||||
{:else}
|
||||
<CheckmarkOutline24 class="carbon-icon" />
|
||||
{/if}
|
||||
</IconButton>
|
||||
</div>
|
||||
</Checkbox>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
{#if QUESTION_TYPE.TEXTAREA === question.type}
|
||||
<TextArea bind:value={option.value} />
|
||||
{/if}
|
||||
{/each}
|
||||
{#if QUESTION_TYPE.TEXTAREA === question.type}
|
||||
<TextArea bind:value={question.value} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if QUESTION_TYPE.TEXTAREA !== question.type}
|
||||
|
||||
@@ -2,16 +2,19 @@
|
||||
import { questionnaire } from "./store/index";
|
||||
import RadioQuestion from "../../../../Question/RadioQuestion/index.svelte";
|
||||
import CheckboxQuestion from "../../../../Question/CheckboxQuestion/index.svelte";
|
||||
import TextareaQuestion from "../../../../Question/TextareaQuestion/index.svelte";
|
||||
import PrimaryButton from "../../../../PrimaryButton/index.svelte";
|
||||
import Progress from "../../../../Progress/index.svelte";
|
||||
|
||||
import { QUESTION_TYPE } from "../../../../Question/constants";
|
||||
|
||||
export let preview;
|
||||
|
||||
import {
|
||||
QUESTION_TYPE,
|
||||
QUESTION_TYPES,
|
||||
} from "../../../../Question/constants";
|
||||
import Checkbox from "../../../../Form/Checkbox.svelte";
|
||||
let answers = {};
|
||||
let currentQuestionIndex = 0;
|
||||
let currentQuestion = {};
|
||||
let renderProps = {};
|
||||
let progressValue = 0;
|
||||
|
||||
const { questions, title, description } = $questionnaire;
|
||||
|
||||
@@ -20,7 +23,7 @@
|
||||
}
|
||||
|
||||
function onSubmit(name, value) {
|
||||
if (!value) return;
|
||||
// if (!value) return;
|
||||
answers = {
|
||||
...answers,
|
||||
[name]: value,
|
||||
@@ -28,28 +31,81 @@
|
||||
currentQuestionIndex += 1;
|
||||
}
|
||||
|
||||
function onCheckboxSubmit(name, value) {
|
||||
if (!value) return;
|
||||
|
||||
answers = {
|
||||
...answers,
|
||||
[name]: value,
|
||||
};
|
||||
|
||||
currentQuestionIndex += 1;
|
||||
}
|
||||
|
||||
$: {
|
||||
currentQuestion = questions[currentQuestionIndex - 1];
|
||||
console.log("currentQuestion", currentQuestion);
|
||||
}
|
||||
|
||||
function onPrevious() {
|
||||
currentQuestionIndex -= 1;
|
||||
}
|
||||
|
||||
function getRenderProps(question, questionIndex) {
|
||||
return {
|
||||
title: questionIndex + ". " + question.title,
|
||||
name: `${question.id}`,
|
||||
options: question.options,
|
||||
code: question.code,
|
||||
defaultValue:
|
||||
question.type === QUESTION_TYPE.TEXTAREA
|
||||
? question.value || ""
|
||||
: answers[question.id] || [],
|
||||
onSubmit,
|
||||
onPrevious,
|
||||
disablePreviousButton: questionIndex === 1,
|
||||
isLast: questionIndex === questions.length,
|
||||
isPreview: preview,
|
||||
};
|
||||
}
|
||||
|
||||
function getProgressValue(currentQuestionIndex) {
|
||||
if (!currentQuestion) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
return (
|
||||
Math.round(((currentQuestionIndex - 1) / questions.length) * 100) || 0
|
||||
);
|
||||
}
|
||||
|
||||
$: {
|
||||
currentQuestion = questions[currentQuestionIndex - 1];
|
||||
|
||||
if (currentQuestion) {
|
||||
renderProps = getRenderProps(currentQuestion, currentQuestionIndex);
|
||||
}
|
||||
}
|
||||
|
||||
$: progressValue = getProgressValue(currentQuestionIndex);
|
||||
</script>
|
||||
|
||||
{#if currentQuestionIndex === 0}
|
||||
<!-- <svelte:window on:keydown={handleKeydown} /> -->
|
||||
|
||||
{#if !preview && currentQuestionIndex > 0}
|
||||
<Progress value={progressValue} />
|
||||
{/if}
|
||||
|
||||
{#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}
|
||||
<RadioQuestion
|
||||
{...getRenderProps(currentQuestion, currentQuestionIndex)}
|
||||
/>
|
||||
{:else if QUESTION_TYPE.CHECKBOX === currentQuestion.type}
|
||||
<CheckboxQuestion
|
||||
{...getRenderProps(currentQuestion, currentQuestionIndex)}
|
||||
/>
|
||||
{:else if QUESTION_TYPE.TEXTAREA === currentQuestion.type}
|
||||
<TextareaQuestion
|
||||
{...getRenderProps(currentQuestion, currentQuestionIndex)}
|
||||
/>
|
||||
{/if}
|
||||
{/each}
|
||||
{:else if currentQuestionIndex === 0}
|
||||
<div>
|
||||
<h2 class="my-1">{title}</h2>
|
||||
<p>{description}</p>
|
||||
@@ -66,27 +122,9 @@
|
||||
<code>{JSON.stringify(answers)}</code>
|
||||
</pre>
|
||||
{:else if QUESTION_TYPE.RADIO === currentQuestion.type}
|
||||
<RadioQuestion
|
||||
title={currentQuestionIndex + ". " + currentQuestion.title}
|
||||
name={`${currentQuestion.id}`}
|
||||
options={currentQuestion.options}
|
||||
code={currentQuestion.code}
|
||||
defaultValue={answers[`${currentQuestion.id}`] || false}
|
||||
{onSubmit}
|
||||
{onPrevious}
|
||||
disablePreviousButton={currentQuestionIndex === 1}
|
||||
isLast={currentQuestionIndex === questions.length}
|
||||
/>
|
||||
<RadioQuestion {...renderProps} />
|
||||
{:else if QUESTION_TYPE.CHECKBOX === currentQuestion.type}
|
||||
<CheckboxQuestion
|
||||
title={currentQuestionIndex + ". " + currentQuestion.title}
|
||||
name={`${currentQuestion.id}`}
|
||||
options={currentQuestion.options}
|
||||
code={currentQuestion.code}
|
||||
defaultValue={answers[currentQuestion.id] || []}
|
||||
onSubmit={onCheckboxSubmit}
|
||||
{onPrevious}
|
||||
disablePreviousButton={currentQuestionIndex === 1}
|
||||
isLast={currentQuestionIndex === questions.length}
|
||||
/>
|
||||
<CheckboxQuestion {...renderProps} />
|
||||
{:else if QUESTION_TYPE.TEXTAREA === currentQuestion.type}
|
||||
<TextareaQuestion {...renderProps} />
|
||||
{/if}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
label={mode === MODES.edit ? "Save" : "Edit"}
|
||||
onClick={() => (mode = mode === MODES.edit ? MODES.view : MODES.edit)}
|
||||
/>
|
||||
{#if mode === MODES.edit}
|
||||
{#if mode === MODES.edit || preview}
|
||||
<PrimaryButton
|
||||
variant={VARIANTS.OUTLINED}
|
||||
label={preview ? "Edit" : "Preview"}
|
||||
@@ -40,7 +40,7 @@
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
{#if mode === MODES.edit}
|
||||
{#if mode === MODES.edit && !preview}
|
||||
<EditMode />
|
||||
{:else}
|
||||
<ViewMode {preview} />
|
||||
|
||||
@@ -31,6 +31,7 @@ export const questionnaire = writable({
|
||||
value: "Traversy Media",
|
||||
},
|
||||
],
|
||||
answers: [],
|
||||
},
|
||||
{
|
||||
id: "vue-founder",
|
||||
@@ -59,6 +60,7 @@ export const questionnaire = writable({
|
||||
value: "Bill Gates",
|
||||
},
|
||||
],
|
||||
answers: [],
|
||||
},
|
||||
{
|
||||
id: "svelte-founder",
|
||||
@@ -82,6 +84,7 @@ export const questionnaire = writable({
|
||||
value: "Coding Train",
|
||||
},
|
||||
],
|
||||
answers: [2],
|
||||
},
|
||||
{
|
||||
id: "angular-founder",
|
||||
@@ -103,6 +106,7 @@ export function handleAddQuestion() {
|
||||
...QUESTION_TEMPLATE,
|
||||
id: questions.length + 1,
|
||||
value: "",
|
||||
answers: [],
|
||||
options: [
|
||||
{
|
||||
id: 1,
|
||||
@@ -151,11 +155,6 @@ export function handleRemoveOption(questionId, optionId) {
|
||||
...q,
|
||||
questions: questions.map((question) => {
|
||||
if (question.id === questionId) {
|
||||
console.log(
|
||||
"filter",
|
||||
optionId,
|
||||
question.options.filter((option) => option.id !== optionId)
|
||||
);
|
||||
return {
|
||||
...question,
|
||||
options: [
|
||||
@@ -194,7 +193,7 @@ export function handleCode(questionId, shouldAdd = true) {
|
||||
if (question.id === questionId) {
|
||||
return {
|
||||
...question,
|
||||
code: shouldAdd ? "" : undefined,
|
||||
code: shouldAdd ? (question.code || "") : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -203,3 +202,40 @@ export function handleCode(questionId, shouldAdd = true) {
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function handleAnswerSelect(questionId, optionId) {
|
||||
return () => {
|
||||
questionnaire.update((q) => {
|
||||
const { questions } = q;
|
||||
|
||||
return {
|
||||
...q,
|
||||
questions: questions.map((question) => {
|
||||
if (question.id === questionId) {
|
||||
const selectOption = question.options.find(option => option.id === optionId);
|
||||
const newAnswers = [];
|
||||
|
||||
if (question.answers.includes(selectOption.id)) {
|
||||
newAnswers.push(
|
||||
...question.answers.filter(answer => answer !== selectOption.id)
|
||||
)
|
||||
} else {
|
||||
newAnswers.push(
|
||||
...question.answers,
|
||||
selectOption.id
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
...question,
|
||||
answers: newAnswers
|
||||
};
|
||||
}
|
||||
|
||||
return question;
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user