// АРМ курсанта: приём вызова и разговор голосом. // Карточка КИО — lct-10, таймеры — lct-11. import { useState } from "react"; import { KioCard } from "@/features/kio-card/KioCard"; import { StandStatus } from "@/features/health/StandStatus"; import { ModeBanner, hintsAllowed } from "@/features/mode-banner/ModeBanner"; import { Debrief } from "@/features/debrief/Debrief"; import { SelfAssessment } from "@/features/self-assessment/SelfAssessment"; import { InterviewTimer, Timers } from "@/features/timers/Timers"; import { display } from "@/features/kio-card/merge"; import { useCall } from "@/features/call/useCall"; import { sessionIdFromUrl } from "@/shared/api/session"; import type { DDSCode } from "@/shared/types/generated"; const STATUS_LABEL: Record = { connecting: "подключение", open: "на связи", reconnecting: "связь потеряна, переподключение", closed: "отключено", }; const RESOLVE_LABELS = { consultation: "справочно-консультационная помощь", transfer_region: "передан в систему-112 другого региона", } as const; function ddsCode(value: unknown): DDSCode | undefined { return value === "01" || value === "02" || value === "03" || value === "04" || value === "gkh" ? value : undefined; } export function Call() { const [resolveComment, setResolveComment] = useState(""); const [resolved, setResolved] = useState<"consultation" | "transfer_region" | null>(null); const sessionId = sessionIdFromUrl(); const call = useCall(sessionId); if (!sessionId) { return (

АРМ курсанта

В адресе нет номера занятия: откройте ссылку вида /trainee?session=…

); } if (call.briefing) { return

АРМ оператора 112 · учебная карточка

Текстовое упражнение: входящий голосовой вызов и микрофон не используются.

Канал{STATUS_LABEL[call.status]}
Сценарий{call.briefing.scenario_id}
Состояние{call.cardSubmitted ? "карточка отправлена на оценку" : "карточка заполняется"}

Вводная о происшествии

{call.briefing.text}

Извлеките сведения из вводной, заполните поля карточки и проверьте предлагаемый список оповещения.

Карточка информационного обмена

{!call.cardSubmitted &&

} {call.error &&

{call.error}

} {call.cardSubmitted && !call.report && !call.reportError &&

Карточка отправлена. Ожидаем итоговую оценку…

} {call.reportError &&

{call.reportError}

}
{call.report && }
; } const service = ddsCode(display(call.card, "dds")); const notify = display(call.card, "notify"); const autoRoute = Boolean(display(call.card, "incident_code")) && Array.isArray(notify) && notify.length > 0; return (

АРМ оператора 112

Канал{STATUS_LABEL[call.status]}
Вызов{call.incoming ? `${call.incoming.caller_number} · сценарий ${call.incoming.scenario_id} · режим ${call.incoming.mode}` : "ожидание"}
Гарнитура{call.micOn ? "микрофон включён" : "выключен"}
Звонящий{call.callerSpeaking ? "говорит" : "молчит"}

{call.phase === "incoming" && !call.micOn && ( )} {call.micOn && }{" "} {call.micOn && hintsAllowed(call.incoming?.mode) && ( )}

{call.error &&

{call.error}

} {call.phase === "ended" && !call.selfAssessed && call.checklist.length > 0 && ( )} {call.selfAssessed && !call.report &&

Самооценка принята, оценка считается…

} {call.report && }

Карточка информационного обмена

{/* Не каждый вызов заканчивается карточкой: справка и чужой регион — отдельные исходы, и курсант выбирает их сам (docs/spec/TICKETS.md). */}
Закрыть вызов без карточки

setResolveComment(event.target.value)} />

{" "}

{resolved &&

Вызов закрыт: {RESOLVE_LABELS[resolved]}

}

Нормативы

Разговор

{call.lines.map((line, index) => ( ))} {call.lines.length === 0 && }
{line.speaker === "caller" ? "звонящий" : "оператор"} {line.text}
—
); }