Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -218,6 +218,34 @@ if "uploads_count" not in st.session_state:
|
|
218 |
if "food_items" not in st.session_state:
|
219 |
st.session_state["food_items"] = []
|
220 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
# Streamlit Layout - Authentication Section
|
222 |
st.sidebar.title("π User Authentication")
|
223 |
auth_option = st.sidebar.radio("Select an option", ["Login", "Sign Up", "Logout"])
|
@@ -355,108 +383,134 @@ if "original_image" in st.session_state:
|
|
355 |
|
356 |
# Food metadata form
|
357 |
st.subheader("π² Add Food Details")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
358 |
|
359 |
-
|
360 |
-
if
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
|
|
381 |
|
382 |
-
|
383 |
-
|
384 |
-
if food_name and portion_size and portion_unit and cooking_method:
|
385 |
-
# Add the food item to the session state
|
386 |
-
st.session_state["food_items"].append({
|
387 |
-
"food_name": food_name,
|
388 |
-
"portion_size": portion_size,
|
389 |
-
"portion_unit": portion_unit,
|
390 |
-
"cooking_method": cooking_method,
|
391 |
-
"ingredients": ingredients
|
392 |
-
})
|
393 |
-
st.success(f"β
Added {food_name} to your submission")
|
394 |
-
st.rerun()
|
395 |
-
else:
|
396 |
-
st.error("β Please fill in all required fields")
|
397 |
|
398 |
-
# Submit all foods button
|
399 |
-
|
400 |
-
if st.
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
413 |
|
414 |
-
if
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
has_metadata = True # Already validated
|
419 |
-
|
420 |
-
# Check if the food is in a unique category (simplified)
|
421 |
-
is_unique_category = food_item["food_name"] not in ["Pizza", "Burger", "Pasta", "Salad"]
|
422 |
-
|
423 |
-
# Calculate tokens for this item
|
424 |
-
tokens_awarded = calculate_tokens(image_quality, has_metadata, is_unique_category)
|
425 |
-
total_tokens += tokens_awarded
|
426 |
-
|
427 |
-
# Convert float to Decimal for DynamoDB
|
428 |
-
portion_size_decimal = Decimal(str(food_item["portion_size"]))
|
429 |
-
|
430 |
-
# Save metadata to DynamoDB
|
431 |
-
success = save_metadata(
|
432 |
-
st.session_state["user_id"],
|
433 |
-
s3_path,
|
434 |
-
food_item["food_name"],
|
435 |
-
portion_size_decimal, # Use Decimal type
|
436 |
-
food_item["portion_unit"],
|
437 |
-
food_item["cooking_method"],
|
438 |
-
food_item["ingredients"],
|
439 |
-
tokens_awarded
|
440 |
-
)
|
441 |
-
|
442 |
-
if not success:
|
443 |
-
all_saved = False
|
444 |
-
break
|
445 |
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
# Clear the form and image for a new submission
|
452 |
-
st.session_state.pop("original_image", None)
|
453 |
-
st.session_state.pop("processed_image", None)
|
454 |
-
st.session_state["food_items"] = []
|
455 |
-
st.rerun()
|
456 |
-
else:
|
457 |
-
st.error("Failed to save some items. Please try again.")
|
458 |
else:
|
459 |
-
st.error("Failed to
|
|
|
|
|
460 |
|
461 |
# Display earned tokens
|
462 |
st.sidebar.markdown("---")
|
|
|
218 |
if "food_items" not in st.session_state:
|
219 |
st.session_state["food_items"] = []
|
220 |
|
221 |
+
# Initialize form input state variables
|
222 |
+
if "custom_food_name" not in st.session_state:
|
223 |
+
st.session_state["custom_food_name"] = ""
|
224 |
+
|
225 |
+
def reset_form_fields():
|
226 |
+
"""Reset all form fields after adding an item"""
|
227 |
+
# Only reset custom food name, keep the dropdown at its current value
|
228 |
+
st.session_state["custom_food_name"] = ""
|
229 |
+
# We don't reset the dropdown selection as users might want to add multiple similar items
|
230 |
+
|
231 |
+
def add_food_item(food_name, portion_size, portion_unit, cooking_method, ingredients):
|
232 |
+
"""Add a food item to the session state"""
|
233 |
+
if food_name and portion_size and portion_unit and cooking_method:
|
234 |
+
# Add the food item to the session state
|
235 |
+
st.session_state["food_items"].append({
|
236 |
+
"food_name": food_name,
|
237 |
+
"portion_size": portion_size,
|
238 |
+
"portion_unit": portion_unit,
|
239 |
+
"cooking_method": cooking_method,
|
240 |
+
"ingredients": ingredients
|
241 |
+
})
|
242 |
+
st.success(f"β
Added {food_name} to your submission")
|
243 |
+
reset_form_fields()
|
244 |
+
return True
|
245 |
+
else:
|
246 |
+
st.error("β Please fill in all required fields")
|
247 |
+
return False
|
248 |
+
|
249 |
# Streamlit Layout - Authentication Section
|
250 |
st.sidebar.title("π User Authentication")
|
251 |
auth_option = st.sidebar.radio("Select an option", ["Login", "Sign Up", "Logout"])
|
|
|
383 |
|
384 |
# Food metadata form
|
385 |
st.subheader("π² Add Food Details")
|
386 |
+
|
387 |
+
# Use Streamlit form to capture Enter key and provide a better UX
|
388 |
+
with st.form(key="food_item_form"):
|
389 |
+
food_selection = st.selectbox("Food Name", options=[""] + FOOD_SUGGESTIONS, index=0)
|
390 |
+
|
391 |
+
# Only show custom food name if the dropdown is empty
|
392 |
+
custom_food_name = ""
|
393 |
+
if food_selection == "":
|
394 |
+
custom_food_name = st.text_input("Or enter a custom food name",
|
395 |
+
value=st.session_state["custom_food_name"],
|
396 |
+
key="food_name_input")
|
397 |
+
|
398 |
+
# Determine the actual food name to use
|
399 |
+
food_name = food_selection if food_selection else custom_food_name
|
400 |
+
|
401 |
+
col1, col2 = st.columns(2)
|
402 |
+
with col1:
|
403 |
+
portion_size = st.number_input("Portion Size", min_value=0.1, step=0.1, format="%.2f")
|
404 |
+
with col2:
|
405 |
+
portion_unit = st.selectbox("Unit", options=UNIT_OPTIONS)
|
406 |
+
|
407 |
+
cooking_method = st.selectbox("Cooking Method", options=[""] + COOKING_METHODS)
|
408 |
+
|
409 |
+
ingredients = st_tags.st_tags(
|
410 |
+
label="Main Ingredients (Add up to 5)",
|
411 |
+
text="Press enter to add",
|
412 |
+
value=[],
|
413 |
+
suggestions=["Salt", "Pepper", "Olive Oil", "Butter", "Garlic", "Onion", "Tomato"],
|
414 |
+
maxtags=5
|
415 |
+
)
|
416 |
+
|
417 |
+
# Submit button inside the form
|
418 |
+
submitted = st.form_submit_button(label="β Add This Food Item")
|
419 |
+
if submitted:
|
420 |
+
if add_food_item(food_name, portion_size, portion_unit, cooking_method, ingredients):
|
421 |
+
# Store custom food name for next reset
|
422 |
+
if custom_food_name:
|
423 |
+
st.session_state["custom_food_name"] = custom_food_name
|
424 |
+
st.rerun()
|
425 |
|
426 |
+
# Separate section for quick-add common foods
|
427 |
+
if "original_image" in st.session_state:
|
428 |
+
with st.expander("π Quick Add Common Foods"):
|
429 |
+
st.info("Click to quickly add common food items with default values")
|
430 |
+
quick_add_cols = st.columns(3)
|
431 |
+
|
432 |
+
common_foods = [
|
433 |
+
{"name": "French Fries", "portion": 100, "unit": "grams", "cooking": "Fried", "ingredients": ["Potatoes", "Salt", "Oil"]},
|
434 |
+
{"name": "Hamburger", "portion": 1, "unit": "pieces", "cooking": "Grilled", "ingredients": ["Beef", "Bun", "Lettuce", "Tomato"]},
|
435 |
+
{"name": "Salad", "portion": 150, "unit": "grams", "cooking": "Raw", "ingredients": ["Lettuce", "Tomato", "Cucumber"]}
|
436 |
+
]
|
437 |
+
|
438 |
+
for i, food in enumerate(common_foods):
|
439 |
+
with quick_add_cols[i % 3]:
|
440 |
+
if st.button(f"+ {food['name']}", key=f"quick_{i}"):
|
441 |
+
add_food_item(
|
442 |
+
food['name'],
|
443 |
+
food['portion'],
|
444 |
+
food['unit'],
|
445 |
+
food['cooking'],
|
446 |
+
food['ingredients']
|
447 |
+
)
|
448 |
+
st.rerun()
|
449 |
|
450 |
+
# Divider before submit button
|
451 |
+
st.markdown("---")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
452 |
|
453 |
+
# Submit all foods button - outside the form
|
454 |
+
if st.button("π€ Submit All Food Items", disabled=len(st.session_state["food_items"]) == 0):
|
455 |
+
if not st.session_state["food_items"]:
|
456 |
+
st.error("β Please add at least one food item before submitting")
|
457 |
+
else:
|
458 |
+
with st.spinner("Processing your submission..."):
|
459 |
+
all_saved = True
|
460 |
+
total_tokens = 0
|
461 |
+
|
462 |
+
# Determine image quality (simplified version)
|
463 |
+
image_quality = "high" if original_img.width >= 1000 and original_img.height >= 1000 else "standard"
|
464 |
+
|
465 |
+
# Upload image to S3 once
|
466 |
+
s3_path = upload_to_s3(processed_img, st.session_state["user_id"])
|
467 |
+
|
468 |
+
if s3_path:
|
469 |
+
# Save each food item with the same image
|
470 |
+
for food_item in st.session_state["food_items"]:
|
471 |
+
# Check if metadata is complete
|
472 |
+
has_metadata = True # Already validated
|
473 |
+
|
474 |
+
# Check if the food is in a unique category (simplified)
|
475 |
+
is_unique_category = food_item["food_name"] not in ["Pizza", "Burger", "Pasta", "Salad"]
|
476 |
+
|
477 |
+
# Calculate tokens for this item
|
478 |
+
tokens_awarded = calculate_tokens(image_quality, has_metadata, is_unique_category)
|
479 |
+
total_tokens += tokens_awarded
|
480 |
+
|
481 |
+
# Convert float to Decimal for DynamoDB
|
482 |
+
portion_size_decimal = Decimal(str(food_item["portion_size"]))
|
483 |
+
|
484 |
+
# Save metadata to DynamoDB
|
485 |
+
success = save_metadata(
|
486 |
+
st.session_state["user_id"],
|
487 |
+
s3_path,
|
488 |
+
food_item["food_name"],
|
489 |
+
portion_size_decimal, # Use Decimal type
|
490 |
+
food_item["portion_unit"],
|
491 |
+
food_item["cooking_method"],
|
492 |
+
food_item["ingredients"],
|
493 |
+
tokens_awarded
|
494 |
+
)
|
495 |
+
|
496 |
+
if not success:
|
497 |
+
all_saved = False
|
498 |
+
break
|
499 |
|
500 |
+
if all_saved:
|
501 |
+
st.session_state["tokens"] += total_tokens
|
502 |
+
st.session_state["uploads_count"] += 1
|
503 |
+
st.success(f"β
All food items uploaded successfully! You earned {total_tokens} tokens.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
504 |
|
505 |
+
# Clear the form and image for a new submission
|
506 |
+
st.session_state.pop("original_image", None)
|
507 |
+
st.session_state.pop("processed_image", None)
|
508 |
+
st.session_state["food_items"] = []
|
509 |
+
st.rerun()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
510 |
else:
|
511 |
+
st.error("Failed to save some items. Please try again.")
|
512 |
+
else:
|
513 |
+
st.error("Failed to upload image. Please try again.")
|
514 |
|
515 |
# Display earned tokens
|
516 |
st.sidebar.markdown("---")
|