59 lines
2.5 KiB
Python
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")
|