Liori25 commited on
Commit
431a1ae
·
verified ·
1 Parent(s): 61f3ae5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +237 -244
app.py CHANGED
@@ -43,12 +43,18 @@ def image_to_base64(image_path):
43
  with open(image_path, "rb") as img_file:
44
  return base64.b64encode(img_file.read()).decode('utf-8')
45
 
46
- logo_b64 = image_to_base64("logo.jpg")
47
- profile_b64 = image_to_base64("232px-Tv_the_muppet_show_bein_green.jpg")
48
- process_b64 = image_to_base64("preview of process.jpg")
 
 
 
 
 
 
49
 
50
  # ==========================================
51
- # 3. BACKEND LOGIC
52
  # ==========================================
53
  def get_embedding_via_api(text):
54
  if not client: raise ValueError("HF_TOKEN missing")
@@ -71,9 +77,10 @@ def find_similar_recipes_list(query_text):
71
  desc = str(row['Raw_Output'])
72
  score_display = f"{score:.0%}"
73
 
 
74
  card_content = (
75
- f"### 🏆 {title}\n"
76
- f"<span style='color:#1877f2; font-weight:bold; font-size:14px;'>Match Score: {score_display}</span>\n\n"
77
  f"<div class='sim-scroll'>{desc}</div>"
78
  )
79
  results_list.append(card_content)
@@ -109,311 +116,301 @@ def ui_update_pipeline(image_path):
109
  return f"Error: {e}", "Error", gr.update(), gr.update(), "", gr.update(), ""
110
 
111
  # ==========================================
112
- # 4. MODERN UI THEME & CSS
113
  # ==========================================
114
- theme = gr.themes.Soft(
115
- primary_hue="indigo",
116
- secondary_hue="blue",
117
- neutral_hue="slate",
118
- font=[gr.themes.GoogleFont('Inter'), 'ui-sans-serif', 'system-ui']
119
  )
120
 
