Tester #5506 §5: the existing test only asserted the final 'saved'
state, which would also pass if the hook skipped the saving state
altogether. Hold the second mocked saveFn promise so we can assert the
intermediate transition.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Locks in the behaviour added with the saveFn signature widening: a
rejected save keeps the in-flight payload around so handleRetry resends
it without the caller having to re-pass anything.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TranscriptionBlockData now carries mentionedPersons (matches backend
schema added in PR-A).
- useBlockAutoSave.saveFn signature widens to (blockId, text, mentions);
pendingMentions is tracked alongside pendingTexts and is preserved on
failure so a retry resends the in-flight payload (B12).
- TranscriptionBlock.svelte renders <PersonMentionEditor>, exposing the
textarea node back through a captureTextarea callback so the existing
quote-selection feature still works.
- saveBlock in routes/documents/[id]/+page.svelte forwards mentions on
PUT.
- flushOnUnload sends mentions in the keepalive payload too.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The sendBeacon name was misleading after switching to keepalive fetch.
Also adds a test to confirm flush is a no-op when pendingTexts is empty.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sendBeacon always sends POST, but the backend expects PUT for block updates, so
saves were silently dropped on page unload. Replace with fetch({ keepalive: true,
method: 'PUT' }) which survives navigation and uses the correct HTTP method.
Add a catch-all SvelteKit server route at /api/[...path] so all client-side API
calls work in production (without the Vite dev proxy). More-specific routes
(/api/persons, /api/tags, /api/documents/[id]/file) keep precedence.
Closes#204
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>