import gradio as gr from claims_agent import ClaimsIntakeAgent from adjuster_dashboard import AdjusterDashboard from utils import extract_claim_data from PIL import Image # Initialize Agents and Dashboard intake_agent = ClaimsIntakeAgent() dashboard = AdjusterDashboard() # --- Claims Intake View Functions --- import time # --- Claims Intake View Functions --- def intake_chat(message, image, file, progress=gr.Progress()): # Yield status updates to the output box directly yield "🔄 **Initializing AI Agent...**" progress(0.1, desc="Initializing AI Agent...") time.sleep(0.5) # Simulate init time yield "🔍 **Analyzing Image & Documents...**" progress(0.3, desc="Analyzing Image & Documents...") # If file is provided, it comes as a filepath response = intake_agent.process_claim(message, image, file) yield "💾 **Syncing with Adjuster Dashboard...**" progress(0.7, desc="Syncing with Adjuster Dashboard...") # Sync with Dashboard if response and "Error" not in response: try: claim_data = extract_claim_data(response) # Update the dashboard data # Note: In a real app with concurrent users, this needs better state management. # Here we update the global dashboard object. dashboard.add_claim(claim_data) except Exception as e: print(f"Error syncing to dashboard: {e}") progress(1.0, desc="Assessment Complete!") yield response # --- Adjuster Auth Functions --- def check_password(password): if password == "password": return gr.update(visible=False), gr.update(visible=True) return gr.update(visible=True), gr.update(visible=False) # --- UI Construction --- custom_css = """ #main_container { max-width: 1000px; margin: 0 auto; padding: 20px; background-color: white; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); border-radius: 10px; margin-top: 20px; } body { background-color: #f0f2f5; } h1 { text-align: center; color: #2c3e50; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; } """ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="slate"), title="EMA Claims MVP", css=custom_css) as demo: with gr.Column(elem_id="main_container"): gr.Markdown("# 🛡️ EMA Claims MVP") with gr.Tabs(): # Tab 1: Customer View (Claims Intake) with gr.Tab("🚗 Claims Intake (Customer)"): gr.Markdown("### Report an Accident") gr.Markdown("Upload a photo of the damage and any relevant documents (PDF/Doc). Our AI will assess it immediately.") with gr.Row(): with gr.Column(scale=1): image_input = gr.Image(type="pil", label="Upload Damage Photo") file_input = gr.File(label="Upload Documents (PDF/Doc)", file_types=[".pdf", ".docx", ".txt"]) msg_input = gr.Textbox(placeholder="Describe the accident...", label="Description") submit_btn = gr.Button("Submit Claim", variant="primary") with gr.Column(scale=1): chat_output = gr.Markdown(label="AI Assessment") # We need to update the claims table if it's visible, but since it's in another tab, # we can rely on the global dashboard object being updated. # However, Gradio components need an event to refresh. # For MVP, we'll just update the global list. The table in the other tab won't auto-refresh # without a trigger, but we can add a "Refresh" button or make the table update on tab select (harder in simple Blocks). # Let's add a "Refresh" button to the dashboard. submit_btn.click( fn=intake_chat, inputs=[msg_input, image_input, file_input], outputs=[chat_output], show_progress=True ) # Tab 2: Adjuster View (Dashboard) with gr.Tab("👨‍💼 Adjuster Dashboard (Internal)"): # Login State with gr.Group(visible=True) as login_group: gr.Markdown("### Internal Access Only") password_input = gr.Textbox(label="Password", type="password") login_btn = gr.Button("Login") # Dashboard Content (Hidden by default) with gr.Group(visible=False) as dashboard_group: gr.Markdown("### Incoming Claims Queue") refresh_btn = gr.Button("Refresh List", size="sm") with gr.Row(): with gr.Column(scale=2): # Dataframe for claims list claims_df = gr.Dataframe( headers=["ID", "Submitter", "Date", "Vehicle", "Status", "Fraud Risk", "Classification"], value=dashboard.get_claims_data, # Pass method to call on load/refresh interactive=False, label="Active Claims", elem_id="claims_table" ) with gr.Column(scale=1): # Details Panel details_panel = gr.Markdown("Select a claim to view details.", label="Claim Analysis") with gr.Row(): approve_btn = gr.Button("Approve Payment", variant="primary", interactive=False) escalate_btn = gr.Button("Escalate to SIU", variant="stop", interactive=False) action_output = gr.Label(label="Action Status") # Interactions claims_df.select( fn=dashboard.get_claim_details, inputs=None, outputs=[details_panel, approve_btn, escalate_btn] ) approve_btn.click( fn=dashboard.approve_claim, inputs=[details_panel], outputs=[action_output] ) escalate_btn.click( fn=dashboard.escalate_claim, inputs=[details_panel], outputs=[action_output] ) refresh_btn.click( fn=lambda: dashboard.get_claims_data(), inputs=None, outputs=[claims_df] ) login_btn.click( fn=check_password, inputs=[password_input], outputs=[login_group, dashboard_group] ) if __name__ == "__main__": demo.queue() demo.launch(server_name="0.0.0.0", # not 127.0.0.1 server_port=7860,)