121
- modern_css = """
122
- body, .gradio-container { background-color: #f0f2f5; }
 
123
 
124
- /* Sticky Header */
125
- .custom-header {
126
- background: rgba(255, 255, 255, 0.95);
127
- backdrop-filter: blur(10px);
128
- border-bottom: 1px solid #e4e6eb;
129
- padding: 15px 20px;
130
  display: flex;
131
  align-items: center;
 
 
 
132
  justify-content: space-between;
133
- position: fixed;
134
- top: 0; left: 0; right: 0;
135
- width: 100%;
136
- z-index: 9999;
137
- box-shadow: 0 2px 10px rgba(0,0,0,0.05);
 
 
 
 
 
 
 
 
 
 
 
138
  }
139
 
140
- .main-content-wrapper { margin-top: 140px; }
 
 
 
 
141
 
142
- .logo-area { display: flex; align-items: center; gap: 20px; }
143
- .logo-img { height: 120px; width: 120px; border-radius: 12px; object-fit: cover; border: 1px solid #ddd; }
144
- .text-area { display: flex; flex-direction: column; }
145
- .app-name {
146
- font-weight: 800; font-size: 32px;
147
- background: -webkit-linear-gradient(45deg, #1877f2, #6b21a8);
148
- -webkit-background-clip: text; -webkit-text-fill-color: transparent;
149
- line-height: 1.2;
150
  }
151
- .app-slogan { font-size: 16px; color: #65676b; font-weight: 500; }
152
 
153
- /* Sidebar Navigation */
154
  .nav-btn {
155
  text-align: left !important;
156
  justify-content: flex-start !important;
157
  background: transparent !important;
158
  border: none !important;
159
  box-shadow: none !important;
160
- color: #65676b !important;
161
  font-weight: 600 !important;
162
- font-size: 16px !important;
163
- padding: 12px 16px !important;
164
- border-radius: 10px !important;
165
- transition: all 0.2s ease;
166
  }
167
- .nav-btn:hover { background-color: #e4e6eb !important; color: #050505 !important; }
168
- .nav-btn.selected {
169
- background-color: #e7f3ff !important;
170
- color: #1877f2 !important;
171
- border-left: 4px solid #1877f2 !important;
 
 
 
 
 
 
 
 
 
 
 
 
172
  }
 
 
173
 
174
- /* Feed & Content Cards */
175
- #feed-container { gap: 0px !important; padding: 0px !important; }
176
- #feed-container > .form { gap: 0px !important; }
177
-
178
- .content-card {
179
- background-color: #ffffff !important;
180
- border-radius: 12px;
181
- box-shadow: 0 1px 2px rgba(0,0,0,0.1);
182
- border: 1px solid #ddd;
183
- padding: 20px;
184
- margin-bottom: 7px !important;
185
- width: 100%;
186
- display: block;
187
  }
 
 
188
 
189
- /* Saved Recipe Card (Facebook Style) */
190
- .saved-card-container {
191
- background: white;
192
- border-radius: 10px;
193
- box-shadow: 0 1px 2px rgba(0,0,0,0.1);
194
- border: 1px solid #ddd;
195
- padding: 0;
196
- overflow: hidden;
197
- height: 100%;
198
- transition: box-shadow 0.2s;
199
- display: flex;
200
- flex-direction: column;
201
- }
202
- .saved-card-container:hover { box-shadow: 0 8px 16px rgba(0,0,0,0.1); }
203
 
204
- .saved-header {
205
- background: #f0f2f5;
206
- height: 100px;
207
- display: flex;
208
- align-items: center;
209
- justify-content: center;
210
- font-size: 40px;
211
- color: #888;
212
- }
213
-
214
- .saved-body { padding: 15px; flex-grow: 1; }
215
- .saved-title { font-weight: 700; font-size: 16px; margin-bottom: 5px; color: #050505; line-height: 1.3; }
216
- .saved-meta { font-size: 12px; color: #65676b; margin-bottom: 10px; }
217
-
218
- /* Right Sidebar Buttons (Saved Recipes List) */
219
- .sidebar-saved-btn {
220
- text-align: left !important;
221
- justify-content: flex-start !important;
222
- background: white !important;
223
- border: 1px solid #e0e0e0 !important;
224
- box-shadow: 0 1px 2px rgba(0,0,0,0.05) !important;
225
- margin-bottom: 8px !important;
226
- color: #333 !important;
227
- padding: 8px 12px !important;
228
- font-size: 14px !important;
229
- font-weight: 500 !important;
230
- }
231
- .sidebar-saved-btn:hover {
232
- background: #f0f2f5 !important;
233
- border-color: #d0d0d0 !important;
234
- color: #1877f2 !important;
235
- }
236
-
237
- .sim-card {
238
- background: #fff;
239
- border: 1px solid #eee;
240
- border-radius: 8px;
241
- padding: 15px;
242
- height: 100%;
243
- border-top: 4px solid #1877f2;
244
- display: flex; flex-direction: column; justify-content: space-between;
245
- }
246
- .sim-scroll { height: 400px; overflow-y: auto; margin-bottom: 10px; padding-right: 5px; font-size: 14px; color: #4b4f56; }
247
- .gap-fix { gap: 25px !important; }
248
- .gradio-examples { display: flex; justify-content: center; width: 100%; }
249
- button.gallery-item { transition: transform 0.2s ease, box-shadow 0.2s ease !important; z-index: 1; }
250
- button.gallery-item:hover { transform: scale(2.5) !important; z-index: 1000 !important; box-shadow: 0 10px 25px rgba(0,0,0,0.3) !important; border: 2px solid white !important; border-radius: 8px !important; }
251
  """
252
 
253
  # ==========================================
254
  # 5. LAYOUT CONSTRUCTION
255
  # ==========================================
256
- with gr.Blocks(title="Legacy Kitchen") as demo:
257
 
258
- # --- HEADER ---
259
  gr.HTML(f"""
260
- <div class="custom-header">
261
- <div class="logo-area">
262
- <img src="data:image/jpeg;base64,{logo_b64}" class="logo-img">
263
- <div class="text-area">
264
- <span class="app-name">Legacy Kitchen</span>
265
- <span class="app-slogan">Turning Handwritten Notes into a Digital Cookbook.</span>
266
- </div>
267
- </div>
268
- <div style="color: #65676b; font-weight: 600;">v5.2</div>
269
  </div>
 
270
  """)
271
 
272
- with gr.Row(elem_classes=["main-content-wrapper"]):
 
273
 
