File size: 7,371 Bytes
2ae3f7c |
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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
import streamlit as st
import requests
import json
from PIL import Image
import io
import base64
from datetime import datetime
import pandas as pd
import plotly.express as px
# Configure the app
st.set_page_config(
page_title="IndiScan - Product Health Analyzer",
page_icon="π",
layout="wide"
)
# API endpoint
API_URL = "http://localhost:8000" # Change this when deploying
def main():
# Sidebar
st.sidebar.title("IndiScan π")
scan_option = st.sidebar.radio(
"Choose scan method:",
["Barcode", "Image Upload", "Manual Entry"]
)
# Main content
st.title("IndiScan - Product Health Analyzer")
st.markdown("""
Analyze food and cosmetic products for health risks and get detailed insights.
Upload an image, enter a barcode, or manually input product details.
""")
# Admin section in sidebar
with st.sidebar.expander("Admin Controls π"):
admin_username = st.text_input("Username")
admin_password = st.text_input("Password", type="password")
if st.button("Login"):
try:
auth = (admin_username, admin_password)
response = requests.get(f"{API_URL}/export", auth=auth)
if response.status_code == 200:
st.sidebar.success("Logged in as admin")
st.session_state['admin_auth'] = auth
else:
st.sidebar.error("Invalid credentials")
except Exception as e:
st.sidebar.error(f"Login failed: {str(e)}")
# Main content based on selected option
if scan_option == "Barcode":
barcode_scanner()
elif scan_option == "Image Upload":
image_scanner()
else:
manual_entry()
def barcode_scanner():
st.header("Barcode Scanner π±")
barcode = st.text_input("Enter barcode number:")
if barcode:
try:
response = requests.post(f"{API_URL}/scan/barcode", params={"barcode": barcode})
if response.status_code == 200:
display_results(response.json())
else:
st.error("Product not found")
except Exception as e:
st.error(f"Error: {str(e)}")
def image_scanner():
st.header("Image Scanner πΈ")
uploaded_file = st.file_uploader("Upload product image", type=["jpg", "jpeg", "png"])
if uploaded_file:
try:
# Display uploaded image
image = Image.open(uploaded_file)
st.image(image, caption="Uploaded Image", use_column_width=True)
# Process image
files = {"file": uploaded_file}
response = requests.post(f"{API_URL}/scan/image", files=files)
if response.status_code == 200:
display_results(response.json())
else:
st.error("Failed to process image")
except Exception as e:
st.error(f"Error: {str(e)}")
def manual_entry():
st.header("Manual Entry βοΈ")
col1, col2 = st.columns(2)
with col1:
product_type = st.selectbox("Product Type", ["Food", "Cosmetic"])
ingredients_text = st.text_area("Enter ingredients list (comma-separated or as shown on package):")
with col2:
if ingredients_text:
try:
response = requests.post(
f"{API_URL}/analyze/text",
data={
"text": ingredients_text,
"product_type": product_type.lower()
}
)
if response.status_code == 200:
display_results(response.json())
else:
st.error("Failed to analyze ingredients")
except Exception as e:
st.error(f"Error: {str(e)}")
def display_results(data):
# Create three columns for different aspects of the analysis
col1, col2, col3 = st.columns([2, 2, 1])
with col1:
st.subheader("Health Score")
score = data.get('health_score', {}).get('score', 0)
# Create a gauge chart using plotly
fig = px.pie(
values=[score, 1000-score],
names=['Score', 'Remaining'],
hole=0.7,
color_discrete_sequence=['#00ff00' if score > 600 else '#ff0000', '#eee']
)
fig.update_layout(
annotations=[dict(text=f"{score}/1000", x=0.5, y=0.5, font_size=20, showarrow=False)],
showlegend=False,
width=300,
height=300
)
st.plotly_chart(fig)
# Display explanation
if 'explanation' in data.get('health_score', {}):
st.markdown(data['health_score']['explanation'])
with col2:
st.subheader("Ingredients Analysis")
if 'ingredients' in data:
ingredients = data['ingredients']
st.write(f"Found {len(ingredients)} ingredients:")
for i, ingredient in enumerate(ingredients, 1):
st.write(f"{i}. {ingredient}")
# Display risks if available
if 'risks' in data.get('health_score', {}):
st.subheader("Risk Categories")
risks = data['health_score']['risks']
for category, risk_data in risks.items():
with st.expander(f"{category.replace('_', ' ').title()}"):
st.write(f"Found in: {', '.join(risk_data['ingredients'])}")
with col3:
if 'nutrition_info' in data:
st.subheader("Nutrition Info")
nutrition = data['nutrition_info']
for nutrient, value in nutrition.items():
st.metric(nutrient.title(), f"{value}g")
if 'nutrition_analysis' in data:
analysis = data['nutrition_analysis']
if analysis['concerns']:
st.subheader("β οΈ Concerns")
for concern in analysis['concerns']:
st.write(f"- {concern}")
if analysis['positives']:
st.subheader("β
Positives")
for positive in analysis['positives']:
st.write(f"- {positive}")
if analysis['recommendations']:
st.subheader("π‘ Recommendations")
for rec in analysis['recommendations']:
st.write(f"- {rec}")
# Price comparison if available
if 'prices' in data:
st.subheader("Price Comparison")
prices_df = pd.DataFrame(data['prices'])
fig = px.bar(
prices_df,
x='platform',
y='price',
title="Price Comparison Across Platforms",
color='platform'
)
st.plotly_chart(fig)
# Display price table
st.dataframe(
prices_df[['platform', 'price', 'title', 'url']],
column_config={
"url": st.column_config.LinkColumn("Link")
}
)
if __name__ == "__main__":
main() |