This commit is contained in:
kuberwastaken 2026-03-31 16:25:52 +05:30
commit ec53fcbe95
1905 changed files with 513762 additions and 0 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,179 @@
import { useCallback, useReducer } from 'react'
export type AnswerValue = string
export type QuestionState = {
selectedValue?: string | string[]
textInputValue: string
}
type State = {
currentQuestionIndex: number
answers: Record<string, AnswerValue>
questionStates: Record<string, QuestionState>
isInTextInput: boolean
}
type Action =
| { type: 'next-question' }
| { type: 'prev-question' }
| {
type: 'update-question-state'
questionText: string
updates: Partial<QuestionState>
isMultiSelect: boolean
}
| {
type: 'set-answer'
questionText: string
answer: string
shouldAdvance: boolean
}
| { type: 'set-text-input-mode'; isInInput: boolean }
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'next-question':
return {
...state,
currentQuestionIndex: state.currentQuestionIndex + 1,
isInTextInput: false,
}
case 'prev-question':
return {
...state,
currentQuestionIndex: Math.max(0, state.currentQuestionIndex - 1),
isInTextInput: false,
}
case 'update-question-state': {
const existing = state.questionStates[action.questionText]
const newState: QuestionState = {
selectedValue:
action.updates.selectedValue ??
existing?.selectedValue ??
(action.isMultiSelect ? [] : undefined),
textInputValue:
action.updates.textInputValue ?? existing?.textInputValue ?? '',
}
return {
...state,
questionStates: {
...state.questionStates,
[action.questionText]: newState,
},
}
}
case 'set-answer': {
const newState = {
...state,
answers: {
...state.answers,
[action.questionText]: action.answer,
},
}
if (action.shouldAdvance) {
return {
...newState,
currentQuestionIndex: newState.currentQuestionIndex + 1,
isInTextInput: false,
}
}
return newState
}
case 'set-text-input-mode':
return {
...state,
isInTextInput: action.isInInput,
}
}
}
const INITIAL_STATE: State = {
currentQuestionIndex: 0,
answers: {},
questionStates: {},
isInTextInput: false,
}
export type MultipleChoiceState = {
currentQuestionIndex: number
answers: Record<string, AnswerValue>
questionStates: Record<string, QuestionState>
isInTextInput: boolean
nextQuestion: () => void
prevQuestion: () => void
updateQuestionState: (
questionText: string,
updates: Partial<QuestionState>,
isMultiSelect: boolean,
) => void
setAnswer: (
questionText: string,
answer: string,
shouldAdvance?: boolean,
) => void
setTextInputMode: (isInInput: boolean) => void
}
export function useMultipleChoiceState(): MultipleChoiceState {
const [state, dispatch] = useReducer(reducer, INITIAL_STATE)
const nextQuestion = useCallback(() => {
dispatch({ type: 'next-question' })
}, [])
const prevQuestion = useCallback(() => {
dispatch({ type: 'prev-question' })
}, [])
const updateQuestionState = useCallback(
(
questionText: string,
updates: Partial<QuestionState>,
isMultiSelect: boolean,
) => {
dispatch({
type: 'update-question-state',
questionText,
updates,
isMultiSelect,
})
},
[],
)
const setAnswer = useCallback(
(questionText: string, answer: string, shouldAdvance: boolean = true) => {
dispatch({
type: 'set-answer',
questionText,
answer,
shouldAdvance,
})
},
[],
)
const setTextInputMode = useCallback((isInInput: boolean) => {
dispatch({ type: 'set-text-input-mode', isInInput })
}, [])
return {
currentQuestionIndex: state.currentQuestionIndex,
answers: state.answers,
questionStates: state.questionStates,
isInTextInput: state.isInTextInput,
nextQuestion,
prevQuestion,
updateQuestionState,
setAnswer,
setTextInputMode,
}
}