Invite-only sign-up, present mode, series, handouts, templates, dictation, progress, sharing
Build and Push Docker Image / build-and-push (push) Successful in 6m47s
Build and Push Docker Image / build-and-push (push) Successful in 6m47s
- Admin: sign-up Open / Invite only / Closed with single-use invite links - Present mode for scripts (auto-scroll) and outlines (step through, pace vs planned minutes) - Series: group studies on the dashboard, filter by series, calendar file for a study's sessions - Lesson handout: printable page per session (passage, outline, questions, writing lines) - Save a chunk's notes as your own study template (synced) - Voice dictation for notes and scripts (browser speech recognition) - Reading progress: map of the 66 books and a calendar of days read, synced and merged across devices - Export highlights and bookmarks as Markdown or Word, grouped by named colour - Verse of the day push to the ntfy topic (needs IQBIBLE_API_KEY) - Sharing: co-teacher editing via single-use invite links; read-only links can expire and take a passcode Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
88bc59bac0
commit
54cb1c217d
73 files changed
+2739
-134
No files matched your search
@@ -14,7 +14,7 @@ const primaryBtn = 'rounded-xl bg-[var(--r-accent)] px-5 py-2.5 text-sm font-med
|
||||
// Band tints that alternate from chunk to chunk so neighbouring chunks are easy to tell apart.
|
||||
const BANDS = ['color-mix(in srgb, var(--r-accent) 13%, transparent)', 'color-mix(in srgb, var(--r-sub) 17%, transparent)'];
|
||||
|
||||
function PassageForm({ setup, onField, onTitleChange, onLoad, loading, error, withTitle }) {
|
||||
function PassageForm({ setup, onField, onTitleChange, onLoad, loading, error, withTitle, userTemplates = [], onDeleteTemplate }) {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="grid gap-4 sm:grid-cols-2">
|
||||
@@ -35,8 +35,12 @@ function PassageForm({ setup, onField, onTitleChange, onLoad, loading, error, wi
|
||||
<label className="block text-sm sm:col-span-2">Start from
|
||||
<select value={setup.template ?? 'blank'} onChange={(e) => onField('template', e.target.value)} className={inputCls}>
|
||||
{STUDY_TEMPLATES.map((t) => <option key={t.id} value={t.id}>{t.name}</option>)}
|
||||
{userTemplates.length > 0 && <optgroup label="Your templates">{userTemplates.map((t) => <option key={t.id} value={t.id}>{t.name}</option>)}</optgroup>}
|
||||
</select>
|
||||
<span className="mt-1 block text-xs text-[var(--r-sub)]">{getTemplate(setup.template).description}</span>
|
||||
<span className="mt-1 block text-xs text-[var(--r-sub)]">{getTemplate(setup.template, userTemplates).description}</span>
|
||||
{setup.template?.startsWith('user-') && onDeleteTemplate && (
|
||||
<button type="button" onClick={() => { onDeleteTemplate(setup.template); onField('template', 'blank'); }} className="mt-1 text-xs text-[var(--r-danger,#b42318)] hover:underline">Delete this template</button>
|
||||
)}
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
@@ -49,8 +53,8 @@ function PassageForm({ setup, onField, onTitleChange, onLoad, loading, error, wi
|
||||
}
|
||||
|
||||
export default function SetupPage() {
|
||||
const { project, setProject, allChunks, updateProject, setCurrentPage } = useApp();
|
||||
const b = useChunkBuilder({ project, setProject, updateProject, allChunks, setCurrentPage });
|
||||
const { project, setProject, allChunks, updateProject, setCurrentPage, userTemplates, deleteUserTemplate } = useApp();
|
||||
const b = useChunkBuilder({ project, setProject, updateProject, allChunks, setCurrentPage, userTemplates });
|
||||
const { activeChapter, activeChapterIndex } = b;
|
||||
const chapters = project?.chapters ?? [];
|
||||
|
||||
@@ -73,7 +77,7 @@ export default function SetupPage() {
|
||||
<h1 className="mb-1 text-xl font-medium">New study</h1>
|
||||
<p className="mb-5 text-sm text-[var(--r-sub)]">Pick a chapter, then cut it into chunks. You’ll study one chunk at a time.</p>
|
||||
<PassageForm setup={b.setup} onField={b.handleSetupField} onTitleChange={onTitleChange} onLoad={b.handleLoadChapter}
|
||||
loading={b.loadingChapter} error={b.errorMessage} withTitle />
|
||||
loading={b.loadingChapter} error={b.errorMessage} withTitle userTemplates={userTemplates} onDeleteTemplate={deleteUserTemplate} />
|
||||
</section>
|
||||
)}
|
||||
|
||||
|
||||
Reference in new issue
Block a user