From f213588112000d9b8132b04d9b7759eba3796012 Mon Sep 17 00:00:00 2001 From: ernestjx <73307945+ernestjx@users.noreply.github.com> Date: Thu, 15 Aug 2024 21:37:48 +0800 Subject: [PATCH] question update --- app/(main)/questions/create/page.tsx | 327 +++++++++++++++++++++++++++ 1 file changed, 327 insertions(+) create mode 100644 app/(main)/questions/create/page.tsx diff --git a/app/(main)/questions/create/page.tsx b/app/(main)/questions/create/page.tsx new file mode 100644 index 0000000..d14cf0b --- /dev/null +++ b/app/(main)/questions/create/page.tsx @@ -0,0 +1,327 @@ +"use client"; +import { useEffect, useState } from "react"; +import { Questions } from '@/types'; +import { QuestionsService } from '../../../../service/QuestionsService'; +import { TabView, TabPanel } from 'primereact/tabview'; +import { Editor, EditorTextChangeEvent } from "primereact/editor"; +import { InputSwitch, InputSwitchChangeEvent } from "primereact/inputswitch"; +import { DataTable } from 'primereact/datatable'; +import { Column } from 'primereact/column'; +import { Button } from 'primereact/button'; +import { Dialog } from 'primereact/dialog'; +import { TreeSelect, TreeSelectSelectionKeysType } from "primereact/treeselect"; +import { useRouter } from 'next/navigation'; + +const EditQuestion = () => { + const router = useRouter(); + const [selectedTopicNodes, setSelectedTopicNodes] = useState(); + const [topicNodes, setTopicNodes] = useState(null); + + const [addedOptions, setAddedOptions] = useState([]); + const [stem, setStem] = useState(''); + const [answer, setAnswer] = useState(''); + const [explanation, setExplanation] = useState(''); + const [isAnswer, setIsAnswer] = useState(false); + const [listOfTopics, setListOfTopics] = useState([]); + const [showOptionDialog, setShowOptionDialog] = useState(false); + const [activeTab, setActiveTab] = useState(0); + + useEffect(()=>{ + QuestionsService.getTopics().then((data) => { + console.log("topics initialized: ", data); + setListOfTopics(data); + + }); + }, []) + + useEffect(()=>{ + var nodes = listOfTopics.map( topic => { + let childnode: any[] = []; + if(topic.skills){ + childnode = topic.skills.map( skill => { + return { "key": topic.id+"-"+skill.id, + "label": skill.name, + "data": { "id": skill.id,"name": skill.name , "type": "skill", "topicId": topic.id} + }; + }); + } + return { "key" : topic.id, "label": topic.name, "data" : { "id":topic.id, "name": topic.name, "type": "topic"}, children : childnode } + }); + setTopicNodes(nodes); + }, [listOfTopics]) + + const optionsItemTemplate = (option: Questions.Option) => { + return( + <> +
option
+ + +
+
explanation
+ + + + ) + } + const optionItemActionTemplate = (option: Questions.Option) => { + return( + + ) + } + const optionItemisAnswer = (option: Questions.Option) => { + return {'bg-primary' : option.isAnswer}; + } + + + const optionItemAnswerSwitch = (option: Questions.Option) => { + return( + handleOnSelectAnswer(option.no, e.value)} /> + ) + } + + const OptionsHeader = ( +
+
+
+
+
+
+ ); + + const handleOnDeleteOption = (input_no: number) => { + addedOptions.splice(input_no-1, 1); + const reOrderedOptions =addedOptions.map((option, index) => { + return { + no: index + 1, + text: option.text, + isAnswer: option.isAnswer, + explanation: option.explanation + } + }) + setAddedOptions(reOrderedOptions); + } + const handleOnSelectAnswer = (selectedNo: number, checked: boolean) => { + var refreshAnswer = addedOptions; + refreshAnswer[selectedNo-1].isAnswer = checked; + if(checked){ + refreshAnswer =addedOptions.map((option) => { + return { + no: option.no, + text: option.text, + isAnswer: option.no === selectedNo, + explanation: option.explanation + } + }) + } + setAddedOptions(refreshAnswer); + } + const handleOnClickAdd = () => { + //add options + console.log(answer); + if(!answer) + return; + + const options: Questions.Option[] =addedOptions.map((option, index)=> { + return { + no: index + 1, + text: option.text, + isAnswer: option.isAnswer, + explanation: option.explanation + } + }) + options.push({ + no: options.length +1, + text: answer, + isAnswer: isAnswer, + explanation: explanation + }) + + setAddedOptions(options); + setAnswer(""); + setExplanation(""); + setIsAnswer(false); + setShowOptionDialog(false); + }; + + const handleOnClickDone =() => { + console.log("handleOnClickDone"); + console.log(selectedTopicNodes); + //validate + const answer = addedOptions.filter((option: Questions.Option)=>{ + return option.isAnswer + }) + if(!answer || answer.length <= 0 ) + throw "No answer selected" + console.log(answer) + //populate skills for mcq + let selectedTopics: number[] = []; + let selectedSkills: number[] = []; + if(selectedTopicNodes){ + Object.entries(selectedTopicNodes).forEach(([key, data]) => { + console.log("key", key, "data", data); + let topic_skill = key.split("-"); + if(topic_skill.length>1){ + selectedSkills.push(parseInt(topic_skill[1])); + } else { + selectedTopics.push(parseInt(topic_skill[0])); + } + }); + } + //instantiate MCQ object before adding + let mcq = { + stem: stem, + options: addedOptions, + topics: selectedTopics, + skills: selectedSkills, + // isAnswer: answer[0].no, + // status: "Draft", + + } + console.log("mcq to be created ", mcq); + QuestionsService.addMCQ(mcq).then((data) => { + console.log("saveQuestion response: ", data); + router.push('/questions/searchlist'); + }) + // .catch((e)=>{ + // console.log("saveQuestion error: ", e); + // e. + // }) + ; + } + return ( + <> +
Add Question
+
+ setActiveTab(e.index)}> + +
+
+ setSelectedTopicNodes(e.value)} options={topicNodes} + className="md:w-50rem w-full" metaKeySelection={false} selectionMode="checkbox" display="chip" placeholder="Select Topics / Skills" + showClear> + {/* + setSelectedTopics(e.value)} + options={listOfTopics} + optionLabel="name" + placeholder="Select Topics" + filter + display="chip" + className="w-full md:w-50rem" + maxSelectedLabels={3} + /> + + */} +
+
+ {/* + setSelectedSkills(e.value)} + options={listOfSkills} + optionLabel="name" + placeholder="Select Skills" + filter + display="chip" + className="w-full md:w-50rem" + /> + + */} +
+ {/*
+ +
*/} +
+ +
+
+
+ +
+
Fill in the stem of the question.
+
+ setStem(e.htmlValue || '')} style={{ height: '320px' }} /> +
+
+ {/*
+ +
*/} +
+ +
+
+ + {if (!showOptionDialog) return; setShowOptionDialog(false); }}> +
+
Add an option for the question
+ +
+ setAnswer(e.htmlValue || '')} style={{ height: '100px' }} /> +
+
Explain why this option is correct or wrong
+
+ setExplanation(e.htmlValue || '')} style={{ height: '100px' }} /> +
+
+
+
+
+
+
+
+
+ + + + + + +
+ {/*
+ +
*/} +
+ +
+
+
+ +
+
+ + +
+
+ + + + +
+
 
+ {/*
+ +
*/} +
+ +
+ +
+
+
+ + + ) +} + + +export default EditQuestion; + +function Nullable(arg0: {}) { + throw new Error("Function not implemented."); +}