Files
PTSRaiAgent/dashboard/pages/3_Сплит-экран.py
T
Pavel Eliseev 2a2fdb171e
CI / ruff · pytest (pull_request) Successful in 2m16s
feat(ui): extend minimal doctor design across all screens
Refs #85
2026-10-04 16:09:57 +03:00

59 lines
2.5 KiB
Python

"""Split screen for the projector (#17): patient on the left, doctor on the right, clock on top.
Left: the patient web app in an iframe when `PATIENT_WEB_URL` is set (React app, e.g. http://localhost:5173),
otherwise the console's fallback web chat. Right: compact doctor panel polled every 2 s with a red banner
on a new acute alert.
"""
import sys
from pathlib import Path
import streamlit as st
# `streamlit run dashboard/app.py` already puts dashboard/ on sys.path; this keeps the page runnable on its own.
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from console import widgets as w # noqa: E402
from dashboard import theme # noqa: E402
from dashboard.components import ui # noqa: E402
st.set_page_config(page_title="Сплит-экран", page_icon="🖥️", layout="wide", initial_sidebar_state="collapsed")
st.html(theme.CSS)
st.html(ui.page_header("Сплит-экран", "Пациент и врач: сопровождение в реальном времени.", kicker="Демонстрация"))
persona = w.select_persona()
w.show_flash()
token = persona["token"]
top, play = st.columns([6, 1.3], vertical_alignment="center")
with top:
w.render_clock_bar(persona, key="split-clock", with_reset=False)
with play:
scenario, _ = w.scenario_for(persona)
runner = w.make_runner(persona, delay=0.8)
nxt = runner.next_day(scenario) if scenario.days else None
clicked = st.button(
f"▶ Сценарий: день {nxt.day}" if nxt else "Сценарий проигран",
disabled=nxt is None,
width="stretch",
help="Проиграть следующий день из data/synthetic/<персона>.jsonl",
)
if clicked and nxt is not None:
w.execute(runner.play_day(scenario, nxt.day), w.playback_state(token), title=f"День {nxt.day}")
st.rerun()
left, right = st.columns([1.1, 1], gap="large")
with left, st.container(border=True, key="panel-split-patient"):
url = w.patient_web_url()
if url:
st.markdown(f"#### Пациент — {persona.get('display_name') or token}")
st.iframe(url, height=760)
st.caption(f"Веб-приложение пациента: {url}")
else:
st.markdown(f"#### Пациент — {persona.get('display_name') or token}")
w.render_chat(token, height=600, key="split-chat")
with right, st.container(border=True, key="panel-split-doctor"):
st.markdown("#### Кабинет врача — д-р Смирнова Е. А.")
w.polled_doctor_panel(token, key="split-doc")