From d0fc6664f282e06f791be8366c6f76f5fa1d9b58 Mon Sep 17 00:00:00 2001 From: Richard Wong Date: Sat, 10 Jan 2026 13:00:27 +0800 Subject: [PATCH] feat: added live validation toggle --- public/locales/en/translation.json | 6 +++-- public/locales/kn/translation.json | 6 +++-- src/VerseSampler.jsx | 32 +++++++++++++++++++--- src/VerseValidator.jsx | 43 +++++++++++++----------------- 4 files changed, 55 insertions(+), 32 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index a0dd9ca..07be8ba 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -10,8 +10,10 @@ "set_shuffle": "Set Shuffle:", "note_set_shuffle": "(Otherwise cards will appear in sequential order)", "hide_reference": "Set Hide Reference:", - "note_hide_reference": "(If you also want to test the verse reference)", - "pick_pack": "Pick Your Packs:", + "note_hide_reference": "Check this box to hide the verse reference and test your memory on the reference as well.", + "live_validation": "Enable live validation", + "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)", "shuffle_card": "Shuffle Cards:", "verses": "Verses:" }, diff --git a/public/locales/kn/translation.json b/public/locales/kn/translation.json index 473d0cc..30ebddd 100644 --- a/public/locales/kn/translation.json +++ b/public/locales/kn/translation.json @@ -10,8 +10,10 @@ "set_shuffle": "무작위 설정:", "note_set_shuffle": "(Otherwise cards will appear in sequential order)", "hide_reference": "Set Hide Reference:", - "note_hide_reference": "(If you also want to test the verse reference)", - "pick_pack": "Pick Your Packs:", + "note_hide_reference": "Check this box to hide the verse reference and test your memory on the reference as well.", + "live_validation": "Enable live validation", + "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)", "shuffle_card": "Shuffle Cards:", "verses": "Verses:" }, diff --git a/src/VerseSampler.jsx b/src/VerseSampler.jsx index 0867c36..06ff346 100644 --- a/src/VerseSampler.jsx +++ b/src/VerseSampler.jsx @@ -15,7 +15,7 @@ import { useTranslation } from 'react-i18next'; import logo from './assets/droplet.svg'; import { Suspense } from "react"; -const GenerateTestList = ({ VerseData, packs, testCount, toShuffle, toHideReference, translate}) => { +const GenerateTestList = ({ VerseData, packs, testCount, toShuffle, toHideReference, liveValidation, translate}) => { let testList = packs.reduce( // grab all elements included checked in "packs" (accumulator, currentValue) => accumulator.concat(VerseData[currentValue]), @@ -26,18 +26,20 @@ const GenerateTestList = ({ VerseData, packs, testCount, toShuffle, toHideRefere ) } -const ArrayTester = ({ array, toHideReference, translate}) => { +const ArrayTester = ({ array, toHideReference, liveValidation, translate}) => { const list = array.map((element, index) => ( // key needs to be unique; chose 3 elements that will separate all elements @@ -201,6 +203,14 @@ function Page() { setHideReference(!toHideReference); }; + // state for liveValidation + const [liveValidation, setLiveValidation] = useState(true); + // Function to handle checkbox change + const handleLiveValidationCheckboxChange = () => { + // Toggle the state when the checkbox is changed + setLiveValidation(!liveValidation); + }; + @@ -250,7 +260,7 @@ function Page() { {!(toShuffle || toReview) ? <>

- {t('main.hide_reference')} + {t('main.hide_reference')}

} + {!(toReview) ? + <> +

+ {t('main.live_validation')} + +

+

{t('main.note_live_validation')}

+ : +

+ } +

{t('main.pick_pack')}

} diff --git a/src/VerseValidator.jsx b/src/VerseValidator.jsx index 9374288..7b2e68d 100644 --- a/src/VerseValidator.jsx +++ b/src/VerseValidator.jsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; import "./VerseValidator.css"; import { StringDiff } from "react-string-diff"; import { containsKorean, jamoSubstringMatch } from './utils'; @@ -12,8 +12,7 @@ const STATE = { // function to render and handle logic of each of the cells -const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse } , toHideReference, t, index}) => { // useful use of destructuring here - +const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse } , toHideReference, liveValidation, t, index}) => { // useful use of destructuring here const [inputReference, setReference] = useState('') const [referenceBool, setReferenceBool] = useState(STATE.INCORRECT) const [inputChapterTitle, setChapterTitle] = useState('') @@ -26,6 +25,15 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse const[diffBool, setDiffBool] = useState(false) const [isComposing, setIsComposing] = useState(false); + useEffect(() => { + // Re-run validation for all fields when liveValidation changes + // Using current input values to re-evaluate their state + validateReference(inputReference); + validateChapterTitle(inputChapterTitle); + validateTitle(inputTitle); + validateVerse(inputVerse); + }, [liveValidation]); // Dependency array: re-run effect when liveValidation changes + // handle reset const handleReset = () => { setReference(''); @@ -46,13 +54,13 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse setIsComposing(true); }; - function resultChecker(string1, string2) { + function resultChecker(string1, string2, liveValidation) { var result = STATE.INCORRECT; // init // contains korean if (containsKorean(string1)) { if (string1 === string2) { result = STATE.CORRECT; - } else if (jamoSubstringMatch(string2, string1) & string1 !== "") { + } else if (liveValidation && jamoSubstringMatch(string2, string1) & string1 !== "") { result = STATE.PARTIAL; } else { result = STATE.INCORRECT; @@ -60,7 +68,7 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse } else { // does not contain korean if (string1 === string2) { result = STATE.CORRECT; - } else if (string2.startsWith(string1) & string1 !== "") { + } else if (liveValidation && string2.startsWith(string1) & string1 !== "") { result = STATE.PARTIAL; } else { result = STATE.INCORRECT; @@ -81,7 +89,7 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse .toLowerCase() .normalize("NFC"); - const result = resultChecker(string1, string2); + const result = resultChecker(string1, string2, liveValidation); setReferenceBool(result); }; @@ -109,7 +117,7 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse .toLowerCase() .normalize("NFC"); - const result = resultChecker(string1, string2); + const result = resultChecker(string1, string2, liveValidation); setTitleBool(result); }; @@ -140,7 +148,7 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse .toLowerCase() .normalize("NFC"); - const result = resultChecker(string1, string2); + const result = resultChecker(string1, string2, liveValidation); setChapterTitleBool(result); }; @@ -167,7 +175,7 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse .toLowerCase() .normalize("NFC"); - const result = resultChecker(string1, string2); + const result = resultChecker(string1, string2, liveValidation); setVerseBool(result); }; @@ -179,21 +187,6 @@ const VerseValidator = ({ element: { pack, title, chapterTitle, reference, verse }`; - // const DiffViewer = ({oldValue, newValue}) => { - // const string1 = String(oldValue) - // .replace(/[\p{P}\p{S}]/gu, "") - // .toLowerCase() - // .normalize("NFC"); - - - // const string2 = String(newValue) - // .replace(/[\p{P}\p{S}]/gu, "") - // .toLowerCase() - // .normalize("NFC"); - - // return () - // } - const DiffViewerStrict = ({oldValue, newValue}) => { const string1 = String(oldValue) .toLowerCase()