{plan.days} days · {chapters} chapters · about {(chapters / plan.days).toFixed(1)} a day{completedCount > 0 ? ` · completed ${completedCount}×` : ''}
+
+
First days
+
+ {schedule.slice(0, 5).map((refs, i) => (
+
Day {i + 1} · {formatDayReadings(refs)}
+ ))}
+
+
+ {!active && (
+
+ Read in
+
+
+ )}
+
+ {active
+ ?
+ : }
+
+
+ {plan.custom && (
+
+
+
+ {plan.image && }
+
+
+ {imageError &&
{imageError}
}
+
+ )}
+ >
+ );
+}
+
+export default function PlanDetailSheet({ plan, progress, active, completedCount, onClose, actions }) {
+ if (!plan) return null;
+ return (
+ {plan.icon ? `${plan.icon} ` : ''}{plan.title}}>
+ {progress
+ ?
+ : }
+
+ );
+}
diff --git a/src/components/plans/TranslationSelect.jsx b/src/components/plans/TranslationSelect.jsx
new file mode 100644
index 0000000..aa71c50
--- /dev/null
+++ b/src/components/plans/TranslationSelect.jsx
@@ -0,0 +1,11 @@
+import { READER_TRANSLATIONS } from '../../hooks/useBibleReader.js';
+
+// Every Bible the app can read in — used for a plan's own translation.
+export default function TranslationSelect({ value, onChange, className = '' }) {
+ return (
+
+ );
+}
diff --git a/src/components/reader/NavigatorSheet.jsx b/src/components/reader/NavigatorSheet.jsx
index 0139e4c..65697af 100644
--- a/src/components/reader/NavigatorSheet.jsx
+++ b/src/components/reader/NavigatorSheet.jsx
@@ -7,7 +7,7 @@ import { READER_TRANSLATIONS } from '../../hooks/useBibleReader.js';
const NT_START = bookOptions.findIndex((b) => b.abbrev === 'MAT');
const chip = 'rounded-lg border px-2 py-2 text-center text-sm transition';
-export default function NavigatorSheet({ open, onClose, bookAbbrev, chapter, translation, onTranslation, onGo }) {
+export default function NavigatorSheet({ open, onClose, bookAbbrev, chapter, translation, onTranslation, translationNote, onGo }) {
const [pickedBook, setPickedBook] = useState(null); // book abbrev whose chapters are showing
const close = () => { setPickedBook(null); onClose(); };
const book = pickedBook ? bookOptions.find((b) => b.abbrev === pickedBook) : null;
@@ -33,6 +33,7 @@ export default function NavigatorSheet({ open, onClose, bookAbbrev, chapter, tra
))}
+ {translationNote &&
{translationNote}
}
Old Testament
{bookOptions.slice(0, NT_START).map(bookButton)}
New Testament
diff --git a/src/components/reader/PlanFooter.jsx b/src/components/reader/PlanFooter.jsx
new file mode 100644
index 0000000..9c332ba
--- /dev/null
+++ b/src/components/reader/PlanFooter.jsx
@@ -0,0 +1,32 @@
+// Card at the end of the chapter while reading a plan: step to the next chapter of
+// today's reading, or finish the day and roll into the next one.
+export default function PlanFooter({ info, label, onNext, onNextDay, onFinish }) {
+ if (!info || info.position === 0) return null;
+ const last = info.position === info.total;
+ const nextRef = !last ? info.refs[info.position] : null;
+ const btn = 'rounded-full bg-[var(--r-accent)] px-5 py-2 text-sm font-medium text-[var(--r-on)]';
+ return (
+
+ );
+}
diff --git a/src/components/reader/PlanSheet.jsx b/src/components/reader/PlanSheet.jsx
new file mode 100644
index 0000000..c86bce2
--- /dev/null
+++ b/src/components/reader/PlanSheet.jsx
@@ -0,0 +1,75 @@
+// The plan's control room, one tap from the reader: pick the day, tick chapters,
+// choose the Bible this plan is read in, and jump to another active plan.
+import Sheet from './Sheet.jsx';
+import { ChevronLeft, ChevronRight, CheckIcon } from './icons.jsx';
+import { READER_TRANSLATIONS } from '../../hooks/useBibleReader.js';
+import { formatDayReadings } from '../../utils/readingPlans.js';
+
+export default function PlanSheet({
+ open, onClose, info, translation, currentKey, streak, otherPlans, studyBusy,
+ onDay, onToggleChapter, onGoChapter, onTranslation, onToggleDay, onSwitchPlan, onListen, onStudy, onLeave,
+}) {
+ if (!info) return null;
+ const label = (r) => formatDayReadings([r]);
+ return (
+
+
+
+ Day {info.dayIndex + 1} of {info.plan.days}{info.done ? ' · read' : ''}
+
+
+ {otherPlans.map((o) => (
+
+ ))}
+ >
+ )}
+
+
+ );
+}
diff --git a/src/components/reader/PlanStrip.jsx b/src/components/reader/PlanStrip.jsx
index a632ce0..9dd98ff 100644
--- a/src/components/reader/PlanStrip.jsx
+++ b/src/components/reader/PlanStrip.jsx
@@ -1,18 +1,39 @@
-// Thin strip under the top bar while the open chapter belongs to an active
-// reading plan. Shows which day you're on and lets you mark it read.
-export default function PlanStrip({ matches, notice, onToggle }) {
- if (!matches.length && !notice) return null;
+// Thin strip under the top bar while reading a plan: which plan and day, one dot
+// per chapter of today's reading (filled = read, ringed = the chapter on screen),
+// and the translation. Tapping it opens the plan sheet. When you've wandered off
+// today's chapters (e.g. following a cross-reference) it offers a way back.
+export default function PlanStrip({ info, translation, inPlan, notice, onOpen, onJoin, onDot, onBackToDay }) {
+ if (!info && !notice) return null;
return (
-
+ {streak.current > 0 && {streak.current} day streak}
+
-
+
-
+
{readingPlanSyncStatus === 'error' && (
-
-
- ⚠️ Couldn't sync your reading plans to the server — changes here are only saved on this device until this is fixed.
- {readingPlanSyncError && {readingPlanSyncError}}
+
+
+ Couldn’t sync your reading plans to the server. Changes are only saved on this device until this is fixed.
+ {readingPlanSyncError && {readingPlanSyncError}}
-
+