Return

All tests / src/hooks useSurvey.ts

88.57% Statements 31/35
73.68% Branches 14/19
100% Functions 7/7
87.5% Lines 28/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 1031x 1x 1x                                   1x             1x 12x 12x 12x   12x             1x         11x 11x     11x         17x                 1x 20x 20x 20x   20x   20x   20x 2x     20x 1x       20x         11x   20x                         20x    
import { useRouter } from 'next/router';
import { useMemo, useReducer } from 'react';
import { buildSurveyQuestions, sanitizeSurveyName, DEFAULT_SURVEY_NAME, type Question } from '@/constants/survey';
 
interface Answer {
    question: string;
    answer: string;
    isCorrect: boolean;
    questionNum: number;
}
 
interface SurveyState {
    currentQuestion: number;
    questionsDone: number;
    success: boolean;
    answers: Answer[];
}
 
type SurveyAction = { type: 'NEXT_QUESTION' } | { type: 'PREVIOUS_QUESTION' } | { type: 'ADD_ANSWER'; payload: Answer };
 
const initialState: SurveyState = {
    currentQuestion: 0,
    questionsDone: 0,
    success: false,
    answers: [],
};
 
const reducer = (state: SurveyState, action: SurveyAction): SurveyState => {
    const { questionNum } = 'payload' in action ? action.payload : ({} as Partial<Answer>);
    const { answers, questionsDone, currentQuestion } = state;
    const newAnswers: Answer[] = [...answers];
 
    switch (action.type) {
        case 'NEXT_QUESTION':
            return {
                ...state,
                currentQuestion: currentQuestion + 1,
            };
        case 'PREVIOUS_QUESTION':
            return {
                ...state,
                currentQuestion: currentQuestion - 1,
            };
        case 'ADD_ANSWER':
            if (questionNum !== undefined) {
                newAnswers[questionNum] = {
                    ...action.payload,
                };
                return {
                    ...state,
                    answers: newAnswers,
                    currentQuestion: currentQuestion + 1,
                    questionsDone: questionNum > questionsDone ? questionNum : questionsDone,
                    success: newAnswers.every((answer) => answer.isCorrect) && currentQuestion === 10,
                };
            }
            return state;
        default:
            return state;
    }
};
 
const useSurvey = () => {
    const { query } = useRouter();
    const rawName = Array.isArray(query.name) ? query.name[0] : query.name ?? DEFAULT_SURVEY_NAME;
    const name = sanitizeSurveyName(rawName);
 
    const [state, dispatch] = useReducer(reducer, initialState);
 
    const questions = useMemo(() => buildSurveyQuestions(name, state.success), [name, state.success]);
 
    const handlePreviousQuestion = () => {
        if (state.currentQuestion > 1) dispatch({ type: 'PREVIOUS_QUESTION' });
    };
 
    const handleNextQuestion = () => {
        Iif (state.currentQuestion !== 0 && state.questionsDone >= state.currentQuestion)
            dispatch({ type: 'NEXT_QUESTION' });
    };
 
    const handleAnswerOptionClick = (payload: {
        question: string;
        answer: string;
        isCorrect: boolean;
        questionNum: number;
    }) => dispatch({ type: 'ADD_ANSWER', payload });
 
    return {
        questions,
        answers: state.answers,
        surveySuccess: state.success,
        currentQuestionNum: state.currentQuestion,
        questionsDoneNum: state.questionsDone,
        totalQuestions: questions.length,
        handleAnswerOptionClick,
        handleNextQuestion,
        handlePreviousQuestion,
    };
};
 
export default useSurvey;
export type { Question };