diff options
Diffstat (limited to 'src/models')
| -rw-r--r-- | src/models/answerSlice.ts | 21 | ||||
| -rw-r--r-- | src/models/questionSlice.ts | 58 |
2 files changed, 50 insertions, 29 deletions
diff --git a/src/models/answerSlice.ts b/src/models/answerSlice.ts index aada48c..cd20dbc 100644 --- a/src/models/answerSlice.ts +++ b/src/models/answerSlice.ts @@ -1,4 +1,6 @@ import {createSelector, createSlice, PayloadAction} from '@reduxjs/toolkit' +import {Selector} from 'react-redux' + // import {Answer} from "@/models/answer.ts"; // import {stringify} from "querystring"; import {RootState} from '@/store'; // your root state type @@ -183,24 +185,13 @@ export const { } = answerSlice.actions; export default answerSlice.reducer -export const answerForQuestion = (state: RootState, question: ProfileQuestion) => state.answers[question.question_id] ?? { - values: [], - error_msg: "", - complete: false, - processing: false -} as Answer; -export const makeSelectChoicesByQuestion = (question: ProfileQuestion) => +export const selectAnswerForQuestion = ( + question: ProfileQuestion +): Selector<RootState, Answer | null> => createSelector( (state: RootState) => state.answers, (answers) => { - // const question = questions.find(q => q.id === questionId); - // return question?.choices ?? []; - return answers[question.question_id] ?? { - values: [], - error_msg: "", - complete: false, - processing: false - } as Answer; + return answers[question.question_id] || null } );
\ No newline at end of file diff --git a/src/models/questionSlice.ts b/src/models/questionSlice.ts index ec9f84a..9543088 100644 --- a/src/models/questionSlice.ts +++ b/src/models/questionSlice.ts @@ -2,6 +2,8 @@ import {createSelector, createSlice, PayloadAction} from '@reduxjs/toolkit' import type {RootState} from '@/store' import {UpkQuestion} from "@/api"; import {Answer} from "@/models/answerSlice.ts"; +import {assert} from "@/lib/utils.ts" +import {Selector} from "react-redux"; export interface ProfileQuestion extends UpkQuestion { active: false @@ -59,11 +61,18 @@ export const selectQuestions = (state: RootState) => state.questions export const selectActiveQuestion = (state: RootState) => state.questions.find(i => i.active) export const selectAnswers = (state: RootState) => state.answers -export const selectNextAvailableQuestion = createSelector( +export const selectFirstAvailableQuestion = createSelector( [selectQuestions, selectAnswers], - (questions, answers) => { + (questions, answers): Selector<RootState, ProfileQuestion | null> => { + /* This is used when the app loads up the Questions page and we + need to find the first Question that we'll present to + the Respondent. + + If there are any questions marked as active, show that + first. However, if there are not.. go ahead and search for + the next Question without an Answer or an Answer that isn't complete + */ - // -- Check if there are any questions marked as active const active = questions.find(q => q.active) if (active) { return active @@ -71,23 +80,44 @@ export const selectNextAvailableQuestion = createSelector( let res = questions.filter(q => { const a: Answer | undefined = answers[q.question_id] - return !a || a.complete === false + return !a || !a.complete }) - // return res.reduce((min, q) => - // !min || q.order < min.order ? q : min, - // null as typeof res[0] | null - // ) return res[0] || null } ) +export const selectNextAvailableQuestion = createSelector( + [selectQuestions, selectAnswers], + (questions, answers): Selector<RootState, ProfileQuestion | null> => { + /* This takes the current active position and finds the next available + question to answer. -export const selectQuestionById = (questionId: string) => - createSelector( - (state: RootState) => state.questions, - (questions) => { - return questions.find(q => q.question_id === questionId); + Check if there are any questions marked as active. If there are not, + the Questions page didn't load yet and/or we don't know what the Respondent + is currently looking at... so we can't determine what is next. Immediately fail. + */ + const active = questions.find(q => q.active) + assert(active, "Must have an active Question") + const active_index = questions.findIndex(q => q.question_id === active.question_id) + + // Find any Questions without Answers, or Answers that are not complete + // that are positioned after the currently active Question + let found = questions.find((q, q_idx) => { + const a: Answer | undefined = answers[q.question_id] + return q_idx > active_index && (!a || !a.complete) + }) + + if (!found) { + // No eligible questions were found after the current active position, so + // go back and look for any before the current active position. + found = questions.find((q, q_idx) => { + const a: Answer | undefined = answers[q.question_id] + return q_idx < active_index && (!a || !a.complete) + }) } - );
\ No newline at end of file + + return found || null + } +) |
