TheQuantEd's picture
deploy: AMD EA Strategy Optimizer — Neo4j + FastAPI + Streamlit
6252f54
"""Hierarchical questionnaire — Domain → Capability Area → Capability → Constraints."""
import streamlit as st
from frontend.utils.api_client import get_domains, get_subdomains, get_subdomain_capabilities
from frontend.utils.terminology import domain_label, subdomain_label
def render_input_form() -> dict | None:
"""Render hierarchical questionnaire. Returns payload dict when submitted."""
st.subheader("Build Your Strategic Context")
st.caption(
"Select your organisation's focus areas step by step — "
"the AI will generate a governance-grounded roadmap tailored to your selection."
)
# ── Step 1: Domain ─────────────────────────────────────────────────────
st.markdown("##### Step 1 — Select Strategic Domains")
all_domains = st.session_state.get("_domains_cache") or get_domains()
st.session_state["_domains_cache"] = all_domains
domain_label_to_raw: dict[str, str] = {
domain_label(d["name"]): d["name"] for d in all_domains
}
domain_raw_to_obj: dict[str, dict] = {d["name"]: d for d in all_domains}
selected_domain_labels = st.multiselect(
"Strategic Domains",
options=sorted(domain_label_to_raw.keys()),
default=st.session_state.get("_sel_domain_labels", []),
help="Choose the enterprise domains relevant to your organisation",
key="sel_domains",
)
st.session_state["_sel_domain_labels"] = selected_domain_labels
selected_domain_names = [domain_label_to_raw[l] for l in selected_domain_labels]
# ── Step 2: Capability Areas (SubDomains) ──────────────────────────────
selected_subdomain_ids: list[str] = []
if selected_domain_names:
st.markdown("##### Step 2 — Select Capability Areas")
cache_key_sd = "subdomains_" + "_".join(sorted(selected_domain_names))
subdomains = st.session_state.get(cache_key_sd)
if subdomains is None:
subdomains = get_subdomains(selected_domain_names)
st.session_state[cache_key_sd] = subdomains
sd_label_to_obj: dict[str, dict] = {
subdomain_label(sd["name"]): sd for sd in subdomains
}
selected_sd_labels = st.multiselect(
"Capability Areas",
options=sorted(sd_label_to_obj.keys()),
default=sorted(sd_label_to_obj.keys()),
help="Capability areas within your selected domains",
key="sel_subdomains",
)
selected_subdomain_ids = [sd_label_to_obj[l]["id"] for l in selected_sd_labels if l in sd_label_to_obj]
# ── Step 3: Capabilities ────────────────────────────────────────────
selected_cap_ids: list[str] = []
if selected_subdomain_ids:
st.markdown("##### Step 3 — Select Strategic Capabilities")
cache_key_caps = "caps_" + "_".join(sorted(selected_subdomain_ids))
capabilities = st.session_state.get(cache_key_caps)
if capabilities is None:
capabilities = get_subdomain_capabilities(selected_subdomain_ids)
st.session_state[cache_key_caps] = capabilities
# Group by subdomain for display
if capabilities:
cap_id_to_obj: dict[str, dict] = {c["id"]: c for c in capabilities}
cap_options = [c["name"] for c in capabilities]
selected_cap_names = st.multiselect(
f"Strategic Capabilities ({len(cap_options)} available)",
options=cap_options,
default=cap_options,
help="Select the specific capabilities to include in your roadmap",
key="sel_caps",
)
selected_cap_ids = [
c["id"] for c in capabilities if c["name"] in selected_cap_names
]
complexity_map = {c["name"]: c.get("complexity", "") for c in capabilities}
if selected_cap_names:
high = sum(1 for n in selected_cap_names if complexity_map.get(n) in ("high", "very_high"))
med = sum(1 for n in selected_cap_names if complexity_map.get(n) == "medium")
low = sum(1 for n in selected_cap_names if complexity_map.get(n) == "low")
st.caption(f"Selected: {len(selected_cap_names)} capabilities · 🔴 {high} high · 🟡 {med} medium · 🟢 {low} low complexity")
else:
st.info("No capabilities found for selected areas.")
selected_cap_ids = []
else:
selected_cap_ids = []
else:
selected_cap_ids = []
st.divider()
# ── Step 4: Organisation & Constraints ─────────────────────────────────
st.markdown("##### Step 4 — Organisation Context & Constraints")
with st.form("analyze_form"):
col_left, col_right = st.columns(2)
with col_left:
org_type = st.text_input(
"Organisation Type",
placeholder="e.g. Commercial Bank, Healthcare Provider, Government Agency",
help="Describe your organisation — used to tailor AI output language and governance references",
)
budget_tier = st.select_slider(
"Budget Tier",
options=["low", "medium", "high"],
value="medium",
)
risk_tolerance = st.select_slider(
"Risk Tolerance",
options=["low", "medium", "high"],
value="medium",
)
with col_right:
timeline_months = st.slider(
"Timeline (months)",
min_value=6,
max_value=36,
value=18,
step=3,
)
goals_text = st.text_area(
"Additional Strategic Goals (optional)",
height=100,
placeholder="e.g. Achieve ISO 27001 certification, Deploy AI-driven fraud detection",
help="Supplements the capability selection above",
)
submitted = st.form_submit_button(
"Generate Strategic Roadmap",
type="primary",
width='stretch',
)
if submitted:
if not org_type.strip():
st.error("Please enter your Organisation Type.")
return None
if not selected_cap_ids and not selected_domain_names:
st.error("Please select at least one Strategic Domain in Step 1.")
return None
extra_goals = [g.strip() for g in goals_text.split(",") if g.strip()] if goals_text else []
goals = extra_goals or [f"Transform {org_type} digital capabilities"]
return {
"org_type": org_type.strip(),
"goals": goals,
"budget_tier": budget_tier,
"timeline_months": timeline_months,
"risk_tolerance": risk_tolerance,
"sector_focus": selected_domain_names,
"selected_capability_ids": selected_cap_ids,
"selected_subdomain_ids": selected_subdomain_ids,
}
return None