textmachine/frontend/src/showcase/Status.tsx

55 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { pausedReason as pausedReasonWords } from '../api';
import type { Book, ConnectionState, Run } from '../api';
import { languageName, remaining, translatedPercent } from './format';
import styles from './Status.module.css';
interface Props {
book?: Book;
run: Run | null;
connection: ConnectionState;
chapter: string;
}
/**
* The status bar. One fraction and no phase names: what happens inside the pipeline is not the
* user's business (prompt §4.1). The phasing stays where it belongs — in the data and in the sum —
* because a per-phase fraction would read zero for the whole draft wave.
*/
export function Status({ book, run, connection, chapter }: Props) {
const paused = run?.status === 'paused';
const eta = remaining(book?.progress.eta_seconds);
return (
<>
<span>
{book?.title ?? '—'}
{chapter !== '' && ` / ${chapter}`}
</span>
<span className={styles.right}>
{paused ? (
// A ceiling stop is resumable, so it is stated as a fact and not as a failure. The phrase
// is the owner's; the API carries only the machine reason.
<span className={styles.paused}>
{pausedReasonWords.describe(run.paused_reason).label}
</span>
) : (
book && <span>переведено {translatedPercent(book.progress)}%</span>
)}
{/* `null` is a legal value, not just an absent field: there is nothing to estimate from
before the first calls of a wave, and a bare "осталось" with no number is worse than
saying nothing. */}
{!paused && eta !== null && <span>осталось {eta}</span>}
{/* Losing the live channel is its own state: the reads still work, so the screen must say
the numbers have stopped moving rather than let a frozen counter look healthy. */}
{(connection === 'lost' || connection === 'refused') && (
<span className={styles.offline}>живой прогресс недоступен</span>
)}
{book && (
<span>
{languageName(book.source_lang)} {languageName(book.target_lang)}
</span>
)}
</span>
</>
);
}