NutriWeb / views /profile_page.py
Krish264's picture
Deploy: Pin Streamlit to 1.61.1; add deployment parity tests
89d9642
Raw
History Blame Contribute Delete
5.35 kB
"""Profile — sign in, and set the preferences that drive every filter."""
from __future__ import annotations
import streamlit as st
from nutriweb.profile import auth
from nutriweb.profile.model import ALLERGEN_CHOICES, DIET_CHOICES, UserProfile
from views import state
st.markdown(
"""<div class="nw-hero">
<h1>My profile</h1>
<p>Everything here is used as a hard filter: allergens and diet exclude
products outright rather than merely ranking them lower.</p>
</div>""",
unsafe_allow_html=True,
)
profile: UserProfile = state.profile()
if auth.demo_mode():
st.caption(
"No account database is configured, so profiles last for this session only. "
"Set `MONGODB_URI` as a Space secret to persist them."
)
def _preferences_form(current: UserProfile, key_prefix: str) -> UserProfile:
"""The shared preference widgets. Returns a profile built from the inputs."""
label_for_tag = {v: k for k, v in ALLERGEN_CHOICES.items()}
selected_labels = st.multiselect(
"Allergens to avoid",
list(ALLERGEN_CHOICES),
default=[label_for_tag[t] for t in current.allergens if t in label_for_tag],
key=f"{key_prefix}_allergens",
help="Matched against Open Food Facts' curated allergen and traces tags.",
)
diets = st.multiselect(
"Dietary preferences",
DIET_CHOICES,
default=current.diets,
key=f"{key_prefix}_diets",
)
col1, col2 = st.columns(2)
with col1:
age = st.number_input("Age", 1, 120, current.age, key=f"{key_prefix}_age")
high_bp = st.checkbox(
"High blood pressure", current.high_blood_pressure, key=f"{key_prefix}_bp",
help="Flags and filters products above 1.15 g salt per 100 g.",
)
with col2:
gender = st.selectbox(
"Gender",
["Prefer not to say", "Female", "Male", "Other"],
index=["Prefer not to say", "Female", "Male", "Other"].index(current.gender)
if current.gender in ["Prefer not to say", "Female", "Male", "Other"] else 0,
key=f"{key_prefix}_gender",
)
high_chol = st.checkbox(
"High cholesterol", current.high_cholesterol, key=f"{key_prefix}_chol",
help="Flags and filters products above 4 g saturated fat per 100 g.",
)
avoid_additives = st.checkbox(
"Exclude products with additives EFSA flags as high-risk",
current.avoid_flagged_additives,
key=f"{key_prefix}_additives",
)
return UserProfile(
user_id=current.user_id,
age=int(age),
gender=gender,
allergens=[ALLERGEN_CHOICES[label] for label in selected_labels],
diets=diets,
high_blood_pressure=high_bp,
high_cholesterol=high_chol,
avoid_flagged_additives=avoid_additives,
)
if profile.user_id:
st.success(f"Signed in as **{profile.user_id}**")
with st.form("prefs"):
updated = _preferences_form(profile, "signed")
if st.form_submit_button("Save preferences", type="primary"):
updated.user_id = profile.user_id
st.session_state.profile = updated
auth.save_profile(updated)
st.toast("Preferences saved.")
st.divider()
st.markdown("### Recently viewed")
history = auth.recent_views(profile.user_id)
if not history:
st.caption("Nothing viewed yet.")
else:
for entry in history[:15]:
st.markdown(
f"- **{entry.get('product_name') or 'Unnamed'}** "
f"<span class='nw-sub'>{entry.get('brands') or ''} · "
f"{entry.get('verdict') or ''}</span>",
unsafe_allow_html=True,
)
st.stop()
tab_guest, tab_login, tab_register = st.tabs(
["Use without an account", "Sign in", "Create account"]
)
with tab_guest:
st.caption(
"Set preferences for this session only. Nothing is stored and no account is needed."
)
with st.form("guest"):
guest_profile = _preferences_form(profile, "guest")
if st.form_submit_button("Apply", type="primary"):
st.session_state.profile = guest_profile
st.toast("Preferences applied for this session.")
st.rerun()
with tab_login:
with st.form("login"):
user_id = st.text_input("Username")
password = st.text_input("Password", type="password")
if st.form_submit_button("Sign in", type="primary"):
result = auth.login(user_id, password)
if result.ok:
st.session_state.profile = result.profile
st.rerun()
else:
st.error(result.message)
with tab_register:
with st.form("register"):
new_id = st.text_input("Choose a username")
new_pw = st.text_input("Choose a password", type="password", help="At least 8 characters.")
new_profile = _preferences_form(UserProfile(), "reg")
if st.form_submit_button("Create account", type="primary"):
result = auth.register(new_id, new_pw, new_profile)
if result.ok:
st.session_state.profile = result.profile
st.success(result.message)
st.rerun()
else:
st.error(result.message)