questionnaire/assets/js/components/client/question.js

743 lines
40 KiB
JavaScript
Vendored

import m from "mithril"
import stream from "mithril/stream"
import _ from "lodash"
import powerform from "powerform"
import { required } from "validatex"
import { Card, TextField, RadioGroup, Button, Checkbox } from "polythene-mithril"
import Section from "../../models/Section"
import SectionQuestion from "../../models/SectionQuestion"
import Question from "../../models/Question"
import QuestionAnswer from "../../models/QuestionAnswer"
import Answer from "../../models/Answer"
import Respondent from "../../models/Respondent"
const text = {
form: powerform({
req: function(v) {
if (!v) {
return "Tuliskan jawaban Anda"
}
},
}),
oninit: function() {
var lS = {}
if (!_.isNil(window.localStorage.answers)) {
lS = _.find(JSON.parse(window.localStorage.answers), function(o) {
return o.id == SectionQuestion.current.data.id
})
}
text.form.req(_.isNil(lS) ? "" : lS.answers[0].text)
},
view: function(vnode) {
var attrs = vnode.attrs
var data = attrs.data || {}
return m(TextField, {
id: data.elId || "question" + SectionQuestion.current.data.id,
label: data.text || SectionQuestion.current.data.attributes.text,
floatingLabel: true,
help: SectionQuestion.current.data.attributes.description,
onChange: function(state) {
text.form.req(state.value)
},
validate: function() {
return {
valid: text.form.req.isValid(),
error: text.form.req.error()
}
},
value: text.form.req()
})
}
}
const choice = {
form: powerform({
req: function(v) {
if (!v) {
return "Pilih salah satu jawaban di bawah ini"
}
var fill = _.find(SectionQuestion.current.data.attributes.choices, function(o) {
return o.id == v
})
if (fill.fillable && !text.form.isValid()) {
return "Tuliskan jawaban Anda"
}
}
}),
oninit: function() {
var lS = {}
if (!_.isNil(window.localStorage.answers)) {
lS = _.find(JSON.parse(window.localStorage.answers), function(o) {
return o.id == SectionQuestion.current.data.id
})
}
choice.form.req(_.isNil(lS) ? "" : lS.answers[0].choice)
},
oncreate: function(vnode) {
SectionQuestion.current.data.attributes.choices.map(function(c) {
if (c.fillable) {
var child = document.createElement("span")
// child.style.marginTop = "1.4em"
var input = { view: function() {
return m(text, {
data: {
elId: "fillable-" + c.id,
text: "Tuliskan"
}
})
}}
/* Get parent */
var parent = document.getElementById("choice-" + c.id).childNodes[0]
parent.appendChild(child)
m.mount(parent.querySelector("span"), input)
if (!parent.querySelector("input").checked) {
document.getElementById("fillable-" + c.id).querySelector("input").disabled = true
}
}
document.getElementById("choice-" + c.id)
.childNodes[0].querySelector("input")
.required = true
})
},
view: function(vnode) {
return [
m("div", {
style: {
color: "rgba(0, 0, 0, .4)",
fontSize: "16px",
fontWeight: "400",
lineHeight: "24px",
marginTop: ".5em"
}
}, SectionQuestion.current.data.attributes.text + " *"),
m("i", {
style: {
color: "rgba(0, 0, 0, .4)"
}
}, "(" + SectionQuestion.current.data.attributes.description + ")" || null),
m(RadioGroup, {
id: "choices" + SectionQuestion.current.data.id,
all: {name: SectionQuestion.current.data.attributes.questionType},
className: "flex",
style: {
margin: ".5rem 0",
flexFlow: "row wrap"
},
buttons: SectionQuestion.current.data.attributes.choices.map(function(c) {
return {
id: "choice-" + c.id,
value: c.id,
label: c.text,
defaultChecked: c.id == choice.form.req(),
style: {
marginTop: ".5em",
marginBottom: ".5em",
marginRight: "0",
flexGrow: "1",
flexBasis: "100%"
}
}
}),
onChange: function(state) {
var chosen = _.find(SectionQuestion.current.data.attributes.choices, function(o) { return o.id == state.value })
var target = document.getElementById("fillable-" + chosen.id)
if (chosen.fillable) {
target.querySelector("input").disabled = false
target.querySelector("input").focus()
} else {
SectionQuestion.current.data.attributes.choices.map(function(c) {
var target = document.getElementById("fillable-" + c.id)
if (!_.isNil(target)) {
target.querySelector("input").disabled = true
text.form.req("")
}
})
}
choice.form.req(state.value)
}
})
]
}
}
const bool = {
form: powerform({
req: function(v) {
if (v == null || v == "") {
return "Pilih salah satu jawaban di bawah ini"
}
}
}),
oninit: function() {
var lS = {}
if (!_.isNil(window.localStorage.answers)) {
lS = _.find(JSON.parse(window.localStorage.answers), function(o) {
return o.id == SectionQuestion.current.data.id
})
}
bool.form.req(_.isNil(lS) ? "" : lS.answers[0].choice)
},
view: function() {
return [
m("div", {
style: {
color: "rgba(0, 0, 0, .4)",
fontSize: "16px",
fontWeight: "400",
lineHeight: "24px",
marginTop: ".5em"
}
}, SectionQuestion.current.data.attributes.text + " *"),
m("i", {
style: {
color: "rgba(0, 0, 0, .4)"
}
}, "(" + SectionQuestion.current.data.attributes.description + ")" || null),
m(RadioGroup, {
id: "bool" + SectionQuestion.current.data.id,
all: {name: SectionQuestion.current.data.attributes.questionType},
className: "flex",
style: {
margin: ".5rem 0",
flexFlow: "row wrap"
},
buttons: [{label: "Benar", value: 1}, {label: "Salah", value: 0}].map(function(o) {
return {
id: "true",
label: o.label,
value: o.value,
defaultChecked: o.value == SectionQuestion.current.data.attributes.answer.questionchoice_id,
style: {
marginTop: ".5em",
marginBottom: ".5em",
marginRight: "0",
flexGrow: "1",
flexBasis: "100%"
}
}
}),
onChange: function(state) {
bool.form.req(Boolean(state.value).toString())
}
})
]
}
}
const numeric = {
form: powerform({
req: function(v) {
if (v == null || v == "") {
return "Pertanyaan ini harus dijawab"
} else if (/[^\d]+/.test(v)) {
return "Gunakan angka"
}
}
}),
oninit: function() {
var lS = {}
if (!_.isNil(window.localStorage.answers)) {
lS = _.find(JSON.parse(window.localStorage.answers), function(o) {
return o.id == SectionQuestion.current.data.id
})
}
numeric.form.req(_.isNil(lS) ? "" : lS.answers[0].text)
},
view: function(vnode) {
var attrs = vnode.attrs
var data = attrs.data || {}
return m(TextField, {
id: data.elId || "question" + SectionQuestion.current.data.id,
label: SectionQuestion.current.data.attributes.text,
floatingLabel: true,
help: Section.current.data.attributes.description,
onChange: function(state) {
numeric.form.req(state.value)
},
validate: function() {
return {
valid: numeric.form.req.isValid(),
error: numeric.form.req.error()
}
},
value: numeric.form.req()
})
}
}
const multichoice = {
form: powerform({
req: function(v) {
if (_.isEmpty(v) || _.isNil(v)) {
return "Pilih minimal 1 jawaban"
}
var item = _.find(SectionQuestion.current.data.attributes.choices, function(o) {
return o.fillable
})
if (
_.find(v, function(o) { return o == item.id }) != undefined
&& _.isEmpty(document.getElementById("mfillable-" + item.id)
.querySelector("input").value)
) {
return "Tuliskan jawaban Anda"
}
}
}),
oninit: function() {
var lS = {}
if (!_.isNil(window.localStorage.answers)) {
lS = _.find(JSON.parse(window.localStorage.answers), function(o) {
return o.id == SectionQuestion.current.data.id
})
}
var choices = []
if (!_.isNil(lS)) {
for (var i = 0; i < lS.answers.length; i++) {
choices.push(lS.answers[i].choice)
}
}
multichoice.form.req(choices)
},
oncreate: function(vnode) {
SectionQuestion.current.data.attributes.choices.map(function(c) {
if (c.fillable) {
var child = document.createElement("span")
// child.style.marginTop = "1.4em"
var input = { view: function() {
return m(text, {
data: {
elId: "mfillable-" + c.id,
text: "Tuliskan",
float: false
}
})
}}
/* Get parent */
var parent = document.getElementById("mchoice-" + c.id).childNodes[0]
parent.appendChild(child)
m.mount(parent.querySelector("span"), input)
document.getElementById("mfillable-" + c.id).querySelector("input").disabled = true
}
})
},
view: function(vnode) {
var attrs = vnode.attrs
var data = attrs.data || {}
return [
m("div", {
style: {
color: "rgba(0, 0, 0, .4)",
fontSize: "16px",
fontWeight: "400",
lineHeight: "24px",
marginTop: ".5em"
}
}, SectionQuestion.current.data.attributes.text + " *"),
m("i", {
style: {
color: "rgba(0, 0, 0, .4)"
}
}, "(" + SectionQuestion.current.data.attributes.description + ")" || null),
m(".flex", {
style: {marginTop: "1em", marginBottom: "1em", flexFlow: "row wrap"}
}, SectionQuestion.current.data.attributes.choices.map(function(o) {
return m(Checkbox, {
style: {margin: ".5em 0"},
id: "mchoice-" + o.id,
label: o.text,
value: o.id,
defaultChecked: multichoice.form.req().indexOf(o.id) != -1,
onChange: function(state) {
var choices = multichoice.form.req()
if (state.checked) {
choices.push(state.value)
if (o.fillable) {
var target = document.getElementById("mfillable-" + o.id)
.querySelector("input")
target.disabled = false
target.focus()
}
} else {
var index = _.findIndex(choices, function(o) {
return o == state.value
})
choices.splice(index, 1)
if (o.fillable) {
var target = document.getElementById("mfillable-" + o.id)
.querySelector("input")
target.disabled = true
}
}
multichoice.form.req(choices)
}
})
}))
]
}
}
window.questionType = {text, choice, bool, numeric, multichoice}
const question = {
oninit: function(vnode) {
Respondent.fetch(1)
Section.fetch(vnode.attrs.id)
SectionQuestion.fetch(vnode.attrs.id)
},
view: function() {
return [
m(".header-img", {
style: {
backgroundImage: "url('img/head1.jpg')"
}
}),
m(".header-content", {
style: {top: 0}
}, m("article", {
style: {backgroundColor: "#fff", minHeight: "100vh"}
}, Section.loading ? null : [
m("h2.article-title", [
m("i.fa.fa-hashtag[aria-hidden=true]", {
style: {color: "rgb(255, 153, 0)", cursor: "pointer"},
onclick: function() {
m.route.set("/questionnaires/" + Section.current.data.attributes.questionnaire.id)
}
}),
m("div", {
style: {marginTop: ".3em"}
}, Section.current.data.attributes.title),
]),
_.isNil(Section.current.data.description) ? null : m("h6.article-title", "(" + Section.current.data.attributes.description + ")"),
SectionQuestion.loading ? null : m("h4.article-title", m("div", m("span", {style: {flexGrow: "1"}}, [
"Nomor: ",
m("input", {
placeholder: SectionQuestion.current.meta.pagination.current_page,
style: {
maxWidth: "3em",
minHeight: "3em"
},
maxlength: SectionQuestion.current.meta.pagination.total_pages.toString().length,
onchange: function(e) {
// if (e.keyCode == 13 || e.which == 13 || e.key == "Enter") {
var value = this.value
var question = _.find(Section.current.data.attributes.questions, function(o) {
return o.number == value
})
if (!_.isNil(question)) {
SectionQuestion.nextOrPrev(
SectionQuestion.current
.data.attributes.
section.links.self
+ "/questions?page=" + question.number
)
}
// }
}
}),
"/",
SectionQuestion.current.meta.pagination.total_pages
]))),
SectionQuestion.loading ? null : m(".flex", {
style: {flexFlow: "row wrap"}
}, m(".constant"), m(Card, {
style: {flexBasis: "80%"},
content: [
{
text: {
content: m("form#question-form", {
onsubmit: function(e) {
e.preventDefault()
}
}, [
m(window.questionType[SectionQuestion.current.data.attributes.questionType]),
m(".flex", [
m(Button, {
id: "prev",
label: [
m("i.fa.fa-chevron-left.fa-fw[aria-hidden=true]"),
m.trust("&nbsp;"),
"prev"
],
style: {
backgroundColor: "rgb(255, 153, 0)",
padding: ".8em",
fontSize: "14px",
lineHeight: "14px",
fontWeight: "500",
textTransform: "uppercase",
whiteSpace: "pre"
},
tone: "dark",
events: {
onclick: function() {
var qType =
SectionQuestion.current
.data.attributes
.questionType
if (window.questionType[qType].form.isValid()) {
var strQuestions = window.localStorage.getItem("answers")
var questions = JSON.parse(strQuestions) || []
var question = {
id: SectionQuestion.current.data.id,
answers: []
}
if (qType == "multichoice") {
var choices =
window.questionType[qType]
.form.req()
for (var i = 0; i < choices.length; i++) {
var answer = {}
answer.choice = choices[i]
answer.text =
window.questionType["text"]
.form.req()
answer.respondent = {
id: Respondent.current.data.id,
name: Respondent.current.data.attributes.name,
occupation: Respondent.current.data.attributes.occupation,
gender: Respondent.current.data.attributes.gender
}
answer.question = {
id: SectionQuestion.current.data.id,
text: SectionQuestion.current.data.attributes.text,
description: SectionQuestion.current.data.attributes.description,
section: {
id: Section.current.data.id,
title: Section.current.data.attributes.title,
description: Section.current.data.attributes.description
}
}
question.answers
.push(answer)
}
} else {
var answer = {
respondent: {
id: Respondent.current.data.id,
name: Respondent.current.data.attributes.name,
occupation: Respondent.current.data.attributes.occupation,
gender: Respondent.current.data.attributes.gender
},
question: {
id: SectionQuestion.current.data.id,
text: SectionQuestion.current.data.attributes.text,
description: SectionQuestion.current.data.attributes.description,
section: {
id: Section.current.data.id,
title: Section.current.data.attributes.title,
description: Section.current.data.attributes.description
}
}
}
if (qType == "choice" || qType == "bool") {
var choice = window.questionType[qType]
.form.req()
answer.choice = choice
answer.text = window.questionType["text"].form.req()
} else {
var text = window.questionType[qType]
.form.req()
answer.choice = null
answer.text = text
}
question.answers
.push(answer)
}
var dupIndex =
_.findIndex(questions, function(o) {
return o.id == SectionQuestion.current.data.id
})
if (dupIndex == -1) questions.push(question)
else questions[dupIndex] = question
window.localStorage
.setItem(
"answers",
JSON.stringify(questions)
)
}
if (!_.isNil(SectionQuestion.current.links.prev)) {
SectionQuestion.nextOrPrev(SectionQuestion.current.links.prev)
}
}
}
}),
m(".flex"),
!_.isNil(window.localStorage.getItem("answers"))
&& JSON.parse(window.localStorage.getItem("answers")).length
== SectionQuestion.current.meta.pagination.total
&& SectionQuestion.current.meta.pagination.current_page
== SectionQuestion.current.meta.pagination.total_pages ?
m(Button, {
id: "finish",
label: [
"finish",
m.trust("&nbsp;"),
m("i.fa.fa-check.fa-fw[aria-hidden=true]")
],
style: {
backgroundColor: "rgb(255, 153, 0)",
padding: ".8em",
fontSize: "14px",
lineHeight: "14px",
fontWeight: "500",
textTransform: "uppercase",
whiteSpace: "pre"
},
tone: "dark",
events: {
onclick: function() {
var arrAnswers = JSON.parse(window.localStorage.getItem("answers"))
// var answers = []
for (var i = 0; i < arrAnswers.length; i++) {
for (var o = 0; o < arrAnswers[i].answers.length; o++) {
// answers.push(arrAnswers[i].answers[o])
QuestionAnswer.current = arrAnswers[i].answers[o]
QuestionAnswer.upload(QuestionAnswer.current.question.id)
}
}
// console.log(answers);
console.log("finished");
}
}
})
: m(Button, {
id: "next",
label: [
"next",
m.trust("&nbsp;"),
m("i.fa.fa-chevron-right.fa-fw[aria-hidden=true]")
],
style: {
backgroundColor: "rgb(255, 153, 0)",
padding: ".8em",
fontSize: "14px",
lineHeight: "14px",
fontWeight: "500",
textTransform: "uppercase",
whiteSpace: "pre"
},
tone: "dark",
events: {
onclick: function() {
console.log(JSON.parse(window.localStorage.getItem("answers")).length);
var qType =
SectionQuestion.current
.data.attributes
.questionType
if (window.questionType[qType].form.isValid()) {
var strQuestions = window.localStorage.getItem("answers")
var questions = JSON.parse(strQuestions) || []
var question = {
id: SectionQuestion.current.data.id,
answers: []
}
if (qType == "multichoice") {
var choices =
window.questionType[qType]
.form.req()
for (var i = 0; i < choices.length; i++) {
var answer = {}
answer.choice = choices[i]
answer.text =
window.questionType["text"]
.form.req()
answer.respondent = {
id: Respondent.current.data.id,
name: Respondent.current.data.attributes.name,
occupation: Respondent.current.data.attributes.occupation,
gender: Respondent.current.data.attributes.gender
}
answer.question = {
id: SectionQuestion.current.data.id,
text: SectionQuestion.current.data.attributes.text,
description: SectionQuestion.current.data.attributes.description,
section: {
id: Section.current.data.id,
title: Section.current.data.attributes.title,
description: Section.current.data.attributes.description
}
}
question.answers
.push(answer)
}
} else {
var answer = {
respondent: {
id: Respondent.current.data.id,
name: Respondent.current.data.attributes.name,
occupation: Respondent.current.data.attributes.occupation,
gender: Respondent.current.data.attributes.gender
},
question: {
id: SectionQuestion.current.data.id,
text: SectionQuestion.current.data.attributes.text,
description: SectionQuestion.current.data.attributes.description,
section: {
id: Section.current.data.id,
title: Section.current.data.attributes.title,
description: Section.current.data.attributes.description
}
}
}
if (qType == "choice" || qType == "bool") {
var choice = window.questionType[qType]
.form.req()
answer.choice = choice
answer.text = window.questionType["text"].form.req()
} else {
var text = window.questionType[qType]
.form.req()
answer.choice = null
answer.text = text
}
question.answers
.push(answer)
}
var dupIndex =
_.findIndex(questions, function(o) {
return o.id == SectionQuestion.current.data.id
})
if (dupIndex == -1) questions.push(question)
else questions[dupIndex] = question
window.localStorage
.setItem(
"answers",
JSON.stringify(questions)
)
}
if (!_.isNil(SectionQuestion.current.links.next)) {
SectionQuestion.nextOrPrev(SectionQuestion.current.links.next)
}
}
}
})
])
])
}
}
]
}), m(".constant"))
]))
]
}
}
export default question