fix: preserve multi-select choices with custom answers

This commit is contained in:
Erik Kotsiuba
2026-04-19 16:32:27 +02:00
parent 4a131f7752
commit 8d8e7b67c9
8 changed files with 157 additions and 14 deletions
+6 -2
View File
@@ -37,19 +37,23 @@ function formatAnswerLine(
answer: AskResult["answers"][string],
mode: "summary" | "render"
): string | undefined {
const answerText = answer.customText ?? answer.labels.join(", ");
const answerText = answer.labels.join(", ");
if (!answerText) {
return;
}
if (mode === "summary") {
return `${questionLabel}: ${answerText}`;
}
if (answer.customText) {
if (isCustomOnlyAnswer(answer)) {
return `✓ ${questionLabel}: (wrote) ${answerText}`;
}
return `✓ ${questionLabel}: ${answerText}`;
}
function isCustomOnlyAnswer(answer: AskResult["answers"][string]): boolean {
return answer.indices.length === 0 && !!answer.customText;
}
function formatQuestionNoteLine(
questionLabel: string,
note: string | undefined,
+13 -9
View File
@@ -35,7 +35,6 @@ export function toggleSelection(
index: number
): AskStateAnswer {
const next = cloneAnswer(answer);
next.customText = undefined;
const selectedIndex = next.selected.findIndex(
(selection) => selection.value === option.value
);
@@ -74,11 +73,14 @@ export function setSingleSelection(
export function saveCustomText(
answer: AskStateAnswer,
rawValue: string
rawValue: string,
mode: "single" | "multi"
): AskStateAnswer {
const trimmed = rawValue.trim();
const next = cloneAnswer(answer);
next.selected = [];
if (mode === "single") {
next.selected = [];
}
if (!trimmed) {
next.customText = undefined;
return next;
@@ -143,12 +145,14 @@ export function isOptionSelected(
}
export function serializeAnswer(answer: AskStateAnswer): AskResultAnswer {
const values = answer.customText
? [answer.customText]
: answer.selected.map((selection) => selection.value);
const labels = answer.customText
? [answer.customText]
: answer.selected.map((selection) => selection.label);
const values = [
...answer.selected.map((selection) => selection.value),
...(answer.customText ? [answer.customText] : []),
];
const labels = [
...answer.selected.map((selection) => selection.label),
...(answer.customText ? [answer.customText] : []),
];
const indices = answer.selected.map((selection) => selection.index);
const selectedNotes = answer.optionNotes
? Object.fromEntries(
+6 -1
View File
@@ -258,7 +258,12 @@ function saveInputValue(
const nextState = updateAnswer(
exitEditingView(state),
question.id,
(answer) => saveCustomText(answer, rawValue)
(answer) =>
saveCustomText(
answer,
rawValue,
question.type === "multi" ? "multi" : "single"
)
);
if (!(submit && isAnswerAnswered(nextState.answers[question.id]))) {
return nextState;
+6 -2
View File
@@ -64,14 +64,14 @@ function renderSubmittedAnswer(
theme: Theme,
width: number
) {
const answerText = answer.customText ?? answer.labels.join(", ");
const answerText = answer.labels.join(", ");
if (answerText) {
pushWrappedText(
lines,
`→ ${answerText}`,
width,
theme,
answer.customText ? "text" : "success",
isCustomOnlyAnswer(answer) ? "text" : "success",
" ",
" "
);
@@ -106,6 +106,10 @@ function renderSubmittedAnswer(
}
}
function isCustomOnlyAnswer(answer: AskResult["answers"][string]): boolean {
return answer.indices.length === 0 && !!answer.customText;
}
function renderSubmitActions(
lines: string[],
state: AskState,