"""Facility Executive persona. Features: - KPI dashboard (occupancy, ER avoidance, falls, compliance) - Risk heatmap across residents - Financial impact metrics - Staff efficiency analytics """ import streamlit as st import plotly.express as px import plotly.graph_objects as go import pandas as pd from data.synthetic import ( get_residents, get_facility_kpis, get_sensor_data, get_staff_metrics, get_ed_avoidance_data, get_age_in_place_scores, ) from components.chatbot import render_chatbot def render(): """Render the Facility Executive dashboard.""" st.title("Executive Intelligence Dashboard") kpis = get_facility_kpis() residents = get_residents() staff = get_staff_metrics() sensors = get_sensor_data(hours=48) # Top KPI row c1, c2, c3, c4, c5 = st.columns(5) with c1: st.metric("Occupancy", f"{kpis['occupancy_rate']}%", kpis["occupancy_delta"]) with c2: st.metric("ER Transfers", kpis["er_transfers_month"], kpis["er_transfers_delta"], delta_color="inverse") with c3: st.metric("Falls (Month)", kpis["falls_this_month"], kpis["falls_delta"], delta_color="inverse") with c4: st.metric("Family Satisfaction", f"{kpis['family_satisfaction']}/5.0", "+0.2") with c5: st.metric("Compliance", f"{kpis['regulatory_compliance_pct']}%", "+0.3%") st.divider() tab_ops, tab_risk, tab_ed, tab_aip, tab_finance, tab_staff, tab_chat = st.tabs([ "Operations", "Risk Overview", "🚑 ED Avoidance", "🏠 Age-in-Place", "Financial Impact", "Staff Analytics", "📊 Strategic Advisor", ]) # --- TAB: OPERATIONS --- with tab_ops: col1, col2 = st.columns(2) with col1: st.subheader("Mobility Trends (All Residents)") fig = px.area( sensors, x="Timestamp", y="Mobility_Index", title="Aggregate Mobility Index (48h)", template="plotly_white", ) fig.update_traces(line_color="#8b5cf6", fillcolor="rgba(139,92,246,0.1)") st.plotly_chart(fig, use_container_width=True) with col2: st.subheader("Social Engagement Trend") fig2 = px.bar( sensors.tail(24), x="Timestamp", y="Social_Engagement_Hrs", title="Communal Hours (Last 24h)", template="plotly_white", color="Social_Engagement_Hrs", color_continuous_scale="Teal", ) st.plotly_chart(fig2, use_container_width=True) st.subheader("Key Operational Metrics") op_col1, op_col2, op_col3, op_col4 = st.columns(4) with op_col1: st.metric("Avg Length of Stay", f"{kpis['avg_los_days']} days") with op_col2: st.metric("Infection Rate", f"{kpis['infection_rate_per_1000']}/1000") with op_col3: st.metric("Readmission Rate", f"{kpis['readmission_rate_pct']}%") with op_col4: st.metric("Staff Turnover", f"{kpis['staff_turnover_pct']}%") # --- TAB: RISK OVERVIEW --- with tab_risk: st.subheader("Resident Risk Heatmap") risk_data = pd.DataFrame([ { "Resident": r["name"], "Room": r["room"], "Unit": r["unit"], "Risk Level": r["risk_level"], "Wellness Score": r["wellness_score"], "Mobility": r["mobility_baseline"], "Diagnoses": ", ".join(r["diagnoses"][:2]), } for r in residents ]) # Color-coded risk table def highlight_risk(val): colors = {"High": "background-color: #fef2f2; color: #dc2626;", "Moderate": "background-color: #fffbeb; color: #d97706;", "Low": "background-color: #f0fdf4; color: #16a34a;"} return colors.get(val, "") styled = risk_data.style.applymap(highlight_risk, subset=["Risk Level"]) st.dataframe(styled, use_container_width=True, hide_index=True) st.divider() # Risk distribution col_r1, col_r2 = st.columns(2) with col_r1: risk_counts = risk_data["Risk Level"].value_counts().reset_index() risk_counts.columns = ["Risk Level", "Count"] fig_risk = px.pie( risk_counts, values="Count", names="Risk Level", title="Risk Distribution", color="Risk Level", color_discrete_map={"High": "#ef4444", "Moderate": "#f59e0b", "Low": "#10b981"}, template="plotly_white", ) st.plotly_chart(fig_risk, use_container_width=True) with col_r2: fig_well = px.bar( risk_data, x="Resident", y="Wellness Score", title="Wellness Scores by Resident", color="Wellness Score", color_continuous_scale="RdYlGn", template="plotly_white", ) fig_well.add_hline(y=85, line_dash="dash", line_color="green", annotation_text="Target") st.plotly_chart(fig_well, use_container_width=True) # High risk alerts high_risk = [r for r in residents if r["risk_level"] == "High"] if high_risk: st.error( f"**{len(high_risk)} High-Risk Resident(s):** " + ", ".join(f"{r['name']} (Room {r['room']})" for r in high_risk), icon="🚨", ) # --- TAB: ED AVOIDANCE INTELLIGENCE --- with tab_ed: st.subheader("ED Avoidance Intelligence") st.caption( "Track emergency department transfers avoided through proactive AI-powered interventions. " "Relief from acuity burden with predictive clinical care." ) ed_data = get_ed_avoidance_data() # Top metrics ed1, ed2, ed3, ed4 = st.columns(4) with ed1: st.metric("ED Transfers (Month)", ed_data["ed_transfers"][-1], "-5 vs 6mo ago", delta_color="inverse") with ed2: st.metric("ED Avoidances (Month)", ed_data["ed_avoidances"][-1], "+6 vs 6mo ago") with ed3: total_savings = sum(ed_data["savings_per_month"]) st.metric("Total Savings (6mo)", f"${total_savings:,}") with ed4: avoidance_rate = ed_data["ed_avoidances"][-1] / (ed_data["ed_transfers"][-1] + ed_data["ed_avoidances"][-1]) * 100 st.metric("Avoidance Rate", f"{avoidance_rate:.0f}%") # Charts ed_col1, ed_col2 = st.columns(2) with ed_col1: ed_df = pd.DataFrame({ "Month": ed_data["months"], "ED Transfers": ed_data["ed_transfers"], "Avoided": ed_data["ed_avoidances"], }) fig_ed = px.bar( ed_df, x="Month", y=["ED Transfers", "Avoided"], title="ED Transfers vs. AI-Prevented Transfers", barmode="group", color_discrete_map={"ED Transfers": "#ef4444", "Avoided": "#10b981"}, template="plotly_white", ) st.plotly_chart(fig_ed, use_container_width=True) with ed_col2: fig_sav = px.area( x=ed_data["months"], y=ed_data["savings_per_month"], title="Monthly ED Avoidance Savings ($)", labels={"x": "Month", "y": "Savings ($)"}, template="plotly_white", ) fig_sav.update_traces(line_color="#10b981", fillcolor="rgba(16,185,129,0.15)") st.plotly_chart(fig_sav, use_container_width=True) # Top avoidance reasons st.markdown("**Top ED Avoidance Categories (6 Months)**") for item in ed_data["top_avoidance_reasons"]: r_col1, r_col2, r_col3 = st.columns([4, 1, 1]) with r_col1: st.markdown(f"**{item['reason']}**") with r_col2: st.metric("Count", item["count"], label_visibility="collapsed") with r_col3: st.metric("Saved", f"${item['savings']:,}", label_visibility="collapsed") st.divider() # Recent interventions st.markdown("**This Month's Interventions**") for intervention in ed_data["interventions_this_month"]: with st.expander(f"✅ {intervention['resident']} — {intervention['type']} (Saved {intervention['savings']})"): st.markdown(intervention["action"]) # --- TAB: AGE-IN-PLACE --- with tab_aip: st.subheader("Age-in-Place Stability Index") st.caption( "Measure how effectively each resident is aging in place. " "Higher scores indicate greater stability and longer projected stays." ) aip_scores = get_age_in_place_scores() # Summary metrics avg_score = sum(s["score"] for s in aip_scores) / len(aip_scores) high_risk = [s for s in aip_scores if s["risk_of_transfer"] in ("Moderate", "High")] aip_c1, aip_c2, aip_c3 = st.columns(3) with aip_c1: st.metric("Avg Age-in-Place Score", f"{avg_score:.0f}/100") with aip_c2: st.metric("At-Risk Residents", len(high_risk), delta_color="inverse") with aip_c3: avg_los = sum(s["projected_los_months"] for s in aip_scores) / len(aip_scores) st.metric("Avg Projected Stay", f"{avg_los:.0f} months") st.divider() # Resident-by-resident breakdown for aip in aip_scores: score_color = "#10b981" if aip["score"] >= 75 else "#f59e0b" if aip["score"] >= 50 else "#ef4444" trend_icon = {"stable": "➡️", "improving": "📈", "declining": "📉"}.get(aip["trend"], "") with st.expander( f"{trend_icon} {aip['resident']} (Room {aip['room']}) — " f"Score: {aip['score']}/100 | Transfer Risk: {aip['risk_of_transfer']}", expanded=(aip["risk_of_transfer"] != "Low"), ): aip_left, aip_right = st.columns([1, 2]) with aip_left: st.markdown( f"""
{aip['score']}
Age-in-Place Score