init: add source code from src.zip

This commit is contained in:
sigridjineth
2026-03-31 01:55:58 -07:00
commit f5a40b86de
1902 changed files with 513237 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,
}
}