diff --git a/002_source/ionic_mobile/src/hooks/fetchCRQuestions.tsx b/002_source/ionic_mobile/src/hooks/fetchCRQuestions.tsx new file mode 100644 index 0000000..1133374 --- /dev/null +++ b/002_source/ionic_mobile/src/hooks/fetchCRQuestions.tsx @@ -0,0 +1,30 @@ +import { idCard } from 'ionicons/icons'; +import { QuizCRQuestion } from '../types/QuizCRQuestion'; +import { usePocketBase } from './usePocketBase'; +import { QueryClient } from '@tanstack/react-query'; +import PocketBase from 'pocketbase'; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: Infinity, + }, + }, +}); + +const fetchCRQuestions = async (cat_id: string, pb: PocketBase) => { + const response = await queryClient.fetchQuery({ + queryKey: ['fetchData', cat_id], + staleTime: 60 * 1000, + queryFn: async () => { + return await pb.collection('QuizCRQuestions').getList(1, 9999, { + filter: `cat_id = "${cat_id}"`, + $autoCancel: false, + }); + }, + }); + + return response; +}; + +export default fetchCRQuestions; diff --git a/002_source/ionic_mobile/src/hooks/useListQuizCRCategories.tsx b/002_source/ionic_mobile/src/hooks/useListQuizCRCategories.tsx new file mode 100644 index 0000000..3b2d02f --- /dev/null +++ b/002_source/ionic_mobile/src/hooks/useListQuizCRCategories.tsx @@ -0,0 +1,38 @@ +// CR = ConnectiveRevision +import { usePocketBase } from './usePocketBase.tsx'; +import { useQuery } from '@tanstack/react-query'; +import IListeningPracticeCategory from '../interfaces/IListeningPracticeCategory.tsx'; + +const useListQuizCRCategories = () => { + const { user, pb } = usePocketBase(); + return useQuery({ + queryKey: [ + 'useListQuizConnectiveRevisionContent', + 'feeds', + 'all', + user?.id || '', + // + ], + staleTime: 60 * 1000, + queryFn: async ({ + queryKey, + }: { + queryKey: [ + 'useListQuizConnectiveRevisionContent', + 'feeds', + 'all', + string | null, + // + ]; + }) => { + console.log('calling useListQuizConnectiveRevisionContent'); + return await pb.collection('LessonsCategories').getList(1, 9999, { + sort: 'pos', + $autoCancel: false, + }); + }, + // enabled: !!user?.id, + }); +}; + +export default useListQuizCRCategories; diff --git a/002_source/ionic_mobile/src/hooks/useListQuizCRQuestionByCRCategoryId.tsx b/002_source/ionic_mobile/src/hooks/useListQuizCRQuestionByCRCategoryId.tsx new file mode 100644 index 0000000..41dbb04 --- /dev/null +++ b/002_source/ionic_mobile/src/hooks/useListQuizCRQuestionByCRCategoryId.tsx @@ -0,0 +1,26 @@ +import { usePocketBase } from './usePocketBase.tsx'; +import { useQuery } from '@tanstack/react-query'; +import { QuizCRQuestion } from '../types/QuizCRQuestion.ts/index.ts'; + +const useListQuizCRQuestionByCRCategoryId = (CRCategoryId: string) => { + const { user, pb } = usePocketBase(); + return useQuery({ + queryKey: ['useListQuizCRQuestionByCRCategoryId', 'feeds', 'all', user?.id || '', CRCategoryId], + staleTime: 60 * 1000, + queryFn: async ({ + queryKey, + }: { + queryKey: ['useListQuizCRQuestionByCRCategoryId', 'feeds', 'all', string | null, string]; + }) => { + console.log('calling useListQuizCRQuestionByCRCategoryId'); + return await pb.collection('QuizCRQuestions').getList(1, 9999, { + filter: `cat_id = "${CRCategoryId}"`, + sort: 'id', + $autoCancel: false, + }); + }, + // enabled: !!user?.id && !!CRCategoryId, + }); +}; + +export default useListQuizCRQuestionByCRCategoryId; diff --git a/002_source/ionic_mobile/src/interfaces/IConnectivesRevisionCategory.tsx b/002_source/ionic_mobile/src/interfaces/IConnectivesRevisionCategory.tsx index 4f893cc..39fbff6 100644 --- a/002_source/ionic_mobile/src/interfaces/IConnectivesRevisionCategory.tsx +++ b/002_source/ionic_mobile/src/interfaces/IConnectivesRevisionCategory.tsx @@ -5,7 +5,9 @@ interface IConnectivesRevisionCategory { test_i: number; cat_info: string; cat_name: string; - content: IConnectivesRevisionQuestion[] | []; + content?: IConnectivesRevisionQuestion[] | []; + // + id: string; } export default IConnectivesRevisionCategory; diff --git a/002_source/ionic_mobile/src/pages/ConnectiveRevision/IQuestionCard.tsx b/002_source/ionic_mobile/src/pages/ConnectiveRevision/IQuestionCard.tsx index 70052ca..ba21e97 100644 --- a/002_source/ionic_mobile/src/pages/ConnectiveRevision/IQuestionCard.tsx +++ b/002_source/ionic_mobile/src/pages/ConnectiveRevision/IQuestionCard.tsx @@ -1,3 +1,4 @@ +// abonded interface IQuestionMeta { question_idx: number; question_fh: string; diff --git a/002_source/ionic_mobile/src/pages/ConnectiveRevision/QuizContent.tsx b/002_source/ionic_mobile/src/pages/ConnectiveRevision/QuizContent.tsx index 83606de..b6824b5 100644 --- a/002_source/ionic_mobile/src/pages/ConnectiveRevision/QuizContent.tsx +++ b/002_source/ionic_mobile/src/pages/ConnectiveRevision/QuizContent.tsx @@ -155,7 +155,7 @@ const QuizContent: React.FC = ({ > {answer_list.map((connective, idx) => { return ( -
+
(); - const i_p_route = parseInt(p_route); + const { p_route: cat_id } = useParams<{ p_route: string }>(); + + // NOTE: abonded, should be updated with `i_cat_id` when done + const i_p_route = parseInt(cat_id); const { setTabActive } = useAppStateContext(); const [question_list, setQuestionList] = useState([]); @@ -22,6 +26,9 @@ function ConnectiveRevisionQuizRun() { const [isOpenCorrectAnswer, setIsOpenCorrectAnswer] = useState(false); const [isOpenWrongAnswer, setIsOpenWrongAnswer] = useState(false); const [answer_list, setAnswerList] = useState(['but', 'and', 'or', 'of', 'with']); + + const { user, pb } = usePocketBase(); + const { setConnectiveRevisionCurrentTest, setConnectiveRevisionProgress, @@ -79,19 +86,19 @@ function ConnectiveRevisionQuizRun() { useEffect(() => { (async () => { - const res_json = await listConectivesRevisionContent(); - let temp_init_ans = res_json[i_p_route].init_ans; + const res_json = await fetchCRQuestions(cat_id, pb); + let temp_init_ans: string[] = res_json.items[0].init_answer; setInitAnswer(temp_init_ans); - let temp = res_json[i_p_route].content; + let temp = res_json.items; let shuffled_temp = shuffleArray(temp); // let shuffled_temp = temp; setQuestionList(shuffled_temp); - let question_meta_current = res_json[i_p_route].content[0]; + let question_meta_current = res_json.items[0] as unknown as IQuestionMeta; setCurrentQuestionMeta({ - question_idx: current_question_idx, ...question_meta_current, + question_idx: current_question_idx, }); })(); setTabActive(QUIZ_MAIN_MENU_LINK); @@ -113,31 +120,7 @@ function ConnectiveRevisionQuizRun() { total_questions_num={question_list.length} answer_list={answer_list} quiz_idx={i_p_route + 1} - // /> - {/* */} - {/* setIsOpenCorrectAnswer(false)} /> */} - {/* */} - {/* setIsOpenWrongAnswer(false)} - /> */} - {/* - setIsOpenCorrectAnswer(false)} - duration={1000 - 100} - color='success' - > - setIsOpenWrongAnswer(false)} - duration={1000 - 100} - color='danger' - > */} diff --git a/002_source/ionic_mobile/src/pages/ConnectiveRevision/SelectCategory.tsx b/002_source/ionic_mobile/src/pages/ConnectiveRevision/SelectCategory.tsx index 089b159..4953159 100644 --- a/002_source/ionic_mobile/src/pages/ConnectiveRevision/SelectCategory.tsx +++ b/002_source/ionic_mobile/src/pages/ConnectiveRevision/SelectCategory.tsx @@ -8,6 +8,7 @@ import { ConnectiveRevisionAllResult } from '../../contexts/ConnectiveRevisionRa import { useMyIonQuizContext } from '../../contexts/MyIonQuiz'; import IConnectivesRevisionCategory from '../../interfaces/IConnectivesRevisionCategory'; import { listConectivesRevisionContent } from '../../public_data/listConectivesRevisionContent'; +import useListQuizCRCategories from '../../hooks/useListQuizCRCategories'; function ConnectiveRevisionSelectCategory() { const PAGE_TITLE = 'Connective Revision'; @@ -17,12 +18,12 @@ function ConnectiveRevisionSelectCategory() { let [categories, setCategories] = useState([]); let { setTabActive, setConnectiveRevisionInProgress } = useAppStateContext(); - useEffect(() => { - listConectivesRevisionContent().then((res_json) => { - setCategories(res_json); - setLoading(false); - }); - }, []); + // useEffect(() => { + // listConectivesRevisionContent().then((res_json) => { + // setCategories(res_json); + // setLoading(false); + // }); + // }, []); let { loadConnectiveRevisionScoreBoard } = useMyIonQuizContext(); let [scoreboard_meta, setScoreboardMeta] = useState(); @@ -36,6 +37,14 @@ function ConnectiveRevisionSelectCategory() { setTabActive(QUIZ_MAIN_MENU_LINK); }, []); + let result = useListQuizCRCategories(); + useEffect(() => { + if (result.status === 'success') { + setCategories(result.data.items); + setLoading(false); + } + }, [result]); + if (loading) return ; if (!scoreboard_meta) return ; @@ -87,36 +96,34 @@ function ConnectiveRevisionSelectCategory() {
{'Question Bank'}
- {categories - .map((item) => item.cat_name) - .map((item_name, idx) => ( -
- { - setConnectiveRevisionInProgress(true); - router.push(`${CONNECTIVE_REVISION_LINK}/r/${idx}`, 'none', 'replace'); + {categories.map((item, idx) => ( +
+ { + setConnectiveRevisionInProgress(true); + router.push(`${CONNECTIVE_REVISION_LINK}/r/${item.id}`, 'none', 'replace'); + }} + > +
-
-
{item_name}
-
- {scoreboard_meta[idx.toString()] || 0} - {'%'} -
+
{item.cat_name}
+
+ {scoreboard_meta[idx.toString()] || 0} + {'%'}
- -
- ))} +
+
+
+ ))}
diff --git a/002_source/ionic_mobile/src/types/QuizCRQuestion.ts b/002_source/ionic_mobile/src/types/QuizCRQuestion.ts new file mode 100644 index 0000000..4de2a62 --- /dev/null +++ b/002_source/ionic_mobile/src/types/QuizCRQuestion.ts @@ -0,0 +1,33 @@ +/** + * Represents a Connectives Revision Quiz Question + */ +export interface QuizCRQuestion { + /** Unique identifier */ + id: string; + /** Creation timestamp */ + created: Date; + /** Last update timestamp */ + updated: Date; + /** First half of the question */ + question_fh: string; + /** Second half of the question */ + question_sh: string; + /** Modal answer text */ + modal_ans: string; + /** Initial answer text */ + init_answer: string[]; + /** Category ID reference */ + cat_id: string; + /** Additional options in JSON format */ + options: Record; +} + +/** + * Expanded QuizCRQuestion with related category data + */ +export interface QuizCRQuestionExpanded extends QuizCRQuestion { + /** Category name */ + cat_name?: string; + /** Category image */ + cat_image?: string; +}