SebastianAndreu commited on
Commit
e01d2a6
Β·
verified Β·
1 Parent(s): d94809e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -52
app.py CHANGED
@@ -1363,15 +1363,15 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1363
  gr.Markdown("*Smart inventory management powered by AI*", elem_id="main-menu-subtitle")
1364
 
1365
  with gr.Row():
1366
- checkout_btn = gr.Button("πŸ›’ Check Out Items", size="lg", elem_classes=["module-button"], scale=1)
1367
- add_items_btn = gr.Button("πŸ“¦ Add Items", size="lg", elem_classes=["module-button"], scale=1)
1368
- analysis_btn = gr.Button("πŸ“Š Inventory Analysis", size="lg", elem_classes=["module-button"], scale=1)
1369
 
1370
  # CHECK OUT MODULE
1371
  with gr.Group(visible=False, elem_classes=["module-page"]) as checkout_module:
1372
- gr.Markdown("# πŸ›’ Check Out Items", elem_classes=["section-header"])
1373
 
1374
- with gr.Accordion("πŸ“– How to Use", open=False):
1375
  gr.Markdown("""
1376
  **Step 1:** Upload a photo of items or type item names manually (comma-separated)
1377
 
@@ -1383,7 +1383,7 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1383
  """)
1384
 
1385
  with gr.Group(visible=True) as checkout_screen1:
1386
- gr.Markdown("### πŸ“Έ Scan Items", elem_classes=["subsection-header"])
1387
 
1388
  with gr.Row():
1389
  with gr.Column(scale=2):
@@ -1394,7 +1394,7 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1394
  height=400
1395
  )
1396
 
1397
- load_example_checkout_btn = gr.Button("πŸ“Έ Load Example", size="sm", variant="secondary", scale=0, visible=EXAMPLE_CHECKOUT_IMAGE is not None)
1398
 
1399
  with gr.Column(scale=1):
