import { Survey } from '../entities/index.js' import { fetchQuestions } from '../services/index.js' import { allSteps, promptOverrides, promptToComponent, inputPlaceholders, invalidInputPrompts, possible, aspectsArr, } from './lang.js' /** * Make a step from match or step information * @param {object} match * @param {object} step * @returns something like a response_key with possible responses */ const formatStep = (match, step) => { const responsesByCategory = possible['usa'] const responseKey = { response_key_id: match ? match.response_key_id : null, response_key_category: match ? match.response_key_category : 'profile', response_key_prompt: match ? match.response_key_prompt : step, response_key_description: match ? match.response_key_description : null, } // Embarassing hack const uglyMatch = step.split('-') if (uglyMatch.length > 1 && uglyMatch[0] == 'aspect') { responseKey.aspect = match.response_key_category responseKey.category = 'aspect' } return { ...responseKey, responses: responsesByCategory[step] ? responsesByCategory[step] : [], } } const associateWithComponent = responseKeyLike => { let component = promptToComponent[responseKeyLike.response_key_prompt] // Embarassing hack if (responseKeyLike.category == 'aspect') { component = promptToComponent[responseKeyLike.category] } return { ...responseKeyLike, component } } const hasMatch = (step, inArray) => { const uglyMatch = step.split('-') // Embarassing hack if (uglyMatch.length > 1 && uglyMatch[0] == 'aspect') { return inArray.find(q => q.response_key_id == uglyMatch[1]) } else { return inArray.find(q => q.response_key_prompt == step) } } class SurveyFactory { constructor() { this.questionsFromDb = [] } _setSteps(langFile) { const stepsToProcess = [...Object.values(langFile)] const seenIds = [] const stepsInCommon = stepsToProcess.map(step => { // Match question to step const match = hasMatch(step, this.questionsFromDb) if (match) { seenIds.push(match.response_key_id) } // Reformat something from the db into something the gui likes const responseKeyLike = formatStep(match, step) // Lookup a matching component const withComponent = associateWithComponent(responseKeyLike) // Mutate the object with extra stuff const langStub = responseKeyLike.response_key_prompt withComponent.survey_stage = langStub if (promptOverrides[responseKeyLike.response_key_prompt]) { withComponent.response_key_prompt = promptOverrides[langStub] withComponent.placeholder = inputPlaceholders[langStub] withComponent.invalidInputPrompt = invalidInputPrompts[langStub] } else { console.warn( `WARN: ${withComponent.survey_stage} must have promptOverride`, ) } return withComponent }) // temporary extra condition in filter let unseen = this.questionsFromDb.filter( q => !seenIds.includes(q.response_key_id) && aspectsArr.includes(q.response_key_id), ) return [...stepsInCommon, ...unseen] } async getQuestions() { try { this.questionsFromDb = await fetchQuestions() return this.questionsFromDb } catch (err) { console.error(err) } } async createSurvey(langFile = allSteps['usa'], roleTree) { if (!this.questionsFromDb.length) { const res = await this.getQuestions() console.warn( `Attempted to create a survey before getting questions: retrieved ${res.length} questions`, ) } const steps = this._setSteps(langFile) return new Survey(steps, roleTree) } } export { SurveyFactory }