import { ref } from "vue";
import type { Question } from "@/dialogs/types";
export interface QuestionState {
selectedOptions: Set<string>;
otherText: string;
showOther: boolean;
}
export interface SelectionInitResult {
hasInvalidOptionCount: boolean;
}
/**
* 管理问卷每个问题的选项状态,抽离自主组件逻辑,便于复用与测试。
*/
export function useSelectionState() {
const questionStates = ref<Map<string, QuestionState>>(new Map());
const hasInvalidOptionCount = ref(false);
function initialize(questions: Question[]) {
hasInvalidOptionCount.value = false;
const states = new Map<string, QuestionState>();
for (const q of questions) {
if (q.options.length < 2) {
hasInvalidOptionCount.value = true;
}
states.set(q.question, {
selectedOptions: new Set(),
otherText: "",
showOther: false,
});
}
questionStates.value = states;
}
function toggleOption(questionText: string, label: string, multiSelect: boolean) {
const state = questionStates.value.get(questionText);
if (!state) return;
if (multiSelect) {
if (state.selectedOptions.has(label)) {
state.selectedOptions.delete(label);
} else {
state.selectedOptions.add(label);
}
} else {
state.selectedOptions.clear();
state.selectedOptions.add(label);
}
if (label !== "__other__") {
state.showOther = false;
state.otherText = "";
}
}
function showOtherInput(questionText: string, multiSelect: boolean) {
const state = questionStates.value.get(questionText);
if (!state) return;
state.showOther = true;
if (!multiSelect) {
state.selectedOptions.clear();
}
}
function isOptionSelected(questionText: string, label: string): boolean {
const state = questionStates.value.get(questionText);
return state ? state.selectedOptions.has(label) : false;
}
function isQuestionAnswered(questionText: string): boolean {
const state = questionStates.value.get(questionText);
if (!state) return false;
const hasSelectedOption = state.selectedOptions.size > 0;
const hasOtherText = state.showOther && state.otherText.trim();
return hasSelectedOption || !!hasOtherText;
}
function getQuestionAnswer(questionText: string, unansweredLabel: string): string {
const state = questionStates.value.get(questionText);
if (!state) return unansweredLabel;
const selectedLabels = Array.from(state.selectedOptions);
const hasOtherText = state.showOther && state.otherText.trim();
const allAnswers = [...selectedLabels];
if (hasOtherText) {
allAnswers.push(state.otherText.trim());
}
return allAnswers.join(", ") || unansweredLabel;
}
function getAnsweredCount(questions: Question[]): number {
let answered = 0;
for (const q of questions) {
if (isQuestionAnswered(q.question)) {
answered++;
}
}
return answered;
}
return {
questionStates,
hasInvalidOptionCount,
initialize,
toggleOption,
showOtherInput,
isOptionSelected,
isQuestionAnswered,
getQuestionAnswer,
getAnsweredCount,
};
}