diff --git a/src/App.jsx b/src/App.jsx index 10ffb59..14f634e 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -11,6 +11,7 @@ import Tooltips from './components/Tooltips.jsx'; import { useAudio } from './hooks/useAudio.js'; import { useAuth } from './hooks/useAuth.js'; import { useBibleReader } from './hooks/useBibleReader.js'; +import { lastTemplateId, planStudyProject } from './utils/planStudy.js'; import { isAudienceWindow } from './utils/presentSync.js'; import { useProjectLibrary } from './hooks/useProjectLibrary.js'; import { useHistoryNav } from './hooks/useHistoryNav.js'; @@ -425,29 +426,13 @@ const AppInner = () => { const studyReadingPlanDay = async (dayRefs, title) => { setStudyBuildBusy(true); try { + const lastTemplate = lastTemplateId(); // the notes template you picked last time you started a study by hand + const templateDef = reader.userTemplates?.find((t) => t.id === lastTemplate); const chapters = await Promise.all(dayRefs.map(async ({ book, chapter }) => { const data = await fetchStudyChapter('BSB', book, chapter); - const verses = parseBibleChapter(data); - const bookName = bookOptions.find((b) => b.abbrev === book)?.name ?? book; - const chunk = { - id: makeId(), - startVerse: verses[0]?.number ?? 1, - endVerse: verses.at(-1)?.number ?? 1, - spilloverEndVerse: null, - observation: '', interpretation: '', application: '', - crossReferences: [], greekWords: [], generalNotes: '', - episodeNumber: '', episodeTitle: '', finalScript: '', tags: [], - }; - return { book: bookName, bookAbbrev: book, chapter: String(chapter), verses, chunks: [chunk] }; + return { bookAbbrev: book, bookName: bookOptions.find((b) => b.abbrev === book)?.name ?? book, chapter, verses: parseBibleChapter(data) }; })); - const newProject = { - id: makeId(), - title: title || 'Reading Plan Study', - translation: 'BSB', - lastEdited: Date.now(), - selectedChunkId: chapters[0]?.chunks[0]?.id ?? null, - chapters, - }; + const newProject = planStudyProject({ chapters, title, templateId: lastTemplate, templateDef, makeId }); setProject(newProject); setCurrentPage('study'); } catch (err) { diff --git a/src/components/DailyFive.jsx b/src/components/DailyFive.jsx new file mode 100644 index 0000000..70bf82a --- /dev/null +++ b/src/components/DailyFive.jsx @@ -0,0 +1,66 @@ +// Home card: your five minutes for today. A short prompt on a passage from your studies, a five-minute clock, and a +// box to write in. What you write is added to that passage's notes. Pasting is turned off here on purpose. +import { useEffect, useMemo, useRef, useState } from 'react'; +import { useApp } from '../context/AppContext.js'; +import { loadProjectById } from '../utils/projectStorage.js'; +import { FIELD_NAMES, MINUTES, dailyPatch, pickDaily } from '../utils/dailyFive.js'; +import { formatClock } from '../utils/present.js'; + +const box = 'mb-4 rounded-xl border border-[var(--r-line)] bg-[var(--r-bar)] px-4 py-3 text-sm'; + +export default function DailyFive() { + const { projectIndex, saveChunkPatch } = useApp(); + const [step, setStep] = useState('card'); // card -> write -> done + const [text, setText] = useState(''); + const [left, setLeft] = useState(MINUTES * 60); + const [pasteTried, setPasteTried] = useState(false); + const pick = useMemo(() => pickDaily(projectIndex.map((e) => loadProjectById(e.id)).filter(Boolean)), [projectIndex]); + const started = useRef(null); + + useEffect(() => { + if (step !== 'write') return undefined; + started.current = Date.now(); + const t = window.setInterval(() => setLeft(Math.max(0, MINUTES * 60 - Math.round((Date.now() - started.current) / 1000))), 1000); + return () => window.clearInterval(t); + }, [step]); + + if (step === 'done') return
Saved to your notes. Same time tomorrow.
; + if (!pick) return null; + const { prompt } = pick; + + const save = () => { + saveChunkPatch(pick.projectId, pick.chunk.id, dailyPatch(pick.chunk, prompt.field, text)); + setStep('done'); + }; + + if (step === 'card') { + return ( +
+ Your five minutes: {pick.reference} · {FIELD_NAMES[prompt.field]} · {pick.projectTitle} + +
+ ); + } + return ( +
+
+

{pick.reference} · {FIELD_NAMES[prompt.field]}

+ {left === 0 ? 'Time’s up, finish your thought' : formatClock(left)} +
+ {pick.verses.length > 0 && ( +
+ {pick.verses.map((v) =>

{v.number}{v.text}

)} +
+ )} +

{prompt.text}

+