From 62456f41288eb0f03c5092d36610d566f275c8b5 Mon Sep 17 00:00:00 2001
From: Max Nanis
Date: Tue, 3 Jun 2025 20:06:44 +0700
Subject: selectQuestionById, useMemo selector (MultiChoice.choices makes a lot
 of lookup). Setting up the Questions view to do Pagination to tab through
 available questions and view one at a time

---
 src/pages/Questions.tsx | 154 ++++++++++++++++++++++++------------------------
 1 file changed, 77 insertions(+), 77 deletions(-)

(limited to 'src/pages/Questions.tsx')

diff --git a/src/pages/Questions.tsx b/src/pages/Questions.tsx
index 0a3f43e..9eb7cba 100644
--- a/src/pages/Questions.tsx
+++ b/src/pages/Questions.tsx
@@ -1,23 +1,29 @@
-import React from 'react'
-import {UpkQuestion} from "@/api";
-import {UpkQuestionChoice} from "@/api/models/upk-question-choice.ts";
+import React, {useMemo, useState} from 'react'
+import {UpkQuestion, UpkQuestionChoice} from "@/api";
 import {Card, CardContent, CardHeader} from "@/components/ui/card.tsx";
-import {useAppSelector} from "@/hooks.ts";
+import {useAppDispatch, useAppSelector} from "@/hooks.ts";
+import {addAnswer, makeSelectChoicesByQuestion} from "@/models/answerSlice.ts";
+import {selectQuestionById} from "@/models/questionSlice.ts";
+import {useSelector} from "react-redux";
+import {Button} from "@/components/ui/button"
+import {
+    Pagination,
+    PaginationContent,
+    PaginationItem,
+    PaginationLink,
+    PaginationNext,
+} from "@/components/ui/pagination"
 
 const TextEntry: React.FC<{ question: UpkQuestion }> = ({question}) => {
-    // const dispatch = useAppDispatch()
-    // const buckets = useAppSelector(state => state.buckets)
-
-    // const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
-    //     // Don't allow any input changes after they triggered submission...
-    //     if (question._complete || question._processing) {
-    //         return
-    //     }
-    //
-    //     // Assign the input value as an answer to the question
-    //     const newValue = event.target.value;
-    //     dispatch(setAnswer({questionId: question.questionId, val: newValue}))
-    // };
+    const dispatch = useAppDispatch()
+    const selectAnswer = useMemo(() => makeSelectChoicesByQuestion(question), [question]);
+    const answer = useSelector(selectAnswer);
+
+    const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+        dispatch(addAnswer({question: question, val: event.target.value}))
+    };
+
+    console.log("TextEntry.answer", answer)
 
     return (
         <Card className="@container/card">
@@ -30,83 +36,52 @@ const TextEntry: React.FC<{ question: UpkQuestion }> = ({question}) => {
                        id="text-entry-input"
                        aria-describedby=""
                        placeholder=""
-                    // onInput={handleInputChange}
+                       onKeyDown={handleInputChange}
                 />
-                {/*<small id="text-entry-msg">{question.error_msg}</small>*/}
+                <small id="text-entry-msg">{answer.error_msg}</small>
             </CardContent>
         </Card>
     )
 }
 
 const MultiChoiceItem: React.FC<{ question: UpkQuestion, choice: UpkQuestionChoice }> = ({question, choice}) => {
-
-    // const onclick = function () {
-    //     // Assign the input value as an answer to the question
-    //     let answer = getAnswer;
-    //     let click_value = childView.model.get("choice_id")
-    //
-    //     switch (question.selector) {
-    //
-    //         case "SA": /// Single Answer
-    //             answer.set("values", [{"value": click_value}]);
-    //             break
-    //
-    //         case "MA": /// Multi Answer
-    //             let current_values: AnswerValueItemType[] = answer.get("values") ?? [];
-    //
-    //             if (includes(map(current_values, "value"), click_value)) {
-    //                 // The item has already been selected
-    //                 current_values = remove(current_values, (v) => {
-    //                     return v["value"] != click_value
-    //                 })
-    //
-    //             } else {
-    //                 // It's a new selection
-    //                 current_values.push({"value": click_value})
-    //             }
-    //
-    //             answer.set("values", current_values);
-    //             break
-    //     }
-    //     childView.render();
-    //
-    //     // Validate the answer and show any information
-    //     let res: QuestionValidationResult = this.model.validateAnswer()
-    //     this.ui.message.text(res["message"]);
-    // }
-
-    // const render = function () {
-    //     let answer = this.getOption("answer");
-    //     let current_values: AnswerValueItemType[] = answer.get("values") ?? [];
-    //     let current_values_values = map(current_values, "value");
-    //
-    //     if (includes(current_values_values, this.model.get("choice_id"))) {
-    //         this.$el.addClass("selected");
-    //     }
-    // }
+    const dispatch = useAppDispatch()
+    const selectAnswer = useMemo(() => makeSelectChoicesByQuestion(question), [question]);
+    const answer = useSelector(selectAnswer);
+    const selected = answer.values.includes(choice.choice_id)
 
     return (
-        <>
+        <Button
+            onClick={() => dispatch(addAnswer({question: question, val: choice.choice_id}))}
+            variant={selected ? "default" : "secondary"}
+        >
             {choice.choice_text}
-        </>
+        </Button>
     )
 }
 
 const MultipleChoice: React.FC<{ question: UpkQuestion }> = ({question}) => {
+    const selectAnswer = useMemo(() => makeSelectChoicesByQuestion(question), [question]);
+    const answer = useSelector(selectAnswer);
 
     return (
         <Card>
             <CardHeader>
                 {question.question_text}
-                {/*<small id="text-entry-msg">{question.error_msg}</small>*/}
+                <small id="text-entry-msg">{answer.error_msg}</small>
             </CardHeader>
 
             <CardContent>
-                {
-                    question.choices.map(c => {
-                        return <MultiChoiceItem key={`${question.question_id}-${c.choice_id}`} question={question} choice={c}/>
-                    })
-                }
+                <ol>
+                    {
+                        question.choices.map(c => {
+                            return <MultiChoiceItem
+                                key={`${question.question_id}-${c.choice_id}`}
+                                question={question}
+                                choice={c}/>
+                        })
+                    }
+                </ol>
             </CardContent>
         </Card>
     )
@@ -128,6 +103,12 @@ const ProfileQuestionFull: React.FC<UpkQuestion> = ({question}) => {
 
 const QuestionsPage = () => {
     const questions = useAppSelector(state => state.questions)
+    const [activeQuestionID, setQuestionID] = useState(() => questions[0].question_id);
+
+    const selectQuestion = useMemo(() => selectQuestionById(activeQuestionID), [questions]);
+    const question = useSelector(selectQuestion);
+
+    console.log(activeQuestionID, questions)
 
     return (
         <div>
@@ -135,11 +116,30 @@ const QuestionsPage = () => {
                 A total of {questions.length} questions are available.
             </p>
 
-            {
-                questions.map(q => {
-                    return <ProfileQuestionFull key={q.question_id} question={q} className="mt-4 mb-4"/>;
-                })
-            }
+            <Pagination>
+                <PaginationContent>
+                    {
+                        questions.map((q, i) => {
+                            return (
+                                <PaginationItem>
+                                    <PaginationLink
+                                        onClick={() => setQuestionID(q.question_id)}
+                                    >
+                                        {i+1}
+                                    </PaginationLink>
+                                </PaginationItem>
+                            )
+                        })
+                    }
+
+                    <PaginationItem>
+                        <PaginationNext/>
+                    </PaginationItem>
+                </PaginationContent>
+            </Pagination>
+
+
+            <ProfileQuestionFull key={question.question_id} question={question} className="mt-4 mb-4"/>
         </div>
     );
 }
-- 
cgit v1.2.3

