Code snippet, better UX in questionnaire
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
import {
|
||||
questionnaire,
|
||||
handleAddOption,
|
||||
handleAddQuestion,
|
||||
handleRemoveOption,
|
||||
handleRemoveQuestion,
|
||||
handleCode,
|
||||
} from "./store/index";
|
||||
import Delete24 from "carbon-icons-svelte/lib/Delete24";
|
||||
import AddFilled24 from "carbon-icons-svelte/lib/AddFilled24";
|
||||
@@ -14,9 +14,10 @@
|
||||
import Checkbox from "../../../../Form/Checkbox.svelte";
|
||||
import RadioItem from "../../../../Form/RadioItem.svelte";
|
||||
import IconButton from "../../../../IconButton/index.svelte";
|
||||
import Select from "../../../../Form/Select.svelte";
|
||||
import PrimaryButton from "../../../../PrimaryButton/index.svelte";
|
||||
import Dropdown from "../../../../Dropdown/index.svelte";
|
||||
import { VARIANTS } from "../../../../PrimaryButton/constants";
|
||||
import Select from "../../../../Form/Select.svelte";
|
||||
import QuestionContainer from "../../../../QuestionContainer/index.svelte";
|
||||
import {
|
||||
QUESTION_TYPE,
|
||||
@@ -26,39 +27,83 @@
|
||||
// import readme from "../../readme.js";
|
||||
|
||||
// let value = readme;
|
||||
const extraActions = ["Code Snippets", "Upload image"];
|
||||
const initialQuestionsLength = $questionnaire.questions.length;
|
||||
|
||||
function shouldScrollToLast(index, questions) {
|
||||
const currentQuestionsLength = questions.length;
|
||||
const isLast = index + 1 === currentQuestionsLength;
|
||||
|
||||
return isLast && initialQuestionsLength !== currentQuestionsLength;
|
||||
}
|
||||
|
||||
function handleOptionClick(questionIndex) {
|
||||
return (actionIndex) => {
|
||||
switch (actionIndex) {
|
||||
case 0:
|
||||
handleCode(questionIndex, true);
|
||||
break;
|
||||
case 1:
|
||||
// uploadImage(questionIndex);
|
||||
break;
|
||||
default:
|
||||
console.log("No option");
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="root relative">
|
||||
<div class="head flex bg-white items-center justify-between sticky right-0">
|
||||
<h3>Home task</h3>
|
||||
<PrimaryButton
|
||||
variant={VARIANTS.OUTLINED}
|
||||
onClick={handleAddQuestion}
|
||||
label="Add Question"
|
||||
mnb
|
||||
v
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="w-auto m-auto">
|
||||
<QuestionContainer isTitle={true}>
|
||||
<TextField placeholder="Title" bind:value={$questionnaire.title} />
|
||||
|
||||
<TextField
|
||||
placeholder="Title"
|
||||
bind:value={$questionnaire.title}
|
||||
className="mb-2"
|
||||
/>
|
||||
<TextArea
|
||||
placeholder="Description and Rules"
|
||||
bind:value={$questionnaire.description}
|
||||
/>
|
||||
</QuestionContainer>
|
||||
|
||||
{#each $questionnaire.questions as question}
|
||||
<QuestionContainer onClose={handleRemoveQuestion(question.id)}>
|
||||
<div class="flex justify-between">
|
||||
{#each $questionnaire.questions as question, index}
|
||||
<QuestionContainer
|
||||
onClose={handleRemoveQuestion(question.id)}
|
||||
scrollToQuestion={shouldScrollToLast(index, $questionnaire.questions)}
|
||||
>
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="mr-2 w-3/5">
|
||||
<TextField placeholder="Question" bind:value={question.title} />
|
||||
</div>
|
||||
|
||||
<Dropdown
|
||||
options={extraActions}
|
||||
handleOptionClick={handleOptionClick(question.id)}
|
||||
>
|
||||
<AddFilled24 class="carbon-icon" />
|
||||
<p class="ml-2 text-gray-600">Add</p>
|
||||
</Dropdown>
|
||||
|
||||
<Select bind:value={question.type} options={QUESTION_TYPES} />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col">
|
||||
{#if typeof question.code === "string"}
|
||||
<div class="flex justify-between items-center my-3 w-3/5">
|
||||
<TextArea
|
||||
bind:value={question.code}
|
||||
rows="2"
|
||||
placeholder="Write your code"
|
||||
/>
|
||||
<IconButton
|
||||
value="write-code"
|
||||
onClick={() => handleCode(question.id, false)}
|
||||
>
|
||||
<Delete24 class="carbon-icon" />
|
||||
</IconButton>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex flex-col mt-2">
|
||||
{#each question.options as option}
|
||||
{#if QUESTION_TYPE.RADIO === question.type}
|
||||
<RadioItem
|
||||
@@ -86,7 +131,7 @@
|
||||
<div slot="iconbutton">
|
||||
<IconButton
|
||||
value={option.id}
|
||||
onClick={handleRemoveOption(question.id)}
|
||||
onClick={handleRemoveOption(question.id, option.id)}
|
||||
>
|
||||
<Delete24 class="carbon-icon" />
|
||||
</IconButton>
|
||||
@@ -101,24 +146,18 @@
|
||||
</div>
|
||||
|
||||
{#if QUESTION_TYPE.TEXTAREA !== question.type}
|
||||
<div class="flex items-center">
|
||||
<IconButton onClick={handleAddOption(question.id)}>
|
||||
<div class="flex items-center mt-3">
|
||||
<PrimaryButton
|
||||
disablePadding={true}
|
||||
className="p-2"
|
||||
variant={VARIANTS.OUTLINED}
|
||||
onClick={handleAddOption(question.id)}
|
||||
>
|
||||
<AddFilled24 class="carbon-icon" />
|
||||
</IconButton>
|
||||
<p class="italic">Add option</p>
|
||||
<p class="ml-2">Add option</p>
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
{/if}
|
||||
</QuestionContainer>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.root {
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
.head {
|
||||
top: 63px;
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
<script>
|
||||
import { questionnaire } from "./store/index";
|
||||
// import RadioQuestion from "../../../../Question/RadioQuestion/index.svelte";
|
||||
import RadioQuestion from "../../../../Question/RadioQuestion/index.svelte";
|
||||
import CheckboxQuestion from "../../../../Question/CheckboxQuestion/index.svelte";
|
||||
import PrimaryButton from "../../../../PrimaryButton/index.svelte";
|
||||
|
||||
import {
|
||||
QUESTION_TYPE,
|
||||
QUESTION_TYPES,
|
||||
} from "../../../../Question/constants";
|
||||
import Checkbox from "../../../../Form/Checkbox.svelte";
|
||||
let answers = {};
|
||||
let currentQuestionIndex = 0;
|
||||
let currentQuestion = {};
|
||||
@@ -34,7 +39,10 @@
|
||||
currentQuestionIndex += 1;
|
||||
}
|
||||
|
||||
$: currentQuestion = questions[currentQuestionIndex - 1];
|
||||
$: {
|
||||
currentQuestion = questions[currentQuestionIndex - 1];
|
||||
console.log("currentQuestion", currentQuestion);
|
||||
}
|
||||
|
||||
function onPrevious() {
|
||||
currentQuestionIndex -= 1;
|
||||
@@ -43,7 +51,7 @@
|
||||
|
||||
{#if currentQuestionIndex === 0}
|
||||
<div>
|
||||
<h2>{title}</h2>
|
||||
<h2 class="my-1">{title}</h2>
|
||||
<p>{description}</p>
|
||||
|
||||
<PrimaryButton
|
||||
@@ -57,21 +65,24 @@
|
||||
<pre>
|
||||
<code>{JSON.stringify(answers)}</code>
|
||||
</pre>
|
||||
{:else}
|
||||
<!-- <RadioQuestion
|
||||
{:else if QUESTION_TYPE.RADIO === currentQuestion.type}
|
||||
<RadioQuestion
|
||||
title={currentQuestionIndex + ". " + currentQuestion.title}
|
||||
name={currentQuestion.name}
|
||||
name={`${currentQuestion.id}`}
|
||||
options={currentQuestion.options}
|
||||
defaultValue={answers[currentQuestion.name] || false}
|
||||
code={currentQuestion.code}
|
||||
defaultValue={answers[`${currentQuestion.id}`] || false}
|
||||
{onSubmit}
|
||||
{onPrevious}
|
||||
disablePreviousButton={currentQuestionIndex === 1}
|
||||
isLast={currentQuestionIndex === questions.length}
|
||||
/> -->
|
||||
/>
|
||||
{: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}
|
||||
|
||||
@@ -1,25 +1,48 @@
|
||||
<script>
|
||||
import PrimaryContainedButton from "../../../../PrimaryContainedButton/index.svelte";
|
||||
import { handleAddQuestion } from "./store/index";
|
||||
import PrimaryButton from "../../../../PrimaryButton/index.svelte";
|
||||
import PageBody from "../../../../PageBody/index.svelte";
|
||||
import EditMode from "./EditMode.svelte";
|
||||
import ViewMode from "./ViewMode.svelte";
|
||||
import MODES from "../../../../../utils/constants/mode.js";
|
||||
import { VARIANTS } from "../../../../PrimaryButton/constants";
|
||||
|
||||
let mode = MODES.view;
|
||||
let preview = false;
|
||||
</script>
|
||||
|
||||
<PageBody>
|
||||
<svelte:fragment slot="header">
|
||||
<h3>Lesson 2 home exercises</h3>
|
||||
<PrimaryContainedButton
|
||||
label={mode === MODES.edit ? "Save" : "Edit"}
|
||||
handleClick={() => (mode = mode === MODES.edit ? MODES.view : MODES.edit)}
|
||||
/>
|
||||
<div class="flex items-center">
|
||||
<PrimaryButton
|
||||
className="mr-2"
|
||||
variant={VARIANTS.OUTLINED}
|
||||
label={mode === MODES.edit ? "Save" : "Edit"}
|
||||
onClick={() => (mode = mode === MODES.edit ? MODES.view : MODES.edit)}
|
||||
/>
|
||||
{#if mode === MODES.edit}
|
||||
<PrimaryButton
|
||||
variant={VARIANTS.OUTLINED}
|
||||
label={preview ? "Edit" : "Preview"}
|
||||
onClick={() => (preview = !preview)}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if mode === MODES.edit}
|
||||
<div class="flex items-center">
|
||||
<PrimaryButton
|
||||
variant={VARIANTS.OUTLINED}
|
||||
onClick={handleAddQuestion}
|
||||
label="Add Question"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
{#if mode === MODES.edit}
|
||||
<EditMode />
|
||||
{:else}
|
||||
<ViewMode />
|
||||
<ViewMode {preview} />
|
||||
{/if}
|
||||
</PageBody>
|
||||
|
||||
@@ -11,19 +11,23 @@ export const questionnaire = writable({
|
||||
questions: [
|
||||
{
|
||||
id: "react-founder",
|
||||
type: QUESTION_TYPE.CHECKBOX,
|
||||
type: QUESTION_TYPE.RADIO,
|
||||
title: "Who is the creator of React.js",
|
||||
options: [
|
||||
{
|
||||
id: 1,
|
||||
value: "Dan Abrahmov",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: "Google",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
value: "Facebook",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
value: "Traversy Media",
|
||||
},
|
||||
],
|
||||
@@ -32,17 +36,26 @@ export const questionnaire = writable({
|
||||
id: "vue-founder",
|
||||
type: QUESTION_TYPE.CHECKBOX,
|
||||
title: "Who is the creator of Vue.js",
|
||||
code: `const name = 'Josh Perez';\nconst element = <h1>Hello, {name}</h1>;\n\nReactDOM.render(\n
|
||||
element,\,
|
||||
document.getElementById('root')
|
||||
)
|
||||
`,
|
||||
options: [
|
||||
{
|
||||
id: 1,
|
||||
value: "Evan Vue",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: "Mark Zukerberg",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
value: "Prince Charles",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
value: "Bill Gates",
|
||||
},
|
||||
],
|
||||
@@ -53,34 +66,28 @@ export const questionnaire = writable({
|
||||
title: "Who is the creator of Svelte.js",
|
||||
options: [
|
||||
{
|
||||
id: 1,
|
||||
value: "Hillary Svelte",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: "Mircosoft",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
value: "Elevate",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
value: "Coding Train",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "angular-founder",
|
||||
type: QUESTION_TYPE.CHECKBOX,
|
||||
type: QUESTION_TYPE.TEXTAREA,
|
||||
title: "Who is the creator of Angular.js",
|
||||
options: [
|
||||
{
|
||||
value: "Laryy page",
|
||||
},
|
||||
{
|
||||
value: "Google",
|
||||
},
|
||||
{
|
||||
value: "Sales Force",
|
||||
},
|
||||
],
|
||||
value: "",
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -95,6 +102,7 @@ export function handleAddQuestion() {
|
||||
{
|
||||
...QUESTION_TEMPLATE,
|
||||
id: questions.length + 1,
|
||||
value: "",
|
||||
options: [
|
||||
{
|
||||
id: 1,
|
||||
@@ -120,7 +128,7 @@ export function handleAddOption(questionId) {
|
||||
options: [
|
||||
...question.options,
|
||||
{
|
||||
id: question.options.length + 1,
|
||||
id: question.options[question.options.length - 1].id + 1,
|
||||
value: "",
|
||||
},
|
||||
],
|
||||
@@ -143,6 +151,11 @@ 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: [
|
||||
@@ -170,3 +183,23 @@ export function handleRemoveQuestion(questionId) {
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function handleCode(questionId, shouldAdd = true) {
|
||||
questionnaire.update((q) => {
|
||||
const { questions } = q;
|
||||
|
||||
return {
|
||||
...q,
|
||||
questions: questions.map((question) => {
|
||||
if (question.id === questionId) {
|
||||
return {
|
||||
...question,
|
||||
code: shouldAdd ? "" : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
return question;
|
||||
}),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user