1400
  gr.Markdown("""
@@ -1414,7 +1414,7 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1414
  )
1415
 
1416
  checkout_status = gr.Markdown("")
1417
- checkout_scan_btn = gr.Button("πŸ” Scan & Match Items", variant="primary", size="lg")
1418
 
1419
  with gr.Group(visible=False) as checkout_screen2:
1420
  gr.Markdown("### Review Selected Items", elem_classes=["subsection-header"])
@@ -1428,7 +1428,7 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1428
  with gr.Column(scale=1):
1429
  item_qty = gr.Number(value=1, minimum=1, label="Qty")
1430
  with gr.Column(scale=1):
1431
- item_remove = gr.Button("πŸ—‘οΈ Remove", size="sm", variant="stop")
1432
 
1433
  checkout_item_controls.append({
1434
  'row': item_row,
@@ -1438,11 +1438,11 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1438
  })
1439
 
1440
  with gr.Row():
1441
- checkout_rescan_btn = gr.Button("↩️ Rescan", variant="secondary")
1442
- checkout_confirm_btn = gr.Button("βœ… Proceed to Checkout", variant="primary", size="lg")
1443
 
1444
  with gr.Group(visible=False) as checkout_screen3:
1445
- gr.Markdown("### 🎫 Confirm Checkout", elem_classes=["subsection-header"])
1446
 
1447
  checkout_preview = gr.Markdown("")
1448
 
@@ -1455,20 +1455,20 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1455
  checkout_processing = gr.Markdown("")
1456
 
1457
  with gr.Row():
1458
- checkout_cancel_btn = gr.Button("❌ Cancel", variant="secondary")
1459
- checkout_final_btn = gr.Button("βœ… Complete Checkout", variant="primary", size="lg")
1460
 
1461
  checkout_result = gr.Markdown("")
1462
 
1463
  with gr.Row():
1464
- checkout_return_btn = gr.Button("🏠 Return to Main Menu", variant="secondary")
1465
- checkout_another_btn = gr.Button("πŸ›’ Check Out More Items", variant="primary", visible=False)
1466
 
1467
  # ADD ITEMS MODULE
1468
  with gr.Group(visible=False, elem_classes=["module-page"]) as add_items_module:
1469
- gr.Markdown("# πŸ“¦ Add Items to Inventory", elem_classes=["section-header"])
1470
 
1471
- with gr.Accordion("πŸ“– How to Use", open=False):
1472
  gr.Markdown("""
1473
  **Receipt Upload:**
1474
  1. Upload receipt image or PDF β†’ AI extracts items
@@ -1484,17 +1484,17 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1484
  - Track all changes with timestamps
1485
  """)
1486
 
1487
- with gr.Tab("πŸ“„ Receipt Upload"):
1488
  gr.Markdown("### Upload Receipt", elem_classes=["subsection-header"])
1489
 
1490
  receipt_file = gr.File(label="Upload Receipt (PDF or Image)", file_types=[".pdf", ".png", ".jpg", ".jpeg"])
1491
 
1492
- load_example_receipt_btn = gr.Button("πŸ“„ Load Example", size="sm", variant="secondary", scale=0, visible=EXAMPLE_RECEIPT_PDF is not None)
1493
 
1494
  receipt_status = gr.Markdown("")
1495
 
1496
  gr.Markdown("### Review Detected Items", elem_classes=["subsection-header"])
1497
- gr.Markdown("*Check items to include, edit quantities, then apply*")
1498
 
1499
  add_items_table = gr.Dataframe(
1500
  headers=["Include", "Item Name", "Quantity", "Match Confidence"],
@@ -1507,11 +1507,11 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1507
  add_items_status = gr.Markdown("")
1508
 
1509
  with gr.Row():
1510
- add_items_reject_btn = gr.Button("❌ Clear All", variant="secondary")
1511
- add_items_confirm_btn = gr.Button("βœ… Apply Updates", variant="primary", interactive=False)
1512
 
1513
- with gr.Tab("✍️ Manual Entry"):
1514
- gr.Markdown("### Manually Add Items", elem_classes=["subsection-header"])
1515
 
1516
  with gr.Row():
1517
  manual_item = gr.Textbox(
@@ -1525,11 +1525,11 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1525
  minimum=1
1526
  )
1527
 
1528
- manual_apply_btn = gr.Button("βž• Add to Inventory", variant="primary")
1529
  manual_status = gr.Markdown("")
1530
  manual_inventory_display = gr.Dataframe(label="Updated Inventory", visible=False)
1531
 
1532
- with gr.Tab("πŸ“Š View & History"):
1533
  gr.Markdown("### Current Inventory", elem_classes=["subsection-header"])
1534
 
1535
  with gr.Row():
@@ -1538,26 +1538,26 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1538
  value="All",
1539
  label="Filter by Category"
1540
  )
1541
- view_inventory_btn = gr.Button("πŸ”„ Refresh Inventory")
1542
 
1543
  inventory_display = gr.Dataframe(label="Current Inventory", visible=False)
1544
 
1545
  gr.Markdown("### Update History", elem_classes=["subsection-header"])
1546
 
1547
- view_history_btn = gr.Button("πŸ“œ View Update Log")
1548
  history_display = gr.Textbox(label="Update History", lines=10, visible=False)
1549
 
1550
- add_items_return_btn = gr.Button("🏠 Return to Main Menu", variant="secondary")
1551
 
1552
  # INVENTORY ANALYSIS MODULE
1553
  with gr.Group(visible=False, elem_classes=["module-page"]) as analysis_module:
1554
- gr.Markdown("# πŸ“Š Inventory Layout Analysis", elem_classes=["section-header"])
1555
 
1556
- with gr.Accordion("πŸ“– Understanding the Analysis", open=True):
1557
  gr.Markdown("""
1558
  This module analyzes checkout patterns to optimize item placement and minimize walking distance.
1559
 
1560
- ### πŸ“ˆ Key Metrics:
1561
 
1562
  **Support** - Frequency of co-occurrence (e.g., 0.10 = 10% of checkouts)
1563
 
@@ -1567,13 +1567,13 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1567
 
1568
  **Distance Saved** - Walking distance reduction in grid units
1569
 
1570
- ### 🎯 Goal:
1571
  Items frequently checked together should be placed closer to reduce travel time!
1572
  """)
1573
 
1574
  with gr.Row():
1575
  with gr.Column(scale=1):
1576
- gr.Markdown("### βš™οΈ Parameters", elem_classes=["subsection-header"])
1577
 
1578
  min_support = gr.Slider(
1579
  minimum=0.01,
@@ -1611,25 +1611,25 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1611
  info="Threshold for suggestions"
1612
  )
1613
 
1614
- run_analysis_btn = gr.Button("πŸ” Run Analysis", variant="primary", size="lg")
1615
 
1616
  with gr.Column(scale=2):
1617
- gr.Markdown("### πŸ“Š Summary", elem_classes=["subsection-header"])
1618
  analysis_summary = gr.Textbox(label="", lines=14, show_label=False)
1619
 
1620
- gr.Markdown("### πŸ—ΊοΈ Visual Layout Comparison", elem_classes=["subsection-header"])
1621
  analysis_viz = gr.Image(label="", type="numpy", show_label=False)
1622
 
1623
  with gr.Row():
1624
  with gr.Column():
1625
- gr.Markdown("### πŸ”— Frequent Pairs", elem_classes=["subsection-header"])
1626
  pairs_table = gr.Dataframe(label="", show_label=False)
1627
 
1628
  with gr.Column():
1629
- gr.Markdown("### πŸ“ Recommendations", elem_classes=["subsection-header"])
1630
  recs_table = gr.Dataframe(label="", show_label=False)
1631
 
1632
- analysis_return_btn = gr.Button("🏠 Return to Main Menu", variant="secondary")
1633
 
1634
  # EVENT HANDLERS - Navigation
1635
  def show_checkout():
@@ -1715,14 +1715,14 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1715
  return gr.update(visible=False), gr.update(visible=True)
1716
 
1717
  checkout_scan_btn.click(
1718
- fn=lambda: (gr.update(value="⏳ Scanning...", interactive=False), "πŸ” **Processing...** AI is analyzing your image..."),
1719
  outputs=[checkout_scan_btn, checkout_status]
1720
  ).then(
1721
  fn=scan_items_checkout,
1722
  inputs=[checkout_image, checkout_manual],
1723
  outputs=[matched_items_state, checkout_status]
1724
  ).then(
1725
- fn=lambda: gr.update(value="πŸ” Scan & Match Items", interactive=True),
1726
  outputs=[checkout_scan_btn]
1727
  ).then(
1728
  fn=lambda items: (
@@ -1777,14 +1777,14 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1777
  )
1778
 
1779
  checkout_final_btn.click(
1780
- fn=lambda: (gr.update(value="⏳ Processing...", interactive=False), "⏳ **Processing checkout...** Updating inventory..."),
1781
  outputs=[checkout_final_btn, checkout_processing]
1782
  ).then(
1783
  fn=process_checkout,
1784
  inputs=[matched_items_state, checkout_user_id],
1785
  outputs=[checkout_result]
1786
  ).then(
1787
- fn=lambda: (gr.update(value="βœ… Complete Checkout", interactive=True), ""),
1788
  outputs=[checkout_final_btn, checkout_processing]
1789
  ).then(
1790
  fn=lambda: (gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)),
@@ -1805,32 +1805,32 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1805
 
1806
  # EVENT HANDLERS - Add Items
1807
  receipt_file.change(
1808
- fn=lambda: "πŸ“„ **Processing receipt...** Extracting text with OCR...",
1809
  outputs=[receipt_status]
1810
  ).then(
1811
  fn=extract_text_from_receipt,
1812
  inputs=[receipt_file],
1813
  outputs=[add_items_table, proposals_state]
1814
  ).then(
1815
- fn=lambda proposals: (gr.update(interactive=len(proposals) > 0), "βœ… Items detected! Review and edit the table below."),
1816
  inputs=[proposals_state],
1817
  outputs=[add_items_confirm_btn, receipt_status]
1818
  )
1819
 
1820
  add_items_confirm_btn.click(
1821
- fn=lambda: (gr.update(value="⏳ Applying...", interactive=False), "⏳ **Updating inventory...**"),
1822
  outputs=[add_items_confirm_btn, add_items_status]
1823
  ).then(
1824
  fn=apply_updates_from_table,
1825
  inputs=[add_items_table],
1826
  outputs=[add_items_status, inventory_display]
1827
  ).then(
1828
- fn=lambda: (gr.update(value="βœ… Apply Updates", interactive=False), gr.update(visible=True)),
1829
  outputs=[add_items_confirm_btn, inventory_display]
1830
  )
1831
 
1832
  add_items_reject_btn.click(
1833
- fn=lambda: ([["No items", "", "", ""]], "❌ Cleared all items.", []),
1834
  outputs=[add_items_table, add_items_status, proposals_state]
1835
  ).then(
1836
  fn=lambda: gr.update(interactive=False),
@@ -1838,14 +1838,14 @@ with gr.Blocks(title="Makerspace Inventory System", css=CUSTOM_CSS) as demo:
1838
  )
1839
 
1840
  manual_apply_btn.click(
1841
- fn=lambda: gr.update(value="⏳ Adding...", interactive=False),
1842
  outputs=[manual_apply_btn]
1843
  ).then(
1844
  fn=manual_update,
1845
  inputs=[manual_item, manual_qty],
1846
  outputs=[manual_status, manual_inventory_display]
1847
  ).then(
1848
- fn=lambda: (gr.update(value="βž• Add to Inventory", interactive=True), gr.update(visible=True)),
1849
  outputs=[manual_apply_btn, manual_inventory_display]
1850
  )
1851
 
 
1363
  gr.Markdown("*Smart inventory management powered by AI*", elem_id="main-menu-subtitle")
1364
 
1365
  with gr.Row():
1366
+ checkout_btn = gr.Button("Check Out Items", size="lg", elem_classes=["module-button"], scale=1)
1367
+ add_items_btn = gr.Button("Add Items", size="lg", elem_classes=["module-button"], scale=1)
1368
+ analysis_btn = gr.Button("Inventory Analysis", size="lg", elem_classes=["module-button"], scale=1)
1369
 
1370
  # CHECK OUT MODULE
1371
  with gr.Group(visible=False, elem_classes=["module-page"]) as checkout_module:
1372
+ gr.Markdown("# Check Out Items", elem_classes=["section-header"])
1373
 
1374
+ with gr.Accordion("How to Use This Module", open=False):
1375
  gr.Markdown("""
1376
  **Step 1:** Upload a photo of items or type item names manually (comma-separated)
1377
 
 
1383
  """)
1384
 
1385
  with gr.Group(visible=True) as checkout_screen1:
1386
+ gr.Markdown("### Scan Items", elem_classes=["subsection-header"])
1387
 
1388
  with gr.Row():
1389
  with gr.Column(scale=2):
 
1394
  height=400
1395
  )
1396
 
1397
+ load_example_checkout_btn = gr.Button("Load Example", size="sm", variant="secondary", scale=0, visible=EXAMPLE_CHECKOUT_IMAGE is not None)
1398
 
1399
  with gr.Column(scale=1):
1400
  gr.Markdown("""
 
1414
  )
