feat: let teamers fill in and read their questionnaire
This commit is contained in:
1 parent
2a041d25a0
commit
5e4e574076
11 files changed
+472
-2
No files matched your search
@@ -0,0 +1,74 @@
|
||||
import { Controller } from '@hotwired/stimulus'
|
||||
|
||||
/*
|
||||
* Shows a questionnaire question only while its show_if holds, mirroring
|
||||
* App\Model\Questionnaire\Definition::isVisible(): the condition must be met and the question it
|
||||
* depends on must itself be shown.
|
||||
*
|
||||
* Every question row carries data-question-key; a conditional one also data-show-if, the JSON
|
||||
* {question, operator, value} that App\Form\QuestionnaireType writes. A hidden row stays in the
|
||||
* form and is submitted: a draft keeps its answer, and the server drops it on submit.
|
||||
*/
|
||||
export default class extends Controller {
|
||||
|
||||
connect() {
|
||||
this.update()
|
||||
}
|
||||
|
||||
update() {
|
||||
const visible = {}
|
||||
|
||||
// Rows come in definition order, and a condition may only name an earlier question, so
|
||||
// the question a row depends on has always been decided by the time the row is reached.
|
||||
for (const row of this.element.querySelectorAll('[data-question-key]')) {
|
||||
const key = row.dataset.questionKey
|
||||
const condition = row.dataset.showIf ? JSON.parse(row.dataset.showIf) : null
|
||||
|
||||
visible[key] = null === condition
|
||||
|| (true === visible[condition.question] && this.isMet(condition))
|
||||
|
||||
row.hidden = false === visible[key]
|
||||
}
|
||||
}
|
||||
|
||||
isMet({ question, operator, value }) {
|
||||
const answer = this.answer(question)
|
||||
|
||||
if (null === answer) {
|
||||
return false
|
||||
}
|
||||
|
||||
switch (operator) {
|
||||
case 'equals':
|
||||
return answer === value
|
||||
case 'in':
|
||||
return value.includes(answer)
|
||||
case 'lte':
|
||||
return Number(answer) <= value
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
answer(key) {
|
||||
const row = this.element.querySelector(`[data-question-key="${key}"]`)
|
||||
|
||||
if (null === row) {
|
||||
return null
|
||||
}
|
||||
|
||||
const checked = row.querySelector('input[type="radio"]:checked')
|
||||
|
||||
if (null !== checked) {
|
||||
return checked.value
|
||||
}
|
||||
|
||||
const select = row.querySelector('select')
|
||||
|
||||
if (null !== select) {
|
||||
return '' === select.value ? null : select.value
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user