You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
motief/.mindmodel/examples/streamlit-page-example.py

316 lines
8.7 KiB

"""Example: Streamlit page patterns - from actual pages/ files."""
import streamlit as st
# =============================================================================
# Example 1: Home page (Home.py)
# =============================================================================
def render_home_page():
"""Simplified version of Home.py."""
st.set_page_config(
page_title="Motief: de stematlas",
page_icon="🗺",
layout="centered",
initial_sidebar_state="expanded",
)
st.title("🗺 Motief: de stematlas")
st.markdown(
"**Motief** brengt de Nederlandse Tweede Kamer in kaart op basis van "
"echte stemmingen over moties. Gebruik de Stemwijzer om te ontdekken welke "
"partij het beste bij jouw standpunten past, of verken de politieke ruimte "
"zelf in de Explorer."
)
st.divider()
col1, col2 = st.columns(2)
with col1:
st.subheader("🗳 Stemwijzer")
st.markdown(
"Stem op echte Tweede Kamer moties en zie welke partij het "
"dichtst bij jouw keuzes staat."
)
st.page_link("pages/1_Stemwijzer.py", label="Open Stemwijzer", icon="🗳")
with col2:
st.subheader("🔭 Politiek Explorer")
st.markdown(
"Verken het politieke kompas, partijtrajecten door de tijd, "
"en zoek vergelijkbare moties op in het archief."
)
st.page_link("pages/2_Explorer.py", label="Open Explorer", icon="🔭")
st.divider()
st.caption("Data: Tweede Kamer API · Embeddings: QWEN (via OpenRouter)")
# =============================================================================
# Example 2: Thin page wrapper (pages/1_Stemwijzer.py)
# =============================================================================
def render_stemwijzer_page():
"""Pattern: thin page that delegates to module function."""
st.set_page_config(
page_title="Stemwijzer",
page_icon="🗳",
layout="centered",
)
# Delegate to main module
from explorer import build_mp_quiz_tab
build_mp_quiz_tab("data/motions.db")
# =============================================================================
# Example 3: Session state initialization
# =============================================================================
def init_session_state():
"""Pattern: Initialize all session state at start."""
defaults = {
"session_id": None,
"current_motion_index": 0,
"motions": [],
"show_results": False,
"user_votes": {},
}
for key, default in defaults.items():
if key not in st.session_state:
st.session_state[key] = default
# =============================================================================
# Example 4: Sidebar configuration
# =============================================================================
def render_sidebar():
"""Pattern: Sidebar for configuration."""
with st.sidebar:
st.header("Instellingen")
motion_count = st.slider(
"Aantal moties",
min_value=5,
max_value=25,
value=10,
help="Hoeveel moties wilt u beantwoorden?",
)
policy_area = st.selectbox(
"Beleidsgebied",
[
"Alle",
"Economie",
"Klimaat",
"Immigratie",
"Zorg",
"Onderwijs",
"Defensie",
"Sociale Zaken",
"Algemeen",
],
)
margin_range = st.slider(
"Controversiële moties (%)",
min_value=0,
max_value=100,
value=(0, 100),
help="Filter op hoe omstreden de moties zijn",
)
st.divider()
if st.button("Start Nieuwe Sessie", type="primary"):
return {
"motion_count": motion_count,
"policy_area": policy_area,
"margin_range": margin_range,
}
return None
# =============================================================================
# Example 5: Motion voting interface
# =============================================================================
def render_motion_vote(motion: dict, index: int, total: int):
"""Pattern: Display motion and voting buttons."""
st.subheader(f"Motie {index + 1} van {total}")
# Motion content
st.markdown(f"### {motion['title']}")
col1, col2 = st.columns([3, 1])
with col1:
if motion.get("layman_explanation"):
st.info(motion["layman_explanation"])
with st.expander("Meer details"):
st.markdown(f"**Datum:** {motion.get('date', 'Onbekend')}")
st.markdown(f"**Beleidsgebied:** {motion.get('policy_area', 'Onbekend')}")
if motion.get("description"):
st.markdown(f"**Beschrijving:** {motion['description']}")
with col2:
st.metric(
label="Winstmarge",
value=f"{motion.get('winning_margin', 0):.0%}",
delta="Omstreden" if motion.get("controversy_score", 0) > 0.5 else "Helder",
)
st.divider()
# Voting buttons
col1, col2, col3 = st.columns(3)
with col1:
st.button(
"👍 **Voor**",
on_click=on_vote,
args=(motion["id"], "Voor"),
use_container_width=True,
)
with col2:
st.button(
"👎 **Tegen**",
on_click=on_vote,
args=(motion["id"], "Tegen"),
use_container_width=True,
)
with col3:
st.button(
"🤔 **Onthouden**",
on_click=on_vote,
args=(motion["id"], "Onthouden"),
use_container_width=True,
)
def on_vote(motion_id: int, vote: str):
"""Callback when user votes."""
# Record vote
from database import db
db.record_vote(
session_id=st.session_state.session_id, motion_id=motion_id, vote=vote
)
# Update session state
st.session_state.user_votes[motion_id] = vote
# Move to next or show results
if st.session_state.current_motion_index < len(st.session_state.motions) - 1:
st.session_state.current_motion_index += 1
else:
st.session_state.show_results = True
st.rerun()
# =============================================================================
# Example 6: Results display
# =============================================================================
def render_results():
"""Pattern: Display voting results."""
from database import db
st.header("📊 Uw Resultaten")
# Get party results
results = db.get_party_results(st.session_state.session_id)
if not results:
st.warning("Geen resultaten beschikbaar")
return
# Sort by agreement
sorted_results = sorted(
results.items(), key=lambda x: x[1].get("agreement_percentage", 0), reverse=True
)
# Display top match
if sorted_results:
top_party, top_data = sorted_results[0]
st.success(
f"**Uw beste match:** {top_party} ({top_data.get('agreement_percentage', 0):.0%} overeenstemming)"
)
st.divider()
# Show all parties
for party, data in sorted_results:
agreement = data.get("agreement_percentage", 0)
col1, col2 = st.columns([3, 1])
with col1:
st.markdown(f"**{party}**")
st.progress(agreement, text=f"{agreement:.0%}")
with col2:
st.metric("Overeenstemming", f"{agreement:.0%}")
# Detailed breakdown
with st.expander("Details per motie"):
for motion in st.session_state.motions:
user_vote = st.session_state.user_votes.get(motion["id"], "?")
st.markdown(f"- **{motion['title']}**: U={user_vote}")
# =============================================================================
# Example 7: Tabs layout
# =============================================================================
def render_tabs_example():
"""Pattern: Use tabs for organizing content."""
tab1, tab2, tab3 = st.tabs(["Compass", "Trajectories", "Zoeken"])
with tab1:
st.subheader("Politiek Kompas")
st.write("Visualiseer partijposities in 2D ruimte")
# Add compass chart...
with tab2:
st.subheader("Partij Trajectories")
st.write("Bekijk hoe partijen door de tijd bewegen")
# Add trajectory chart...
with tab3:
st.subheader("Zoek Moties")
query = st.text_input("Zoekterm")
if query:
# Search functionality...
st.write(f"Zoeken naar: {query}")
if __name__ == "__main__":
# Demo rendering
init_session_state()
st.write("Streamlit page structure example")