1415
 
1416
  checkout_status = gr.Markdown("")
1417
+ checkout_scan_btn = gr.Button("Scan & Match Items", variant="primary", size="lg")
1418
 
1419
  with gr.Group(visible=False) as checkout_screen2:
1420
  gr.Markdown("### Review Selected Items", elem_classes=["subsection-header"])
 
1428
  with gr.Column(scale=1):
1429
  item_qty = gr.Number(value=1, minimum=1, label="Qty")
1430
  with gr.Column(scale=1):
1431
+ item_remove = gr.Button("Remove", size="sm", variant="stop")
1432
 
1433
  checkout_item_controls.append({
1434
  'row': item_row,
 
1438
  })
1439
 
1440
  with gr.Row():
1441
+ checkout_rescan_btn = gr.Button("Rescan", variant="secondary")
1442
+ checkout_confirm_btn = gr.Button("Proceed to Checkout", variant="primary", size="lg")
1443
 
1444
  with gr.Group(visible=False) as checkout_screen3:
1445
+ gr.Markdown("### Confirm Checkout", elem_classes=["subsection-header"])
1446
 
1447
  checkout_preview = gr.Markdown("")
1448
 
 
1455
  checkout_processing = gr.Markdown("")
1456
 
1457
  with gr.Row():
1458
+ checkout_cancel_btn = gr.Button("Cancel", variant="secondary")
1459
+ checkout_final_btn = gr.Button("Complete Checkout", variant="primary", size="lg")
1460
 
