import { AlertTriangle, Check, CloudOff, Eye, RefreshCw } from 'lucide-react' import type { BookRecord } from '@trek/shared' import type { SaveState } from './useBookStore' /** * Whether the book is safe. * * Autosave without a sign of it is a promise you are asking someone to take on * faith, and the moment they do not is the moment they close the tab to check. * So: a tick when it is written, a spinner while it is being written, and — the * one that matters — a real choice when someone else got there first. * * Quiet by design. This sits in the top bar of an editor, and a status that * announces every successful save is a status people learn to stop reading, * which is exactly the wrong habit for the one time it says something else. */ export function SaveIndicator({ state, t, onAcceptTheirs, onKeepMine, onRetry, }: { state: SaveState t: (k: string) => string onAcceptTheirs: (current: BookRecord) => void onKeepMine: (current: BookRecord) => void onRetry: () => void }) { if (state.status === 'conflict') { return (
{t('journey.studio.saveConflict')} {/* Two ways out, both stated plainly. There is no merge here and pretending otherwise would be worse than saying so: one of these documents is going to be the book. */}
) } if (state.status === 'readonly') { /* * Not an error and not retryable: this person was invited to read the * journey, not to write it. Said once, plainly, and left standing — the * alternative is an editor that looks like it is saving and is not. */ return (
{t('journey.studio.saveReadOnly')}
) } if (state.status === 'error') { return ( ) } if (state.status === 'saving') { return (
{t('journey.studio.saving')}
) } if (state.status === 'saved') { return (
{t('journey.studio.saved')}
) } return null }