+ {q.prompt &&
{q.prompt}
}
+ {q.options && q.options.length > 0 && (
+
+ {q.options.map((opt, i) => {
+ const isSelected = answer?.selected === opt.label;
+ return (
+
+ {opt.label ?? `option ${i + 1}`}
+
+ );
+ })}
+
+ )}
+ {answer?.custom_text && (
+
+ {answer.custom_text}
+
+ )}
+
+ );
+}
+
+// matchAnswerForQuestion accepts both response shapes the backend may emit:
+// keyed by question id (`{ q1: {...} }`) or as a positional list. The raw
+// `responses` value is read directly rather than via `pickObject`, because
+// the latter discards arrays and would silently lose list-shaped payloads.
+function matchAnswerForQuestion(
+ responses: unknown,
+ question: Question,
+ index: number,
+): AnswerEntry | undefined {
+ if (!responses || typeof responses !== "object") return undefined;
+ if (Array.isArray(responses)) return responses[index] as AnswerEntry | undefined;
+ if (question.id) {
+ const entry = (responses as Record