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,
            )