Teaching tools: word occurrences, blanks handout, templates, series progress, book info, comments
Build and Push Docker Image / build-and-push (push) Successful in 6m41s
Build and Push Docker Image / build-and-push (push) Successful in 6m41s
- Words tab: "Where else" lists every verse using a Strong's number, by book (new /api/strongs/:number/occurrences, indexed from the interlinear files) - Handout: fill-in-the-blanks layout with a word bank - Four new study templates: character, topical, word, verse by verse - Finish: series progress (not started / studied / ready / taught) - Background: book at a glance for all 66 books - Chunk comments for co-teachers, merged between copies - TODO: correct BSB audio note, tick co-teacher comments Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d9891ff9fe
commit
a6af9bd1c6
24 files changed
+670
-9
No files matched your search
@@ -8,6 +8,7 @@ import { normalizeStrongs } from '../../utils/iqbible.js';
|
||||
import IqLexicon from '../iq/IqLexicon.jsx';
|
||||
import GrammarPanel from '../GrammarPanel.jsx';
|
||||
import IqDictionary from '../iq/IqDictionary.jsx';
|
||||
import WordOccurrences from './WordOccurrences.jsx';
|
||||
|
||||
const inputCls = 'mt-1 block w-full rounded-lg border border-[var(--r-line)] bg-[var(--r-bg)] px-2.5 py-1.5 text-sm text-[var(--r-text)] focus:outline-none focus:ring-2 focus:ring-[var(--r-line)]';
|
||||
const btn = 'rounded-lg border border-[var(--r-line)] px-2.5 py-1.5 text-xs hover:bg-black/5 disabled:opacity-50';
|
||||
@@ -16,6 +17,7 @@ function WordCard({ word, open, onToggle, chunkId, wordStudy }) {
|
||||
const { updateChunkWord, lookupWord, removeGreekWord } = wordStudy;
|
||||
const iq = useIqAvailable();
|
||||
const [lexicon, setLexicon] = useState(false);
|
||||
const [where, setWhere] = useState(false);
|
||||
const strongs = normalizeStrongs(word.strongNumber || word.query);
|
||||
const set = (patch) => updateChunkWord(chunkId, word.id, patch);
|
||||
const field = (label, key, placeholder) => (
|
||||
@@ -34,6 +36,7 @@ function WordCard({ word, open, onToggle, chunkId, wordStudy }) {
|
||||
{open && (
|
||||
<div className="space-y-3 border-t border-[var(--r-line)] px-3 py-3">
|
||||
{lexicon && iq && strongs && <IqLexicon strongs={strongs} onClose={() => setLexicon(false)} />}
|
||||
{where && strongs && <WordOccurrences strongs={strongs} onClose={() => setWhere(false)} />}
|
||||
<label className="block text-xs text-[var(--r-sub)]">Strong’s number or English gloss
|
||||
<input type="text" value={word.query} onChange={(e) => set({ query: e.target.value })}
|
||||
onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); lookupWord(chunkId, word.id, 'greek'); } }}
|
||||
@@ -43,6 +46,7 @@ function WordCard({ word, open, onToggle, chunkId, wordStudy }) {
|
||||
<button type="button" onClick={() => lookupWord(chunkId, word.id, 'greek')} className={`${btn} bg-[var(--r-text)] text-[var(--r-bg)] hover:opacity-90`}>{word.loading ? 'Looking up...' : 'Look up Greek'}</button>
|
||||
<button type="button" onClick={() => lookupWord(chunkId, word.id, 'hebrew')} className={btn}>{word.loading ? 'Looking up...' : 'Look up Hebrew'}</button>
|
||||
{iq && strongs && <button type="button" onClick={() => setLexicon((o) => !o)} aria-pressed={lexicon} className={btn} title="Strong's, BDB, LSJ and Abbott-Smith entries">Lexicons</button>}
|
||||
{strongs && <button type="button" onClick={() => setWhere((o) => !o)} aria-pressed={where} className={btn} title="Every verse that uses this word, by book">Where else</button>}
|
||||
{word.lexeme && <button type="button" onClick={() => speakOriginalWord(word.lexeme, word.strongNumber)} className={btn} title="Hear pronunciation">Speak</button>}
|
||||
<button type="button" onClick={() => removeGreekWord(chunkId, word.id)} className={`${btn} ml-auto text-[var(--r-danger,#b42318)]`}>Delete</button>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user