File size: 2,598 Bytes
89d9642 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | """Search — the landing page."""
from __future__ import annotations
import streamlit as st
from components import cards
from nutriweb.data import catalog
from views import state
st.markdown(
"""<div class="nw-hero">
<h1>Find a product, get a healthier swap</h1>
<p>Search by name or scan a barcode. Every result is checked against your
allergens, your diet and your health profile before it is recommended.</p>
</div>""",
unsafe_allow_html=True,
)
@st.cache_data(show_spinner=False, ttl=600)
def _search(query: str, limit: int) -> list[dict]:
return catalog.search(query, limit=limit)
@st.cache_data(show_spinner=False)
def _stats() -> dict:
return catalog.stats()
def _use_example(example: str) -> None:
"""Fill the search box from an example chip."""
st.session_state.search_box = example
query = st.text_input(
"Search",
placeholder="e.g. peanut butter, greek yogurt, or a barcode like 0049000028911",
label_visibility="collapsed",
key="search_box",
)
if not query:
stats = _stats()
st.caption(
f"{stats['products']:,} US products · {stats['scored']:,} with a health score · "
f"{stats['graded_by_nutriweb']:,} graded by NutriWeb where Open Food Facts had no grade"
)
st.markdown("##### Try one of these")
examples = ["greek yogurt", "peanut butter", "granola bar", "tortilla chips", "sparkling water"]
columns = st.columns(len(examples))
for column, example in zip(columns, examples):
# Seeding must happen in an on_click callback, not in the button's
# if-branch: Streamlit refuses assignment to a widget's key once that
# widget has been instantiated this run, and search_box is created
# above. Callbacks run before the rerun, so the assignment is legal.
column.button(
example,
width="stretch",
key=f"eg_{example}",
on_click=_use_example,
args=(example,),
)
st.stop()
with st.spinner("Searching..."):
results = _search(query, 24)
if not results:
st.warning(
f"Nothing matched **{query}**. Try a brand name, a simpler term, or a full barcode."
)
st.stop()
st.caption(f"{len(results)} results for **{query}**")
for start in range(0, len(results), 4):
row = results[start : start + 4]
for column, product in zip(st.columns(4), row):
with column:
cards.product_card(
product,
key=f"open_{product['code']}",
on_open=state.open_product,
)
|