1461
  checkout_result = gr.Markdown("")
1462
 
1463
  with gr.Row():
1464
+ checkout_return_btn = gr.Button("Return to Main Menu", variant="secondary")
1465
+ checkout_another_btn = gr.Button("Check Out More Items", variant="primary", visible=False)
1466
 
1467
  # ADD ITEMS MODULE
1468
  with gr.Group(visible=False, elem_classes=["module-page"]) as add_items_module:
1469
+ gr.Markdown("# Add Items to Inventory", elem_classes=["section-header"])
1470
 
1471
+ with gr.Accordion("How to Use This Module", open=False):
1472
  gr.Markdown("""
1473
  **Receipt Upload:**
1474
  1. Upload receipt image or PDF β†’ AI extracts items
 
1484
  - Track all changes with timestamps
1485
  """)
1486
 
1487
+ with gr.Tab("Receipt Upload"):
1488
  gr.Markdown("### Upload Receipt", elem_classes=["subsection-header"])
1489
 
1490
  receipt_file = gr.File(label="Upload Receipt (PDF or Image)", file_types=[".pdf", ".png", ".jpg", ".jpeg"])
1491
 
1492
+ load_example_receipt_btn = gr.Button("Load Example", size="sm", variant="secondary", scale=0, visible=EXAMPLE_RECEIPT_PDF is not None)
1493
 
