lct-10: карточка КИО — форма, слияние правок, read-only

Фронт не хранит карточку как истину: локально живут только правки
курсанта, ещё не подтверждённые сервером. Распознанное сервером значение
перекрывает набранное, эхо своей правки её подтверждает. Иначе
автозаполнение и ручной ввод дерутся за одно поле — худший класс багов
для отладки в последнюю ночь.

Описание полей отдельно от отрисовки: по нему же карточка рисуется
read-only на мониторе, пульте и АРМ ДДС.

Сверка формы с контрактом встроена в make typecheck: все 40 полей
домена на форме, а поле, добавленное в контракт и забытое в форме,
теперь поймается само. Это пропущенный факт по вине интерфейса,
а не курсанта.

Открытый вопрос в карточке: нужно ли автозаполнение карточки из речи
вообще — полнота КИО оценивается кодом E5, и если сервер впишет адрес
сам, курсант перестанет за неё отвечать.
This commit is contained in:
Ivan Gerasimov 2026-09-17 21:16:51 +03:00
commit 48c936ea6e
8 changed files with 454 additions and 3 deletions

View file

@ -1,6 +1,8 @@
// АРМ курсанта: приём вызова и разговор голосом.
// Карточка КИО — lct-10, таймеры — lct-11.
import { KioCard } from "@/features/kio-card/KioCard";
import { display } from "@/features/kio-card/merge";
import { useCall } from "@/features/call/useCall";
import { sessionIdFromUrl } from "@/shared/api/session";
@ -48,6 +50,26 @@ export function Call() {
{call.error && <p className="violated">{call.error}</p>}
<div className="columns">
<section>
<h2>Карточка информационного обмена</h2>
<KioCard
state={call.card}
required={call.incoming?.required_fields ?? []}
readOnly={!call.micOn}
onChange={call.patchKio}
/>
<p>
<button
type="button"
disabled={!call.micOn || !display(call.card, "dds")}
onClick={() => call.dispatch(display(call.card, "dds") as never)}
>
Передать в ДДС
</button>
</p>
</section>
<section>
<h2>Разговор</h2>
<table className="grid">
<tbody>
@ -60,6 +82,8 @@ export function Call() {
{call.lines.length === 0 && <tr><td colSpan={2}>—</td></tr>}
</tbody>
</table>
</section>
</div>
</main>
);
}