Al responder "No" en las tres, el formulario salta a 6.4 (no muestra secciones 2-5 ni 6.1-6.3) La pregunta 6.6 aparece antes del cierre Las preguntas multiple_choice muestran el hint "Podés marcar más de una opción"
62 lines
2.0 KiB
TypeScript
62 lines
2.0 KiB
TypeScript
import type { ConditionalRule, FormAnswers, Question } from './types'
|
|
|
|
/** Returns true if the question should be shown given the current answers. */
|
|
export function isQuestionVisible(
|
|
question: Question,
|
|
answers: FormAnswers
|
|
): boolean {
|
|
const rules = question.conditional_rules
|
|
if (!rules || rules.length === 0) return true
|
|
// All rules must pass (AND semantics)
|
|
return rules.every((rule) => evaluateRule(rule, answers))
|
|
}
|
|
|
|
/** Normalizes if_question to an array of codes regardless of rule shape. */
|
|
export function ruleQuestionCodes(rule: ConditionalRule): string[] {
|
|
return Array.isArray(rule.if_question) ? rule.if_question : [rule.if_question]
|
|
}
|
|
|
|
function evaluateRule(rule: ConditionalRule, answers: FormAnswers): boolean {
|
|
if (rule.op === 'eq') {
|
|
return answers[rule.if_question as string] === rule.value
|
|
}
|
|
if (rule.op === 'eq_any') {
|
|
return ruleQuestionCodes(rule).some((code) => answers[code] === rule.value)
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Returns the codes of questions that will become hidden when `triggerCode`
|
|
* changes to `newValue`. Used to clear those answers reactively.
|
|
*/
|
|
export function getHiddenCodes(
|
|
triggerCode: string,
|
|
newValue: string | string[] | number | null,
|
|
questions: Question[],
|
|
currentAnswers: FormAnswers
|
|
): string[] {
|
|
const projected = { ...currentAnswers, [triggerCode]: newValue }
|
|
return questions
|
|
.filter((q) => {
|
|
if (!q.conditional_rules?.length) return false
|
|
const dependsOnTrigger = q.conditional_rules.some((r) =>
|
|
ruleQuestionCodes(r).includes(triggerCode)
|
|
)
|
|
if (!dependsOnTrigger) return false
|
|
return !isQuestionVisible(q, projected)
|
|
})
|
|
.map((q) => q.code)
|
|
}
|
|
|
|
/** All trigger codes in the survey (questions that have dependents). */
|
|
export function getTriggerCodes(questions: Question[]): Set<string> {
|
|
const triggers = new Set<string>()
|
|
for (const q of questions) {
|
|
for (const rule of q.conditional_rules ?? []) {
|
|
for (const code of ruleQuestionCodes(rule)) triggers.add(code)
|
|
}
|
|
}
|
|
return triggers
|
|
}
|