1494
  receipt_status = gr.Markdown("")
1495
 
1496
  gr.Markdown("### Review Detected Items", elem_classes=["subsection-header"])
1497
+ gr.Markdown("*Check items to include, edit quantities as needed, then apply changes*")
1498
 
1499
  add_items_table = gr.Dataframe(
1500
  headers=["Include", "Item Name", "Quantity", "Match Confidence"],
 
1507
  add_items_status = gr.Markdown("")
1508
 
1509
  with gr.Row():
1510
+ add_items_reject_btn = gr.Button("Clear All", variant="secondary")
1511
+ add_items_confirm_btn = gr.Button("Apply Updates", variant="primary", interactive=False)
1512
 
1513
+ with gr.Tab("Manual Entry"):
1514
+ gr.Markdown("### Add Items Manually", elem_classes=["subsection-header"])
1515
 
1516
  with gr.Row():
1517
  manual_item = gr.Textbox(
 
1525
  minimum=1
1526
  )
1527
 
1528
+ manual_apply_btn = gr.Button("Add to Inventory", variant="primary")
1529
  manual_status = gr.Markdown("")
1530
  manual_inventory_display = gr.Dataframe(label="Updated Inventory", visible=False)
1531
 
1532
+ with gr.Tab("View & History"):
1533
  gr.Markdown("### Current Inventory", elem_classes=["subsection-header"])
1534
 
1535
  with gr.Row():
 
1538
  value="All",
1539
  label="Filter by Category"
1540
  )
1541
+ view_inventory_btn = gr.Button("Refresh Inventory")
1542
 
1543
  inventory_display = gr.Dataframe(label="Current Inventory", visible=False)
1544
 
1545
  gr.Markdown("### Update History", elem_classes=["subsection-header"])
1546
 
1547
+ view_history_btn = gr.Button("View Update Log")
1548
  history_display = gr.Textbox(label="Update History", lines=10, visible=False)
1549
 
1550
+ add_items_return_btn = gr.Button("Return to Main Menu", variant="secondary")
1551
 
1552
  # INVENTORY ANALYSIS MODULE
1553
  with gr.Group(visible=False, elem_classes=["module-page"]) as analysis_module:
1554
+ gr.Markdown("# Inventory Layout Analysis", elem_classes=["section-header"])
1555
 
1556
+ with gr.Accordion("Understanding the Analysis", open=True):
1557
  gr.Markdown("""
1558
  This module analyzes checkout patterns to optimize item placement and minimize walking distance.
1559
 
1560
+ ### Key Metrics:
1561
 
1562
  **Support** - Frequency of co-occurrence (e.g., 0.10 = 10% of checkouts)
1563
 
 
1567
 
1568
  **Distance Saved** - Walking distance reduction in grid units
1569
 
1570
+ ### Goal:
1571
  Items frequently checked together should be placed closer to reduce travel time!
1572
  """)
1573
 
1574
  with gr.Row():
1575
  with gr.Column(scale=1):
1576
+ gr.Markdown("### Analysis Parameters", elem_classes=["subsection-header"])
1577
 
1578
  min_support = gr.Slider(
1579
  minimum=0.01,
 
1611
  info="Threshold for suggestions"
1612
  )
1613
 
1614
+ run_analysis_btn = gr.Button("Run Analysis", variant="primary", size="lg")
1615
 
1616
  with gr.Column(scale=2):
1617
+ gr.Markdown("### Analysis Summary", elem_classes=["subsection-header"])
1618
  analysis_summary = gr.Textbox(label="", lines=14, show_label=False)
