feat: added basic show-answer statistics

This commit is contained in:
Richard Wong 2026-01-10 16:12:42 +08:00
parent 0e42ad3a83
commit ae0160b5d2
4 changed files with 50 additions and 6 deletions

View File

@ -15,7 +15,8 @@
"note_live_validation": "Check this box to enable live validation feedback as you type. Uncheck to only show correctness upon completion.", "note_live_validation": "Check this box to enable live validation feedback as you type. Uncheck to only show correctness upon completion.",
"pick_pack": "Pick your pack(s)", "pick_pack": "Pick your pack(s)",
"tools": "Tools:", "tools": "Tools:",
"verses": "Verses:" "verses": "Verses:",
"problem_verses_session": "Statistics (This Session):"
}, },
"verse_validator": { "verse_validator": {
"input_reference": "Input Verse Reference:", "input_reference": "Input Verse Reference:",

View File

@ -15,7 +15,8 @@
"note_live_validation": "Check this box to enable live validation feedback as you type. Uncheck to only show correctness upon completion.", "note_live_validation": "Check this box to enable live validation feedback as you type. Uncheck to only show correctness upon completion.",
"pick_pack": "Pick your pack(s)", "pick_pack": "Pick your pack(s)",
"tools": "Tools:", "tools": "Tools:",
"verses": "Verses:" "verses": "Verses:",
"problem_verses_session": "Statistics (This Session):"
}, },
"verse_validator": { "verse_validator": {
"input_reference": "Input Verse Reference: ", "input_reference": "Input Verse Reference: ",

View File

@ -4,7 +4,7 @@ Implemented features:
- create checklist from keys - create checklist from keys
*/ */
import fullVerseData from "./assets/verse.json" // the actual verse json data file import fullVerseData from "./assets/verse.json" // the actual verse json data file
import { useState, useEffect, useMemo } from "react"; import { useState, useEffect, useMemo, useCallback } from "react";
import CheckboxTree from 'react-checkbox-tree'; import CheckboxTree from 'react-checkbox-tree';
import 'react-checkbox-tree/lib/react-checkbox-tree.css'; import 'react-checkbox-tree/lib/react-checkbox-tree.css';
import _ from 'underscore'; import _ from 'underscore';
@ -16,7 +16,7 @@ import logo from './assets/droplet.svg';
import { Suspense } from "react"; import { Suspense } from "react";
const ArrayTester = ({ array, toHideReference, liveValidation, clearKey, translate}) => { const ArrayTester = ({ array, toHideReference, liveValidation, clearKey, translate, onShowAnswer}) => {
const list = array.map((element, index) => ( const list = array.map((element, index) => (
// key needs to be unique; chose 3 elements that will separate all elements // key needs to be unique; chose 3 elements that will separate all elements
<VerseValidator <VerseValidator
@ -27,6 +27,7 @@ const ArrayTester = ({ array, toHideReference, liveValidation, clearKey, transla
clearKey={clearKey} // Pass clearKey down clearKey={clearKey} // Pass clearKey down
t={translate} // this passes the t i18 object to the function t={translate} // this passes the t i18 object to the function
index={index + 1} index={index + 1}
onShowAnswer={onShowAnswer}
/> />
)) ))
return list return list
@ -99,6 +100,18 @@ function Page() {
setClearKey(clearKey => clearKey + 1); setClearKey(clearKey => clearKey + 1);
}; };
// New state for tracking problem verses within the session
const [sessionProblemVerses, setSessionProblemVerses] = useState({});
// Callback for when 'Show Answer' is clicked in VerseValidator
const handleShowAnswer = useCallback((verseIdentifier) => {
const key = `${verseIdentifier.pack}|${verseIdentifier.reference}`;
setSessionProblemVerses(prev => ({
...prev,
[key]: (prev[key] || 0) + 1
}));
}, []);
// setup i18 for function // setup i18 for function
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
@ -200,6 +213,11 @@ function Page() {
return toShuffle ? _.sample(list, testCount) : _.first(list, testCount); return toShuffle ? _.sample(list, testCount) : _.first(list, testCount);
}, [VerseData, checked, testCount, toShuffle, shuffleKey]); }, [VerseData, checked, testCount, toShuffle, shuffleKey]);
// Reset session problem verses when the testList changes (new session)
useEffect(() => {
setSessionProblemVerses({});
}, [testList]);
return ( return (
@ -302,9 +320,25 @@ function Page() {
liveValidation={liveValidation} liveValidation={liveValidation}
clearKey={clearKey} // Pass clearKey down clearKey={clearKey} // Pass clearKey down
translate={t} translate={t}
onShowAnswer={handleShowAnswer}
/> />
} }
{Object.keys(sessionProblemVerses).length > 0 && (
<div className="session-problem-verses">
<h2>{t('main.problem_verses_session')}</h2>
<ul>
{Object.entries(sessionProblemVerses)
.sort(([, countA], [, countB]) => countB - countA) // Sort by count in descending order
.map(([key, count]) => {
// Assuming key format is "pack:reference"
const [pack, reference] = key.split('|');
return <li key={key}>{reference} (Shown Answer: {count} time{count > 1 ? 's' : ''})</li>;
})}
</ul>
</div>
)}
<hr /> <hr />
<p><x-small> Built on: {VITE_BUILD_DATE} </x-small></p> <p><x-small> Built on: {VITE_BUILD_DATE} </x-small></p>

View File

@ -12,7 +12,7 @@ const STATE = {
// function to render and handle logic of each of the cells // function to render and handle logic of each of the cells
const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse } , toHideReference, liveValidation, clearKey, t, index}) => { // useful use of destructuring here const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse } , toHideReference, liveValidation, clearKey, t, index, onShowAnswer}) => { // useful use of destructuring here
const [inputReference, setReference] = useState('') const [inputReference, setReference] = useState('')
const [referenceBool, setReferenceBool] = useState(STATE.INCORRECT) const [referenceBool, setReferenceBool] = useState(STATE.INCORRECT)
const [inputChapterTitle, setChapterTitle] = useState('') const [inputChapterTitle, setChapterTitle] = useState('')
@ -355,7 +355,15 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
{/* button to toggle show answer*/} {/* button to toggle show answer*/}
<div className="answer-button-box"> <div className="answer-button-box">
{/* <button onClick={() => setHintBool(!hintBool)}>Show Answer:</button> */} {/* <button onClick={() => setHintBool(!hintBool)}>Show Answer:</button> */}
<button onClick={() => setDiffBool(!diffBool)}>Show Answer:</button> <button onClick={() => {
// Toggle the diff display
setDiffBool(prev => !prev);
// If it's being turned ON, and onShowAnswer is provided, call it.
// We only want to count when the user explicitly reveals the answer.
if (!diffBool && onShowAnswer) {
onShowAnswer({ pack, title, reference });
}
}}>Show Answer:</button>
<button onClick={handleReset}>Reset</button> <button onClick={handleReset}>Reset</button>
</div> </div>