import { BodySubmitProfilingQuestionsProductIdProfilingQuestionsPost, ProfilingQuestionsApiFactory, UpkQuestionChoice, UserQuestionAnswerIn, } from "@/api"; import React from "react" import {Card, CardContent, CardFooter, CardHeader, CardTitle} from "@/components/ui/card.tsx"; import {useAppDispatch, useAppSelector} from "@/hooks.ts"; import {addAnswer, Answer, saveAnswer, selectAnswerForQuestion, submitAnswer} from "@/models/answerSlice.ts"; import {useSelector} from "react-redux"; import {Button} from "@/components/ui/button" import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, } from "@/components/ui/pagination" import {Input} from "@/components/ui/input" import {Badge} from "@/components/ui/badge" import clsx from "clsx" import { ProfileQuestion, selectFirstAvailableQuestion, selectNextAvailableQuestion, selectQuestions, setNextQuestion, setQuestionActive } from "@/models/questionSlice.ts"; import {assert} from "@/lib/utils.ts"; import {motion} from "framer-motion" import {App} from "../models/app"; const TextEntry: React.FC<{ question: ProfileQuestion }> = ({question}) => { const dispatch = useAppDispatch() // const selectAnswer = useMemo(() => selectAnswerForQuestion(question), [question]); // const selectAnswer = useSelector(selectAnswerForQuestion(question)); const answer: Answer | undefined = useSelector(selectAnswerForQuestion(question)); const error: Boolean = answer?.error_msg.length > 0 const handleInputChange = (event: React.KeyboardEvent) => { const target = event.target as HTMLInputElement; dispatch(addAnswer({question, val: target.value as string})) }; return ( <> { error &&

{answer?.error_msg}

} ) } const MultiChoiceItem: React.FC<{ question: ProfileQuestion, choice: UpkQuestionChoice }> = ({question, choice}) => { const dispatch = useAppDispatch() // const selectAnswer = useMemo(() => selectAnswerForQuestion(question), [question]); // const answer: Answer = useSelector(selectAnswer); const answer: Answer | undefined = useSelector(selectAnswerForQuestion(question)); const selected: Boolean = (answer?.values || []).includes(choice.choice_id) return (
  • ) } const MultipleChoice: React.FC<{ question: ProfileQuestion }> = ({question}) => { // const selectAnswer = useMemo(() => selectAnswerForQuestion(question), [question]); // const answer: Answer = useSelector(selectAnswer); const answer: Answer | undefined = useSelector(selectAnswerForQuestion(question)); const error: Boolean = answer?.error_msg.length > 0 return ( <> { error &&

    {answer?.error_msg}

    }
      { question.choices.map(c => { return }) }
    ) } export const ProfileQuestionFull: React.FC<{ question: ProfileQuestion, submitAnswerEvt: () => void }> = ({question, submitAnswerEvt}) => { const dispatch = useAppDispatch() // const selectAnswer = useMemo(() => selectAnswerForQuestion(question), [question]); // const answer: Answer = useSelector(selectAnswer); const answer: Answer | undefined = useSelector(selectAnswerForQuestion(question)); const app: App = useAppSelector(state => state.app) const provided_answer = answer?.values.length > 0 const error: Boolean = answer?.error_msg.length > 0 const can_submit = provided_answer && !error && !answer?.complete const renderContent = () => { switch (question.question_type) { case 'TE': return case 'MC': return } }; return ( {answer && answer.processing && ( setLoading(false)} /> )} {(question.importance?.task_count ?? 0).toLocaleString()} {question.question_text} {renderContent()} ) } const PaginationIcon: React.FC<{ question: ProfileQuestion, idx: number, }> = ({question, idx}) => { const dispatch = useAppDispatch() const answers = useAppSelector(state => state.answers) const completed: Boolean = Boolean(answers[question.question_id]?.complete) const setQuestion = (evt: React.MouseEvent) => { if (completed) { evt.preventDefault() } else { dispatch(setQuestionActive(question)) } } return ( {idx + 1} ) } const QuestionsPage = () => { const dispatch = useAppDispatch() const questions = useSelector(selectQuestions) // @ts-ignore const question: ProfileQuestion | null = useSelector(selectFirstAvailableQuestion) dispatch(setQuestionActive(question as ProfileQuestion)) // This is saved now, so that if they click next it's ready. It // cannot be done within the click handler. // @ts-ignore const nextQuestion: ProfileQuestion | null = useSelector(selectNextAvailableQuestion) const answer: Answer | undefined = useSelector(selectAnswerForQuestion(question)); const app: App = useAppSelector(state => state.app) const clickNext = () => { // TODO: if nextQuestion was already submitted, skip it! if (nextQuestion) { // TS is not smart enough to know that the if statement above // prevents this from ever being null dispatch(setQuestionActive(nextQuestion)) } else { // What do we do now... no more questions left to do. } } // All the variables needed for a sliding window const q_idx = questions.findIndex(q => q.question_id === question.question_id) const questionsWindow = ( items: ProfileQuestion[], currentIndex: number, windowSize: number = 7 ): ProfileQuestion[] => { const half: number = Math.floor(windowSize / 2) const total: number = items.length let start: number = currentIndex - half let end: number = currentIndex + half + 1 if (start < 0) { end += Math.abs(start) start = 0 } // Adjust if window goes past the end if (end > total) { const overflow: number = end - total start = Math.max(0, start - overflow) end = total } return items.slice(start, end) } const submitAnswerEvt = () => { dispatch(submitAnswer({question: question})) assert(!answer?.complete, "Can't submit completed Answer") assert(!answer?.processing, "Can't submit processing Answer") assert(answer?.error_msg.length == 0, "Can't submit Answer with error message") let body: BodySubmitProfilingQuestionsProductIdProfilingQuestionsPost = { 'answers': [{ "question_id": question.question_id, "answer": answer.values } as UserQuestionAnswerIn ] } ProfilingQuestionsApiFactory().submitProfilingQuestionsProductIdProfilingQuestionsPost(app.bpid, app.bpuid, body) .then(res => { if (res.status == 200) { dispatch(saveAnswer({question: question})) dispatch(setNextQuestion()) } else { // let error_msg = res.data.msg } }) .catch(err => console.log(err)); } return ( <> { questionsWindow(questions, q_idx).map(q => { return qq.question_id === q.question_id)} /> }) } ) } export { QuestionsPage }