1619
 
1620
+ gr.Markdown("### Visual Layout Comparison", elem_classes=["subsection-header"])
1621
  analysis_viz = gr.Image(label="", type="numpy", show_label=False)
1622
 
1623
  with gr.Row():
1624
  with gr.Column():
1625
+ gr.Markdown("### Frequent Pairs", elem_classes=["subsection-header"])
1626
  pairs_table = gr.Dataframe(label="", show_label=False)
1627
 
1628
  with gr.Column():
1629
+ gr.Markdown("### Relocation Recommendations", elem_classes=["subsection-header"])
1630
  recs_table = gr.Dataframe(label="", show_label=False)
1631
 
1632
+ analysis_return_btn = gr.Button("Return to Main Menu", variant="secondary")
1633
 
1634
  # EVENT HANDLERS - Navigation
1635
  def show_checkout():
 
1715
  return gr.update(visible=False), gr.update(visible=True)
1716
 
1717
  checkout_scan_btn.click(
1718
+ fn=lambda: (gr.update(value="Scanning...", interactive=False), "Processing image with AI..."),
1719
  outputs=[checkout_scan_btn, checkout_status]
1720
  ).then(
1721
  fn=scan_items_checkout,
1722
  inputs=[checkout_image, checkout_manual],
1723
  outputs=[matched_items_state, checkout_status]
1724
  ).then(
1725
+ fn=lambda: gr.update(value="Scan & Match Items", interactive=True),
1726
  outputs=[checkout_scan_btn]
1727
  ).then(
1728
  fn=lambda items: (
 
1777
  )
1778
 
1779
  checkout_final_btn.click(
1780
+ fn=lambda: (gr.update(value="Processing...", interactive=False), "Updating inventory..."),
1781
  outputs=[checkout_final_btn, checkout_processing]
1782
  ).then(
1783
  fn=process_checkout,
1784
  inputs=[matched_items_state, checkout_user_id],
1785
  outputs=[checkout_result]
1786
  ).then(
1787
+ fn=lambda: (gr.update(value="Complete Checkout", interactive=True), ""),
1788
  outputs=[checkout_final_btn, checkout_processing]
1789
  ).then(
1790
  fn=lambda: (gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)),
 
1805
 
1806
  # EVENT HANDLERS - Add Items
1807
  receipt_file.change(
1808
+ fn=lambda: "Processing receipt with OCR...",
1809
  outputs=[receipt_status]
1810
  ).then(
1811
  fn=extract_text_from_receipt,
1812
  inputs=[receipt_file],
1813
  outputs=[add_items_table, proposals_state]
1814
  ).then(
1815
+ fn=lambda proposals: (gr.update(interactive=len(proposals) > 0), "Items detected! Review the table below."),
1816
  inputs=[proposals_state],
1817
  outputs=[add_items_confirm_btn, receipt_status]
1818
  )
1819
 
1820
  add_items_confirm_btn.click(
1821
+ fn=lambda: (gr.update(value="Applying...", interactive=False), "Updating inventory..."),
1822
  outputs=[add_items_confirm_btn, add_items_status]
1823
  ).then(
1824
  fn=apply_updates_from_table,
1825
  inputs=[add_items_table],
1826
  outputs=[add_items_status, inventory_display]
1827
  ).then(
1828
+ fn=lambda: (gr.update(value="Apply Updates", interactive=False), gr.update(visible=True)),
1829
  outputs=[add_items_confirm_btn, inventory_display]
1830
  )
1831
 
1832
  add_items_reject_btn.click(
1833
+ fn=lambda: ([["No items", "", "", ""]], "Cleared all items.", []),
1834
  outputs=[add_items_table, add_items_status, proposals_state]
1835
  ).then(
1836
  fn=lambda: gr.update(interactive=False),
 
1838
  )
1839
 
1840
  manual_apply_btn.click(
1841
+ fn=lambda: gr.update(value="Adding...", interactive=False),
1842
  outputs=[manual_apply_btn]
1843
  ).then(
1844
  fn=manual_update,
1845
  inputs=[manual_item, manual_qty],
1846
  outputs=[manual_status, manual_inventory_display]
1847
  ).then(
1848
+ fn=lambda: (gr.update(value="Add to Inventory", interactive=True), gr.update(visible=True)),
1849
  outputs=[manual_apply_btn, manual_inventory_display]
1850
  )
1851