uumerrr684 commited on
Commit
67d68ab
·
verified ·
1 Parent(s): 7ae5971

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +70 -60
app.py CHANGED
@@ -48,13 +48,13 @@ def init_db():
48
  init_db()
49
 
50
  # ============================================================================
51
- # PARSER – tuned for your exact paste style
52
  # ============================================================================
53
  def parse_nutrition_text(text):
54
  result = {}
55
  key_variants = {
56
- 'calories': ['calories', 'kcal'],
57
- 'protein': ['protein'],
58
  'fat': ['fat'],
59
  'saturated_fat': ['saturated fat', 'sat fat', 'saturated'],
60
  'carbs': ['carbs', 'carbohydrates'],
@@ -101,7 +101,7 @@ def parse_nutrition_text(text):
101
  val_str = numbers[-1]
102
  pos = line.rfind(val_str)
103
  label = line[:pos].strip().lower()
104
- label = re.sub(r'\s*\([^)]*\)', '', label).strip() # remove (g), (mg), etc.
105
 
106
  all_keys = []
107
  for k, vs in key_variants.items():
@@ -118,7 +118,7 @@ def parse_nutrition_text(text):
118
  return result
119
 
120
  # ============================================================================
121
- # DATABASE HELPERS
122
  # ============================================================================
123
  def get_db():
124
  conn = sqlite3.connect("health_tracker.db")
@@ -154,13 +154,13 @@ def delete_food(fid):
154
  conn.close()
155
  return "Deleted"
156
 
157
- def log_meal(date, time_str, food_name, portion, nutrition):
158
  conn = get_db()
159
  c = conn.cursor()
160
  cols = ', '.join(nutrition.keys())
161
  vals = ', '.join(['?'] * len(nutrition))
162
  c.execute(f"INSERT INTO meals (date, time, food_name, portion, {cols}) VALUES (?, ?, ?, ?, {vals})",
163
- (date, time_str, food_name, portion, *nutrition.values()))
164
  conn.commit()
165
  conn.close()
166
  return "Meal logged"
@@ -173,19 +173,19 @@ def get_meals(start_date, end_date):
173
  return df
174
 
175
  # ============================================================================
176
- # GRADIO INTERFACE
177
  # ============================================================================
178
  def parse_and_show(text):
179
  parsed = parse_nutrition_text(text)
180
- return parsed, "Paste parsed! Fill name & save."
181
 
182
  def save_food(name, parsed):
183
  if not name.strip():
184
  return "Enter food name", None
185
  if not parsed:
186
- return "No data to save", None
187
  msg = add_food_to_library(name.strip(), parsed)
188
- return msg, None # clear parsed after save
189
 
190
  def refresh_foods():
191
  df = get_all_foods()
@@ -194,88 +194,98 @@ def refresh_foods():
194
  choices = [f"{row['id']} - {row['food_name']}" for _, row in df.iterrows()]
195
  return df.to_string(index=False), gr.update(choices=choices)
196
 
197
- def delete_selected_food(selected):
198
  if not selected:
199
- return "Select food first"
200
  fid = int(selected.split(" - ")[0])
201
  msg = delete_food(fid)
202
- _, choices_update = refresh_foods()
203
- return msg, choices_update
204
 
205
- def log_selected_meal(food_choice, qty, date, time_str):
206
  if not food_choice:
207
- return "Select food first"
208
  fid = int(food_choice.split(" - ")[0])
209
  foods = get_all_foods()
 
 
210
  food_row = foods[foods['id'] == fid].iloc[0].to_dict()
211
 
212
  nutrition = {}
213
- for k in NUTRIENT_FIELDS:
 
 
 
 
 
214
  if k == 'calories':
215
- nutrition[k] = str(float(food_row.get(k, 0)) * qty)
216
  else:
217
- nutrition[k] = food_row.get(k, 0) * qty
218
 
219
- msg = log_meal(date, time_str, food_row['food_name'], f"{qty}x", nutrition)
 
 
 
220
  return msg
221
 
222
- def show_today_log():
223
  today = datetime.now().strftime("%Y-%m-%d")
224
  df = get_meals(today, today)
225
  if df.empty:
226
  return "No meals today"
227
- cals = df['calories'].apply(lambda x: float(x) if x else 0).sum()
 
228
  pro = df['protein'].sum()
229
  fat = df['fat'].sum()
230
  carb = df['carbs'].sum()
231
- summary = f"Today: {cals:.0f} kcal | P {pro:.1f}g | F {fat:.1f}g | C {carb:.1f}g"
232
- return summary + "\n\n" + df[['time', 'food_name', 'portion', 'calories']].to_string(index=False)
233
 
234
- with gr.Blocks(title="Iron Nutrition Tracker", theme=gr.themes.Soft()) as app:
235
- gr.Markdown("# 🍛 Iron's Nutrition Tracker - Karachi")
236
 
237
  with gr.Tabs():
238
- with gr.Tab("Add Food (Paste)"):
239
  with gr.Row():
240
- with gr.Column():
241
- paste_box = gr.Textbox(label="Paste nutrition text here", lines=12,
242
- placeholder="Calories (kcal) 340\nProtein (g) 13.00\n...")
243
- parse_btn = gr.Button("Parse", variant="secondary")
244
- food_name = gr.Textbox(label="Food Name (e.g. 2 omlette)")
245
- save_btn = gr.Button("💾 Save Food", variant="primary")
246
- with gr.Column():
247
- parsed_output = gr.JSON(label="Parsed Values")
248
- status = gr.Textbox(label="Status")
249
-
250
- parse_btn.click(parse_and_show, inputs=paste_box, outputs=[parsed_output, status])
251
- save_btn.click(save_food, inputs=[food_name, parsed_output], outputs=[status, parsed_output])
252
 
253
- with gr.Tab("Log Meal"):
254
- foods_df = get_all_foods()
255
- food_choices = [f"{row['id']} - {row['food_name']}" for _, row in foods_df.iterrows()] if not foods_df.empty else []
256
 
257
- food_select = gr.Dropdown(label="Select Food", choices=food_choices)
258
- qty = gr.Number(label="Quantity (× serving)", value=1.0, minimum=0.1)
259
- date = gr.DatePicker(label="Date", value=datetime.now().date())
260
- time_input = gr.TimePicker(label="Time", value=datetime.now().time())
261
- log_btn = gr.Button("Log Meal", variant="primary")
262
- log_status = gr.Textbox(label="Status")
 
263
 
264
- log_btn.click(log_selected_meal, inputs=[food_select, qty, date, time_input], outputs=log_status)
265
 
266
  with gr.Tab("Today's Log"):
267
- today_summary = gr.Textbox(label="Today's Meals", lines=10, interactive=False)
268
- refresh_today = gr.Button("Refresh")
269
- refresh_today.click(show_today_log, outputs=today_summary)
270
 
271
  with gr.Tab("Food Library"):
272
- foods_table = gr.Textbox(label="All Foods", lines=15, interactive=False)
273
- delete_choice = gr.Dropdown(label="Delete Food", choices=[])
274
- delete_btn = gr.Button("🗑️ Delete", variant="stop")
275
  lib_status = gr.Textbox(label="Status")
276
 
277
- refresh_lib = gr.Button("Refresh Library")
278
- refresh_lib.click(refresh_foods, outputs=[foods_table, delete_choice])
279
- delete_btn.click(delete_selected_food, inputs=delete_choice, outputs=[lib_status, delete_choice])
 
 
 
 
280
 
281
- app.launch(server_name="0.0.0.0", server_port=7860, share=False) # share=True if you want public link
 
48
  init_db()
49
 
50
  # ============================================================================
51
+ # PARSER
52
  # ============================================================================
53
  def parse_nutrition_text(text):
54
  result = {}
55
  key_variants = {
56
+ 'calories': ['calories', 'kcal', 'energy'],
57
+ 'protein': ['protein', 'prot'],
58
  'fat': ['fat'],
59
  'saturated_fat': ['saturated fat', 'sat fat', 'saturated'],
60
  'carbs': ['carbs', 'carbohydrates'],
 
101
  val_str = numbers[-1]
102
  pos = line.rfind(val_str)
103
  label = line[:pos].strip().lower()
104
+ label = re.sub(r'\s*\([^)]*\)', '', label).strip()
105
 
106
  all_keys = []
107
  for k, vs in key_variants.items():
 
118
  return result
119
 
120
  # ============================================================================
121
+ # DB HELPERS
122
  # ============================================================================
123
  def get_db():
124
  conn = sqlite3.connect("health_tracker.db")
 
154
  conn.close()
155
  return "Deleted"
156
 
157
+ def log_meal(date_str, time_str, food_name, portion, nutrition):
158
  conn = get_db()
159
  c = conn.cursor()
160
  cols = ', '.join(nutrition.keys())
161
  vals = ', '.join(['?'] * len(nutrition))
162
  c.execute(f"INSERT INTO meals (date, time, food_name, portion, {cols}) VALUES (?, ?, ?, ?, {vals})",
163
+ (date_str, time_str, food_name, portion, *nutrition.values()))
164
  conn.commit()
165
  conn.close()
166
  return "Meal logged"
 
173
  return df
174
 
175
  # ============================================================================
176
+ # GRADIO APP – fixed for 4.44.0
177
  # ============================================================================
178
  def parse_and_show(text):
179
  parsed = parse_nutrition_text(text)
180
+ return parsed, "Parsed! Now enter name and save."
181
 
182
  def save_food(name, parsed):
183
  if not name.strip():
184
  return "Enter food name", None
185
  if not parsed:
186
+ return "No data parsed", None
187
  msg = add_food_to_library(name.strip(), parsed)
188
+ return msg, None
189
 
190
  def refresh_foods():
191
  df = get_all_foods()
 
194
  choices = [f"{row['id']} - {row['food_name']}" for _, row in df.iterrows()]
195
  return df.to_string(index=False), gr.update(choices=choices)
196
 
197
+ def delete_selected(selected):
198
  if not selected:
199
+ return "Select food"
200
  fid = int(selected.split(" - ")[0])
201
  msg = delete_food(fid)
202
+ _, choices = refresh_foods()
203
+ return msg, choices
204
 
205
+ def log_meal_fn(food_choice, qty, date_obj, time_obj):
206
  if not food_choice:
207
+ return "Select food"
208
  fid = int(food_choice.split(" - ")[0])
209
  foods = get_all_foods()
210
+ if foods.empty or fid not in foods['id'].values:
211
+ return "Food not found"
212
  food_row = foods[foods['id'] == fid].iloc[0].to_dict()
213
 
214
  nutrition = {}
215
+ for k in ['calories', 'protein', 'fat', 'carbs', 'fiber', 'sodium', 'cholesterol', 'sugar', 'saturated_fat',
216
+ 'vitamin_a', 'vitamin_b1', 'vitamin_b2', 'vitamin_b3', 'vitamin_b5', 'vitamin_b6', 'vitamin_b12',
217
+ 'vitamin_c', 'vitamin_d', 'vitamin_e', 'vitamin_k', 'folate', 'calcium', 'iron', 'magnesium',
218
+ 'phosphorus', 'potassium', 'zinc', 'copper', 'manganese', 'selenium', 'iodine', 'chromium',
219
+ 'molybdenum', 'omega_3', 'omega_6', 'water', 'ash']:
220
+ val = food_row.get(k, 0)
221
  if k == 'calories':
222
+ nutrition[k] = str(float(val) * qty if val else 0)
223
  else:
224
+ nutrition[k] = float(val) * qty if val else 0
225
 
226
+ date_str = date_obj.strftime("%Y-%m-%d") if date_obj else datetime.now().strftime("%Y-%m-%d")
227
+ time_str = time_obj.strftime("%H:%M") if time_obj else datetime.now().strftime("%H:%M")
228
+
229
+ msg = log_meal(date_str, time_str, food_row['food_name'], f"{qty}x", nutrition)
230
  return msg
231
 
232
+ def show_today():
233
  today = datetime.now().strftime("%Y-%m-%d")
234
  df = get_meals(today, today)
235
  if df.empty:
236
  return "No meals today"
237
+ df['calories'] = pd.to_numeric(df['calories'], errors='coerce').fillna(0)
238
+ cals = df['calories'].sum()
239
  pro = df['protein'].sum()
240
  fat = df['fat'].sum()
241
  carb = df['carbs'].sum()
242
+ summary = f"Today: {cals:.0f} kcal | Protein {pro:.1f}g | Fat {fat:.1f}g | Carbs {carb:.1f}g\n\n"
243
+ return summary + df[['time', 'food_name', 'portion', 'calories']].to_string(index=False)
244
 
245
+ with gr.Blocks(title="Nutrition Tracker") as app:
246
+ gr.Markdown("# 🍛 Nutrition Tracker - Paste & Track")
247
 
248
  with gr.Tabs():
249
+ with gr.Tab("Add Food"):
250
  with gr.Row():
251
+ paste = gr.Textbox(label="Paste Nutrition Text", lines=15, placeholder="Calories (kcal) 340\nProtein (g) 13.00\n...")
252
+ parse_btn = gr.Button("Parse")
253
+ parsed_json = gr.JSON(label="Parsed Result")
254
+ status_parse = gr.Textbox(label="Parse Status")
255
+ food_name_in = gr.Textbox(label="Food Name")
256
+ save_btn = gr.Button("Save Food", variant="primary")
257
+ save_status = gr.Textbox(label="Save Status")
 
 
 
 
 
258
 
259
+ parse_btn.click(parse_and_show, inputs=paste, outputs=[parsed_json, status_parse])
260
+ save_btn.click(save_food, inputs=[food_name_in, parsed_json], outputs=[save_status, parsed_json])
 
261
 
262
+ with gr.Tab("Log Meal"):
263
+ food_dropdown = gr.Dropdown(label="Select Food", choices=[])
264
+ qty_input = gr.Number(label="Quantity", value=1.0, minimum=0.1)
265
+ date_input = gr.DatePicker(label="Date")
266
+ time_input = gr.TimePicker(label="Time")
267
+ log_btn = gr.Button("Log Meal")
268
+ log_status_out = gr.Textbox(label="Log Status")
269
 
270
+ log_btn.click(log_meal_fn, inputs=[food_dropdown, qty_input, date_input, time_input], outputs=log_status_out)
271
 
272
  with gr.Tab("Today's Log"):
273
+ today_text = gr.Textbox(label="Today's Summary", lines=12, interactive=False)
274
+ refresh_today_btn = gr.Button("Refresh")
275
+ refresh_today_btn.click(show_today, outputs=today_text)
276
 
277
  with gr.Tab("Food Library"):
278
+ foods_text = gr.Textbox(label="Foods List", lines=15, interactive=False)
279
+ delete_dropdown = gr.Dropdown(label="Delete Food", choices=[])
280
+ delete_btn = gr.Button("Delete", variant="stop")
281
  lib_status = gr.Textbox(label="Status")
282
 
283
+ refresh_lib_btn = gr.Button("Refresh Library")
284
+ refresh_lib_btn.click(refresh_foods, outputs=[foods_text, delete_dropdown])
285
+ delete_btn.click(delete_selected, inputs=delete_dropdown, outputs=[lib_status, delete_dropdown])
286
+
287
+ # Initial load
288
+ app.load(refresh_foods, outputs=[foods_text, delete_dropdown])
289
+ app.load(refresh_foods, outputs=[food_dropdown]) # for log tab
290
 
291
+ app.launch(server_name="0.0.0.0", server_port=7860, theme=gr.themes.Soft())