274
- # --- LEFT SIDEBAR ---
275
- with gr.Column(scale=1, min_width=200):
276
  gr.HTML(f"""
277
- <div style="display:flex; align-items:center; padding: 10px 10px 5px 10px;">
278
- <img src="data:image/jpeg;base64,{profile_b64}" style="width:40px; height:40px; border-radius:50%; margin-right:10px; object-fit:cover;">
279
- <b style="font-size: 16px;">My Profile</b>
280
  </div>
281
  """)
282
- gr.HTML("<hr style='border: 0; border-top: 1px solid #e4e6eb; margin: 10px 0 20px 0;'>")
 
 
 
283
 
284
- nav_digital = gr.Button("✨ AI Digitizer", elem_classes=["nav-btn", "selected"])
285
- nav_feed = gr.Button("📰 News Feed", elem_classes=["nav-btn"])
286
- nav_saved = gr.Button("🔖 Saved Recipes", elem_classes=["nav-btn"])
287
- nav_about = gr.Button("ℹ️ About", elem_classes=["nav-btn"])
288
 
289
- # --- CENTER CONTENT ---
290
- with gr.Column(scale=3):
291
 
292
- # === VIEW 1: AI DIGITALIZER ===
293
  with gr.Group(visible=True) as digitalizer_view:
294
- with gr.Row(elem_classes=["gap-fix"]):
295
- with gr.Column(scale=1):
296
- with gr.Group(elem_classes=["content-card"]):
297
- input_img = gr.Image(type="filepath", label="Upload", height=300)
298
- magic_btn = gr.Button("✨ Convert to Digital", variant="primary", size="lg")
299
- gr.Examples(
300
- examples=[
301
- ["quick_tries_images/applecrisp.jpg"],
302
- ["quick_tries_images/meatballs recipe.jpg"],
303
- ["quick_tries_images/chocolateballs.png"],
304
- ["quick_tries_images/Apple Dapple (aka Fresh Apple Cake).jfif"]
305
- ],
306
- inputs=input_img,
307
- label="Or try these examples:",
308
- cache_examples=False
309
- )
310
- with gr.Column(scale=1):
311
- with gr.Group(elem_classes=["content-card"]):
312
- out_text = gr.Textbox(label="Result", value="Here your digitalized recipe will be presented", lines=20, interactive=False, show_label=False)
313
-
314
- gr.HTML("<div style='height: 35px;'></div>")
315
- gr.Markdown("### 3. Similar Recipes from Database")
316
 
317
- with gr.Row():
318
- with gr.Column(elem_classes=["sim-card"]) as c1_box:
319
- sim1 = gr.Markdown("Once you will upload your scanned recipe, we will share similar recipes!")
320
- with gr.Row(visible=False) as c1_btns:
321
- gr.Button("👍 Like", size="sm", variant="secondary")
322
- gr.Button("↗️ Share", size="sm", variant="secondary")
323
 
