feat: added hint feature

This commit is contained in:
Richard Wong 2026-01-10 16:28:29 +08:00
parent ae0160b5d2
commit 41d6eed467
2 changed files with 134 additions and 57 deletions

View File

@ -58,7 +58,7 @@
font-size: 15px; font-size: 15px;
} }
.answer-button-box { .verse-validator-button-box {
display: flex; display: flex;
gap: 10px; gap: 10px;
padding-top: 10px; padding-top: 10px;

View File

@ -10,9 +10,17 @@ 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, onShowAnswer}) => { // 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('')
@ -26,6 +34,12 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
const [isComposing, setIsComposing] = useState(false); const [isComposing, setIsComposing] = useState(false);
const isInitialMount = useRef(true); const isInitialMount = useRef(true);
// State for hint word counts
const [referenceHintCount, setReferenceHintCount] = useState(0);
const [titleHintCount, setTitleHintCount] = useState(0);
const [chapterTitleHintCount, setChapterTitleHintCount] = useState(0);
const [verseHintCount, setVerseHintCount] = useState(0);
useEffect(() => { useEffect(() => {
if (isInitialMount.current) { if (isInitialMount.current) {
isInitialMount.current = false; isInitialMount.current = false;
@ -54,6 +68,12 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
setVerse(''); setVerse('');
setVerseBool(STATE.INCORRECT); setVerseBool(STATE.INCORRECT);
setDiffBool(false); // optionally hide answer again setDiffBool(false); // optionally hide answer again
setHintBool(false);
// Reset hint counts
setReferenceHintCount(0);
setTitleHintCount(0);
setChapterTitleHintCount(0);
setVerseHintCount(0);
}; };
@ -259,6 +279,19 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
validateReference(value); validateReference(value);
}} }}
/> />
{hintBool && (
<div className="hint-area">
<p className="hint-text">
Hint: {reference.split(' ').slice(0, referenceHintCount).join(' ')}
</p>
<button
onClick={() => setReferenceHintCount(prev => prev + 1)}
disabled={referenceHintCount >= reference.split(' ').length}
>
Next Word
</button>
</div>
)}
</div> </div>
) : ( ) : (
<h2> <h2>
@ -292,69 +325,112 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
setChapterTitle(value); setChapterTitle(value);
validateChapterTitle(value); validateChapterTitle(value);
}} }}
/> />
{hintBool && (
<div className="hint-area">
<p className="hint-text">
Hint: {chapterTitle.split(' ').slice(0, chapterTitleHintCount).join(' ')}
</p>
<button
onClick={() => setChapterTitleHintCount(prev => prev + 1)}
disabled={chapterTitleHintCount >= chapterTitle.split(' ').length}
>
Next Word
</button>
</div>
)}
</div> </div>
)} )}
{/* input box for title */} {/* input box for title */}
<label className="title-box-label"> <div>
{t('verse_validator.input_title')} <label className="title-box-label">
</label> {t('verse_validator.input_title')}
<textarea </label>
className={titleClassName} <textarea
type="text" className={titleClassName}
id="titleBox" type="text"
name="titleBox" id="titleBox"
value={inputTitle} name="titleBox"
onInput={(event) => { value={inputTitle}
const value = event.target.value; onInput={(event) => {
setTitle(value); const value = event.target.value;
if (!isComposing) { setTitle(value);
if (!isComposing) {
validateTitle(value);
}
}}
onCompositionStart={handleCompositionStart}
onCompositionEnd={(event) => {
const value = event.target.value;
setIsComposing(false);
setTitle(value);
validateTitle(value); validateTitle(value);
} }}
}} />
onCompositionStart={handleCompositionStart} {hintBool && (
onCompositionEnd={(event) => { <div className="hint-area">
const value = event.target.value; <p className="hint-text">
setIsComposing(false); Hint: {title.split(' ').slice(0, titleHintCount).join(' ')}
setTitle(value); </p>
validateTitle(value); <button
}} onClick={() => setTitleHintCount(prev => prev + 1)}
disabled={titleHintCount >= title.split(' ').length}
/> >
Next Word
</button>
</div>
)}
</div>
{/* input box for verse */} {/* input box for verse */}
<label className="verse-box-label"> <div>
{t('verse_validator.input_verse')} <label className="verse-box-label">
</label> {t('verse_validator.input_verse')}
<textarea </label>
className={verseClassName} <textarea
type="text" className={verseClassName}
id="verseBox" type="text"
name="verseBox" id="verseBox"
value={inputVerse} name="verseBox"
onInput={(event) => { value={inputVerse}
const value = event.target.value; onInput={(event) => {
setVerse(value); const value = event.target.value;
if (!isComposing) { setVerse(value);
if (!isComposing) {
validateVerse(value);
}
}}
onCompositionStart={handleCompositionStart}
onCompositionEnd={(event) => {
const value = event.target.value;
setIsComposing(false);
setVerse(value);
validateVerse(value); validateVerse(value);
} }}
}} />
onCompositionStart={handleCompositionStart} {hintBool && (
onCompositionEnd={(event) => { <div className="hint-area">
const value = event.target.value; <p className="hint-text">
setIsComposing(false); Hint: {verse.split(' ').slice(0, verseHintCount).join(' ')}
setVerse(value); </p>
validateVerse(value); <button
}} onClick={() => setVerseHintCount(prev => prev + 1)}
disabled={verseHintCount >= verse.split(' ').length}
>
Next Word
</button>
</div>
)}
</div>
{/* buttons to toggle per-block functionality*/}
/> <div className="verse-validator-button-box">
{/* hint button*/}
{/* button to toggle show answer*/} <button onClick={() => setHintBool(!hintBool)}>
<div className="answer-button-box"> {hintBool ? 'Hide Hints' : 'Show Hints'}
{/* <button onClick={() => setHintBool(!hintBool)}>Show Answer:</button> */} </button>
{/* show answer button*/}
<button onClick={() => { <button onClick={() => {
// Toggle the diff display // Toggle the diff display
setDiffBool(prev => !prev); setDiffBool(prev => !prev);
@ -363,7 +439,8 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse
if (!diffBool && onShowAnswer) { if (!diffBool && onShowAnswer) {
onShowAnswer({ pack, title, reference }); onShowAnswer({ pack, title, reference });
} }
}}>Show Answer:</button> }}>Show Answer</button>
{/* reset button*/}
<button onClick={handleReset}>Reset</button> <button onClick={handleReset}>Reset</button>
</div> </div>