Rename the Export stage to Finish

It now holds files, sharing, handouts, slides, importing notes, schedule,
co-teachers and earlier versions, not just exports.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-14 13:17:08 -04:00
1 parent 2c7c7145c4
commit 0f1a181d87
12 files changed
+18 -18

No files matched your search

+1 -1
View File
@@ -167,7 +167,7 @@ const AppInner = () => {
// The browser tab and history show where you are ("Romans 8 · Bible Study", "Luke — Outline · Bible Study")
useEffect(() => {
const names = {
home: 'My Studies', setup: 'Chunks', study: 'Study', outline: 'Outline', script: 'Script', export: 'Export',
home: 'My Studies', setup: 'Chunks', study: 'Study', outline: 'Outline', script: 'Script', export: 'Finish',
import: 'Import', pronunciation: 'Pronunciation Guide', settings: 'Settings', admin: 'Admin', 'reading-plans': 'Reading Plans', prayer: 'Prayer journal', insights: 'Insights',
};
let page = names[currentPage] ?? '';
+1 -1
View File
@@ -1,4 +1,4 @@
// Export → Co-teachers: let other accounts edit this study with you. You make a single-use invite link;
// Finish → Co-teachers: let other accounts edit this study with you. You make a single-use invite link;
// whoever opens it (signed in) can edit the study, and you can remove them any time. Edits from both of you
// sync through the account; if you both change the same study, "Combine both" keeps everything.
import { useCallback, useEffect, useState } from 'react';
+1 -1
View File
@@ -1,4 +1,4 @@
// Export → Lesson handout: a printable page for each session (or one session), for a group to follow along.
// Finish → Lesson handout: a printable page for each session (or one session), for a group to follow along.
import { useState } from 'react';
import { HANDOUT_LAYOUTS, printHandout, sessionsFor } from '../utils/handout.js';
+1 -1
View File
@@ -1,4 +1,4 @@
// Export → Import notes: bring notes from a Word or Markdown file into this study, matched to its chunks by passage.
// Finish → Import notes: bring notes from a Word or Markdown file into this study, matched to its chunks by passage.
import { useState } from 'react';
import { useApp } from '../context/AppContext.js';
import { useToast } from './Toasts.jsx';
+1 -1
View File
@@ -1,4 +1,4 @@
// Export → Schedule: the study's sessions (one per chunk) as a calendar file, starting on a date you pick.
// Finish → Schedule: the study's sessions (one per chunk) as a calendar file, starting on a date you pick.
import { useState } from 'react';
import { formatChunkReference } from '../utils/bibleUtils.jsx';
import { buildIcs, downloadIcs, sessionDates } from '../utils/icsFile.js';
+1 -1
View File
@@ -1,4 +1,4 @@
// Export → Slides: a printable slide deck for a session or the whole study (Save as PDF in the print dialog).
// Finish → Slides: a printable slide deck for a session or the whole study (Save as PDF in the print dialog).
import { useState } from 'react';
import { sessionsFor } from '../utils/handout.js';
import { printSlides } from '../utils/slides.js';
+1 -1
View File
@@ -1,4 +1,4 @@
// Export → Earlier versions: the copies the server kept of this study as you worked. Look at what is different
// Finish → Earlier versions: the copies the server kept of this study as you worked. Look at what is different
// from now, and put one back. The version you replace is kept, so putting one back can be undone too.
import { useCallback, useEffect, useState } from 'react';
import { getStudyVersion, listStudyVersions } from '../syncService.js';
+1 -1
View File
@@ -10,7 +10,7 @@ export const STAGES = [
{ id: 'study', label: 'Study' },
{ id: 'outline', label: 'Outline' },
{ id: 'script', label: 'Script' },
{ id: 'export', label: 'Export' },
{ id: 'export', label: 'Finish' },
];
const THEME_ORDER = ['paper', 'sepia', 'dark'];
+2 -2
View File
@@ -1,4 +1,4 @@
// The Export stage: take the finished study out as a file, or share it read-only.
// The Finish stage: everything for when a study is ready to use: files, sharing, handouts, slides, importing notes, schedule, co-teachers and earlier versions.
import { useApp } from '../context/AppContext.js';
import { useShareLink } from '../hooks/useShareLink.js';
import SlidesExport from '../components/SlidesExport.jsx';
@@ -32,7 +32,7 @@ export default function ExportPage() {
<StudioShell stage="export">
<main className="mx-auto max-w-2xl space-y-5 px-4 py-8">
<div>
<h1 className="text-xl font-medium">Export</h1>
<h1 className="text-xl font-medium">Finish</h1>
<p className="mt-1 text-sm text-[var(--r-sub)]">{allChunks.length} chunk{allChunks.length === 1 ? '' : 's'} · {filled} script{filled === 1 ? '' : 's'} written</p>
</div>
+1 -1
View File
@@ -1,5 +1,5 @@
// Every Greek and Hebrew word in the study with its transliteration, so a
// speaker can rehearse them. Reached from the Script and Export stages.
// speaker can rehearse them. Reached from the Script and Finish stages.
import { useState } from 'react';
import { useApp } from '../context/AppContext.js';
import StudioShell from '../components/study/StudioShell.jsx';
+6 -6
View File
@@ -190,16 +190,16 @@ describe('Home page', () => {
});
// ---------------------------------------------------------------------------
// Export stage (useShareLink) and the shared read-only view
// Finish stage (useShareLink) and the shared read-only view
// ---------------------------------------------------------------------------
describe('Project header and sharing', () => {
const json = (status, data) => Promise.resolve({ ok: status < 400, status, json: () => Promise.resolve(data) });
test('Export stage → Markdown downloads a file', async () => {
test('Finish stage → Markdown downloads a file', async () => {
const user = await loadChapter();
addChunk('Paul, a servant', 'Paul, a servant');
await screen.findByText('1 created');
await user.click(screen.getByRole('button', { name: /^export$/i }));
await user.click(screen.getByRole('button', { name: /^finish$/i }));
await user.click(await screen.findByRole('button', { name: /export markdown/i }));
expect(URL.createObjectURL).toHaveBeenCalled();
});
@@ -216,7 +216,7 @@ describe('Project header and sharing', () => {
const user = await loadChapter();
addChunk('Paul, a servant', 'Paul, a servant');
await screen.findByText('1 created');
await user.click(screen.getByRole('button', { name: /^export$/i }));
await user.click(screen.getByRole('button', { name: /^finish$/i }));
await user.click(await screen.findByRole('button', { name: /enable sharing/i }));
expect(await screen.findByDisplayValue(/\?share=tok123$/)).toBeInTheDocument();
});
@@ -310,12 +310,12 @@ describe('Chunk builder', () => {
});
// ---------------------------------------------------------------------------
// Stage bar (Chunks / Study / Outline / Script / Export)
// Stage bar (Chunks / Study / Outline / Script / Finish)
// ---------------------------------------------------------------------------
describe('Stage bar', () => {
test('later stages are disabled until a chunk exists', async () => {
await loadChapter();
for (const name of [/^study$/i, /^outline$/i, /^script$/i, /^export$/i]) {
for (const name of [/^study$/i, /^outline$/i, /^script$/i, /^finish$/i]) {
expect(screen.getByRole('button', { name })).toBeDisabled();
}
expect(screen.getByRole('button', { name: /^chunks$/i })).not.toBeDisabled();
+1 -1
View File
@@ -26,7 +26,7 @@ describe('Back to the dashboard', () => {
await dashboard();
});
test.each(['Chunks', 'Study', 'Outline', 'Script', 'Export'])('the %s stage of a study', async (stage) => {
test.each(['Chunks', 'Study', 'Outline', 'Script', 'Finish'])('the %s stage of a study', async (stage) => {
const u = await loadChapter();
addChunk('Paul, a servant', 'In hope of eternal');
await screen.findByText('1 created');