324
- with gr.Column(elem_classes=["sim-card"], visible=False) as c2_box:
325
- sim2 = gr.Markdown("")
326
- with gr.Row():
327
- gr.Button("👍 Like", size="sm", variant="secondary")
328
- gr.Button("↗️ Share", size="sm", variant="secondary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
 
330
- with gr.Column(elem_classes=["sim-card"], visible=False) as c3_box:
331
- sim3 = gr.Markdown("")
332
- with gr.Row():
333
- gr.Button("👍 Like", size="sm", variant="secondary")
334
- gr.Button("↗️ Share", size="sm", variant="secondary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
 
336
  magic_btn.click(ui_update_pipeline, input_img, [out_text, sim1, c1_btns, c2_box, sim2, c3_box, sim3])
337
 
338
- # === VIEW 2: FEED ===
339
- with gr.Column(visible=False, elem_id="feed-container") as feed_view:
340
- if not df_recipes.empty:
341
  feed_samples = df_recipes.sample(10)
342
  for index, row in feed_samples.iterrows():
343
  user_name = random.choice(["Grandma Rose", "Chef Mike", "Sarah J."])
344
  emoji = random.choice(["🥘", "🥗", "🍰", "🌮"])
345
- post_time = random.choice(["2h", "3h", "4h", "6h", "9h", "12h", "a day ago", "2 days ago"])
346
 
347
- with gr.Group(elem_classes=["content-card"]):
 
348
  gr.HTML(f"""
349
- <div style="display:flex; gap:10px; align-items:center; margin-bottom:12px;">
350
- <div style="width:40px; height:40px; background:#e4e6eb; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:20px;">{emoji}</div>
351
- <div><b>{user_name}</b><br><span style="color:gray; font-size:12px;">{post_time} · 🌍 Public</span></div>
 
 
 
352
  </div>
353
  """)
354
- gr.Markdown(f"### {row['Title']}")
355
- gr.Markdown(f"{str(row['Raw_Output'])[:250]}...")
356
- with gr.Row():
357
- gr.Button("👍 Like", size="sm", variant="secondary")
358
- gr.Button("💬 Comment", size="sm", variant="secondary")
359
- gr.Button("↗️ Share", size="sm", variant="secondary")
 
 
360
  else:
361
  gr.Markdown("⚠️ Database is empty.")
362
 
363
- # === VIEW 3: SAVED RECIPES ===
364
  with gr.Column(visible=False) as saved_view:
365
- gr.Markdown("### 🔖 Saved Recipes (100 Items)")
366
-
367
  if not df_recipes.empty:
368
- saved_batch = df_recipes.head(100)
369
- # 3-column grid
370
- with gr.Row():
371
- for index, row in saved_batch.iterrows():
372
- emoji_icon = random.choice(["🍝", "🥗", "🍰", "🥘", "🍪", "🍗", "🥪", "🥧"])
373
- with gr.Column(scale=1, min_width=200):
374
- with gr.Group(elem_classes=["saved-card-container"]):
375
- gr.HTML(f"<div class='saved-header'>{emoji_icon}</div>")
376
- with gr.Column(elem_classes=["saved-body"]):
377
- gr.HTML(f"<div class='saved-title'>{row['Title']}</div>")
378
- gr.HTML(f"<div class='saved-meta'>Saved to Collection</div>")
379
- gr.Button("View", size="sm", variant="secondary")
380
- else:
381
- gr.Markdown("Database empty.")
382
 
383
- # === VIEW 4: ABOUT ===
384
  with gr.Group(visible=False) as about_view:
385
- with gr.Group(elem_classes=["content-card"]):
386
- gr.Markdown("""
387
- # Goal Project
388
- The goal of this project is to develop an app that takes a scanned image of a handwritten recipe as input, generates text using a VLM, and based on the extracted text, suggests 3 similar recipes from a 10K dataset of synthetic recipes. Our app will bridge the gap between analog culinary heritage and digital discovery.
389
-
390
- ### About Us
391
- This app was developed by **Shahar Firshtman** and **Lior Feinstein**, 2nd year students for Economics and data science.
392
- """)
393
  gr.HTML(f"""
394
  <div style="margin-top: 20px;">
395
- <h3 style="color: #444;">Process Overview</h3>
396
- <img src="data:image/jpeg;base64,{process_b64}" style="width: 100%; height: auto; border-radius: 8px; border: 1px solid #ddd;">
397
  </div>
398
  """)
399
 
400
- # --- RIGHT COLUMN ---
401
- with gr.Column(scale=1, min_width=200):
402
- # NEW: Dynamic Saved Recipes List
403
- gr.Markdown("### My Saved Recipes")
 
 
 
 
404
 
405
- sidebar_btns = []
406
- if not df_recipes.empty:
407
- saved_10 = df_recipes.head(10)
408
- for i, row in saved_10.iterrows():
409
- # We create buttons here and store them to bind click events later
410
- btn = gr.Button(f"🍲 {row['Title']}", elem_classes=["sidebar-saved-btn"])
411
- sidebar_btns.append(btn)
412
- else:
413
- gr.Markdown("No saved recipes.")
 
 
 
 
414
 
415
  # ==========================================
416
- # 6. JAVASCRIPT LOGIC
417
  # ==========================================
418
  def go_digi():
419
  return (
@@ -442,10 +439,6 @@ with gr.Blocks(title="Legacy Kitchen") as demo:
442
  nav_feed.click(go_feed, None, outputs_ui)
443
  nav_saved.click(go_saved, None, outputs_ui)
444
  nav_about.click(go_about, None, outputs_ui)
445
-
446
- # NEW: Bind right sidebar buttons to go_saved function
447
- for btn in sidebar_btns:
448
- btn.click(go_saved, None, outputs_ui)
449
 
450
  if __name__ == "__main__":
451
- demo.launch(theme=theme, css=modern_css)
 
43
  with open(image_path, "rb") as img_file:
44
  return base64.b64encode(img_file.read()).decode('utf-8')
45
 
46
+ # Using placeholders if files don't exist to prevent crash
47
+ try:
48
+ logo_b64 = image_to_base64("logo.jpg")
49
+ profile_b64 = image_to_base64("232px-Tv_the_muppet_show_bein_green.jpg")
50
+ process_b64 = image_to_base64("preview of process.jpg")
51
+ except:
52
+ logo_b64 = ""
53
+ profile_b64 = ""
54
+ process_b64 = ""
55
 
56
  # ==========================================
57
+ # 3. BACKEND LOGIC (UNCHANGED)
58
  # ==========================================
59
  def get_embedding_via_api(text):
60
  if not client: raise ValueError("HF_TOKEN missing")
 
77
  desc = str(row['Raw_Output'])
78
  score_display = f"{score:.0%}"
79
 
80
+ # HTML styled as a "Suggested Post"
81
  card_content = (
82
+ f"<div class='suggested-header'>Suggested for you · {score_display} Match</div>"
83
+ f"### 🥘 {title}\n"
84
  f"<div class='sim-scroll'>{desc}</div>"
85
  )
86
  results_list.append(card_content)
 
116
  return f"Error: {e}", "Error", gr.update(), gr.update(), "", gr.update(), ""
117
 
118
  # ==========================================
119
+ # 4. FACEBOOK UI THEME & CSS
120
  # ==========================================
121
+ # We override the theme to be neutral so our CSS takes over
122
+ theme = gr.themes.Default(
123
+ primary_hue="blue",
124
+ radius_size="sm",
125
+ font=['Helvetica', 'Arial', 'sans-serif']
126
  )
127
 
128
+ facebook_css = """
129
+ body { background-color: #f0f2f5; margin: 0; padding: 0; }
130
+ .gradio-container { background-color: #f0f2f5 !important; max-width: 100% !important; margin: 0 !important; padding: 0 !important; }
131
 
132
+ /* 1. STICKY NAVBAR */
133
+ .fb-navbar {
134
+ background: white;
135
+ height: 56px;
136
+ padding: 0 16px;
137
+ box-shadow: 0 1px 2px rgba(0,0,0,0.1);
138
  display: flex;
139
  align-items: center;
140
+ position: sticky;
141
+ top: 0;
142
+ z-index: 999;
143
  justify-content: space-between;
144
+ }
145
+ .fb-logo {
146
+ color: #1877F2;
147
+ font-size: 28px;
148
+ font-weight: bold;
149
+ letter-spacing: -0.5px;
150
+ margin-right: 20px;
151
+ }
152
+ .fb-search {
153
+ background: #f0f2f5;
154
+ border-radius: 50px;
155
+ padding: 10px 20px;
156
+ color: #65676B;
157
+ width: 250px;
158
+ display: flex;
159
+ align-items: center;
160
  }
161
 
162
+ /* 2. LAYOUT COLUMNS */
163
+ .main-layout { display: flex; justify-content: center; padding-top: 20px; gap: 20px; }
164
+ .col-left { width: 300px; display: none; } /* Hidden on mobile */
165
+ .col-feed { width: 600px; max-width: 100%; }
166
+ .col-right { width: 300px; display: none; }
167
 
168
+ /* 3. CARD STYLING (The core FB look) */
169
+ .fb-card {
170
+ background: white;
171
+ border-radius: 8px;
172
+ box-shadow: 0 1px 2px rgba(0,0,0,0.2);
173
+ margin-bottom: 15px;
174
+ overflow: hidden;
175
+ padding: 12px 16px;
176
  }
177
+ .no-padding { padding: 0 !important; }
178
 
179
+ /* 4. NAVIGATION BUTTONS (Left Sidebar) */
180
  .nav-btn {
181
  text-align: left !important;
182
  justify-content: flex-start !important;
183
  background: transparent !important;
184
  border: none !important;
185
  box-shadow: none !important;
186
+ color: #050505 !important;
187
  font-weight: 600 !important;
188
+ font-size: 15px !important;
189
+ padding: 10px 8px !important;
190
+ border-radius: 8px !important;
191
+ margin-bottom: 5px !important;
192
  }
193
+ .nav-btn:hover { background-color: #e4e6eb !important; }
194
+ .nav-btn.selected { background-color: #e7f3ff !important; color: #1877f2 !important; }
195
+
196
+ /* 5. POST HEADER (Avatar + Name) */
197
+ .post-header { display: flex; align-items: center; margin-bottom: 12px; }
198
+ .user-avatar { width: 40px; height: 40px; border-radius: 50%; background: #ddd; margin-right: 10px; object-fit: cover; }
199
+ .post-info { display: flex; flex-direction: column; }
200
+ .post-author { font-weight: 600; color: #050505; font-size: 15px; }
201
+ .post-meta { font-size: 13px; color: #65676B; }
202
+
203
+ /* 6. POST ACTIONS (Like/Comment/Share) */
204
+ .post-actions {
205
+ border-top: 1px solid #ced0d4;
206
+ margin-top: 10px;
207
+ padding-top: 5px;
208
+ display: flex;
209
+ justify-content: space-around;
210
  }
211
+ .action-btn { background: transparent !important; color: #65676B !important; box-shadow: none !important; }
212
+ .action-btn:hover { background: #f2f2f2 !important; }
213
 
214
+ /* 7. RIGHT SIDEBAR (Contacts style) */
215
+ .contact-row {
216
+ display: flex; align-items: center; padding: 8px; border-radius: 8px; cursor: pointer;
 
 
 
 
 
 
 
 
 
 
217
  }
218
+ .contact-row:hover { background-color: #e4e6eb; }
219
+ .contact-name { font-weight: 500; font-size: 14px; margin-left: 10px; color: #050505; }
220
 
221
+ /* UTILS */
222
+ .sim-scroll { height: 200px; overflow-y: auto; font-size: 13px; color: #050505; }
223
+ .suggested-header { font-size: 12px; font-weight: bold; color: #65676B; margin-bottom: 5px; }
 
 
 
 
 
 
 
 
 
 
 
224
 
225
+ /* Media Queries */
226
+ @media (min-width: 1100px) { .col-left, .col-right { display: block; } }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  """
228
 
229
  # ==========================================
230
  # 5. LAYOUT CONSTRUCTION
231
  # ==========================================
232
+ with gr.Blocks(title="Legacy Kitchen", css=facebook_css, theme=theme) as demo:
233
 
234
+ # --- 1. FACEBOOK NAVBAR ---
235
  gr.HTML(f"""
236
+ <div class="fb-navbar">
237
+ <div style="display:flex; align-items:center;">
238
+ <div class="fb-logo">facebook</div>
239
+ <div class="fb-search">🔍 &nbsp; Search Legacy Kitchen</div>
240
+ </div>
241
+ <div style="display:flex; gap:10px;">
242
+ <div style="width:40px;height:40px;background:#e4e6eb;border-radius:50%;display:flex;align-items:center;justify-content:center;">➕</div>
243
+ <div style="width:40px;height:40px;background:#e4e6eb;border-radius:50%;display:flex;align-items:center;justify-content:center;">💬</div>
244
+ <img src="data:image/jpeg;base64,{profile_b64}" style="width:40px; height:40px; border-radius:50%; object-fit:cover;">
245
  </div>
246
+ </div>
247
  """)
248
 
249
+ # --- 2. MAIN 3-COLUMN LAYOUT ---
250
+ with gr.Row(elem_classes=["main-layout"]):
251
 
252
+ # === LEFT COLUMN (Sidebar Navigation) ===
253
+ with gr.Column(elem_classes=["col-left"]):
254
  gr.HTML(f"""
255
+ <div class="contact-row">
256
+ <img src="data:image/jpeg;base64,{profile_b64}" style="width:36px; height:36px; border-radius:50%;">
257
+ <div class="contact-name">Welcome User</div>
258
  </div>
259
  """)
260
+ nav_digital = gr.Button("✨ AI Digitizer (Create)", elem_classes=["nav-btn", "selected"])
261
+ nav_feed = gr.Button("📰 News Feed", elem_classes=["nav-btn"])
262
+ nav_saved = gr.Button("🔖 Saved Recipes", elem_classes=["nav-btn"])
263
+ nav_about = gr.Button("ℹ️ About Project", elem_classes=["nav-btn"])
264
 
265
+ gr.HTML("<hr style='border:0; border-top:1px solid #ced0d4; margin: 10px 0;'>")
266
+ gr.Markdown("### Your Shortcuts")
267
+ gr.Markdown("🥘 Culinary Arts Group\n\n🥧 Grandmother's Secrets\n\n🥗 Healthy Eating")
 
268
 
269
+ # === CENTER COLUMN (The Feed & App Logic) ===
270
+ with gr.Column(elem_classes=["col-feed"]):
271
 
272
+ # --- VIEW 1: AI DIGITIZER (Styled as "Create Post") ---
273
  with gr.Group(visible=True) as digitalizer_view:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
275
+ # "Create Post" Card
276
+ with gr.Group(elem_classes=["fb-card"]):
277
+ gr.Markdown("### Create Post")
278
+ gr.HTML("<hr style='border:0; border-top:1px solid #e4e6eb; margin: 10px 0;'>")
 
 
279
 
280
+ with gr.Row():
281
+ input_img = gr.Image(type="filepath", label="Add to your post", height=250, container=True)
282
+
283
+ gr.HTML("<div style='margin-top:10px; font-size:14px; color:#65676B;'>Add to your post: 🟢 Photo/Video 👤 Tag People 📍 Location</div>")
284
+ magic_btn = gr.Button("Post", variant="primary") # Blue button
285
+
286
+ # Examples styled as small chips/thumbnails
287
+ gr.Examples(
288
+ examples=[["quick_tries_images/applecrisp.jpg"], ["quick_tries_images/meatballs recipe.jpg"]],
289
+ inputs=input_img, label="Quick Try (Click to load image)"
290
+ )
291
+
292
+ # Output ("The Resulting Post")
293
+ with gr.Group(elem_classes=["fb-card"]):
294
+ gr.HTML("""
295
+ <div class="post-header">
296
+ <div class="user-avatar" style="background:#1877F2;"></div>
297
+ <div class="post-info">
298
+ <div class="post-author">Legacy Kitchen AI</div>
299
+ <div class="post-meta">Just now · 🌍</div>
300
+ </div>
301
+ </div>
302
+ """)
303
+ out_text = gr.Textbox(label="Transcription Result", placeholder="Your digitized recipe text will appear here...", lines=10, show_label=False)
304
 
305
+ with gr.Row(elem_classes=["post-actions"]):
306
+ gr.Button("👍 Like", elem_classes=["action-btn"], size="sm")
307
+ gr.Button("💬 Comment", elem_classes=["action-btn"], size="sm")
308
+ gr.Button(" Share", elem_classes=["action-btn"], size="sm")
309
+
310
+ # Similar Recipes (Styled as "Suggested Posts")
311
+ gr.Markdown("### Suggested for you")
312
+
313
+ # Sim Result 1
314
+ with gr.Group(elem_classes=["fb-card"], visible=False) as c1_box:
315
+ sim1 = gr.Markdown("Similar Recipe 1")
316
+ with gr.Row(elem_classes=["post-actions"], visible=False) as c1_btns:
317
+ gr.Button("Save", elem_classes=["action-btn"], size="sm")
318
+
319
+ # Sim Result 2
320
+ with gr.Group(elem_classes=["fb-card"], visible=False) as c2_box:
321
+ sim2 = gr.Markdown("Similar Recipe 2")
322
+ with gr.Row(elem_classes=["post-actions"]):
323
+ gr.Button("Save", elem_classes=["action-btn"], size="sm")
324
+
325
+ # Sim Result 3
326
+ with gr.Group(elem_classes=["fb-card"], visible=False) as c3_box:
327
+ sim3 = gr.Markdown("Similar Recipe 3")
328
+ with gr.Row(elem_classes=["post-actions"]):
329
+ gr.Button("Save", elem_classes=["action-btn"], size="sm")
330
 
331
  magic_btn.click(ui_update_pipeline, input_img, [out_text, sim1, c1_btns, c2_box, sim2, c3_box, sim3])
332
 
333
+ # --- VIEW 2: FEED ---
334
+ with gr.Column(visible=False) as feed_view:
335
+ if notdf_recipes.empty:
336
  feed_samples = df_recipes.sample(10)
337
  for index, row in feed_samples.iterrows():
338
  user_name = random.choice(["Grandma Rose", "Chef Mike", "Sarah J."])
339
  emoji = random.choice(["🥘", "🥗", "🍰", "🌮"])
340
+ post_time = random.choice(["2h", "3h", "6h", "Yesterday"])
341
 
342
+ with gr.Group(elem_classes=["fb-card"]):
343
+ # Custom HTML Header for the card
344
  gr.HTML(f"""
345
+ <div class="post-header">
346
+ <div class="user-avatar" style="background:#e4e6eb; display:flex; align-items:center; justify-content:center; font-size:20px;">{emoji}</div>
347
+ <div class="post-info">
348
+ <div class="post-author">{user_name}</div>
349
+ <div class="post-meta">{post_time} · 🌍</div>
350
+ </div>
351
  </div>
352
  """)
353
+ gr.Markdown(f"**{row['Title']}**")
354
+ gr.Markdown(f"{str(row['Raw_Output'])[:300]}... <span style='color:#1877F2; cursor:pointer;'>See more</span>")
355
+
356
+ # Action Bar
357
+ with gr.Row(elem_classes=["post-actions"]):
358
+ gr.Button("👍 Like", elem_classes=["action-btn"], size="sm")
359
+ gr.Button("💬 Comment", elem_classes=["action-btn"], size="sm")
360
+ gr.Button("↪ Share", elem_classes=["action-btn"], size="sm")
361
  else:
362
  gr.Markdown("⚠️ Database is empty.")
363
 
364
+ # --- VIEW 3: SAVED RECIPES ---
365
  with gr.Column(visible=False) as saved_view:
366
+ gr.Markdown("### 🔖 Saved Items")
 
367
  if not df_recipes.empty:
368
+ saved_batch = df_recipes.head(20)
369
+ for index, row in saved_batch.iterrows():
370
+ with gr.Group(elem_classes=["fb-card"]):
371
+ with gr.Row():
372
+ gr.HTML("<div style='width:80px; height:80px; background:#eee; border-radius:8px;'></div>")
373
+ with gr.Column():
374
+ gr.Markdown(f"**{row['Title']}**")
375
+ gr.HTML("<span style='color:#65676B; font-size:12px;'>Saved from News Feed</span>")
376
+ gr.Button("View Collection", size="sm", variant="secondary")
 
 
 
 
 
377
 
378
+ # --- VIEW 4: ABOUT ---
379
  with gr.Group(visible=False) as about_view:
380
+ with gr.Group(elem_classes=["fb-card"]):
381
+ gr.Markdown("# About Legacy Kitchen")
382
+ gr.Markdown("Developed by **Shahar Firshtman** and **Lior Feinstein**.")
 
 
 
 
 
383
  gr.HTML(f"""
384
  <div style="margin-top: 20px;">
385
+ <img src="data:image/jpeg;base64,{process_b64}" style="width: 100%; border-radius: 8px;">
 
386
  </div>
387
  """)
388
 
389
+ # === RIGHT COLUMN (Contacts / Sponsored) ===
390
+ with gr.Column(elem_classes=["col-right"]):
391
+ gr.Markdown("### Sponsored")
392
+ with gr.Group(elem_classes=["fb-card"]):
393
+ gr.Markdown("**Culinary School**\nJoin 10,000+ students learning to cook today!")
394
+ gr.Image("https://picsum.photos/300/150", show_label=False, interactive=False, height=150)
395
+
396
+ gr.HTML("<hr style='border:0; border-top:1px solid #ced0d4; margin: 10px 0;'>")
397
 
398
+ gr.Markdown("### Contacts")
399
+ # Fake contacts list
400
+ contacts = ["Elon Musk", "Gordon Ramsay", "Jamie Oliver", "Martha Stewart"]
401
+ for contact in contacts:
402
+ gr.HTML(f"""
403
+ <div class="contact-row">
404
+ <div style="position:relative;">
405
+ <img src="https://ui-avatars.com/api/?name={contact}&background=random" style="width:36px; height:36px; border-radius:50%;">
406
+ <div style="position:absolute; bottom:0; right:0; width:10px; height:10px; background:#31a24c; border-radius:50%; border:2px solid white;"></div>
407
+ </div>
408
+ <div class="contact-name">{contact}</div>
409
+ </div>
410
+ """)
411
 
412
  # ==========================================
413
+ # 6. JAVASCRIPT NAVIGATION LOGIC
414
  # ==========================================
415
  def go_digi():
416
  return (
 
439
  nav_feed.click(go_feed, None, outputs_ui)
440
  nav_saved.click(go_saved, None, outputs_ui)
441
  nav_about.click(go_about, None, outputs_ui)
 
 
 
 
442
 
443
  if __name__ == "__main__":
444
+ demo.launch()