import gradio as gr import time import json # Mock OCR Function to simulate the backend logic def process_document(file): if file is None: return None, None # Simulate processing time (Scanner effect) time.sleep(2.5) # Mock extracted data mock_data = { "document_type": "Invoice", "invoice_number": "INV-2023-0045", "date": "2023-10-15", "client": "Acme Corp", "total_amount": "$1,250.00", "tax": "$125.00", "status": "Paid", "confidence_score": 0.98 } return file, mock_data # Custom CSS to match the "VisionExtract" dark/glass theme from the request custom_css = """ :root { --primary: #6366f1; --secondary: #a855f7; --accent: #ec4899; --bg-dark: #0f172a; --bg-card: #1e293b; --text-main: #f8fafc; --text-muted: #94a3b8; --success: #10b981; --border: #334155; } body { background-color: var(--bg-dark); color: var(--text-main); font-family: 'Inter', sans-serif; background-image: radial-gradient(circle at 10% 20%, rgba(63, 66, 241, 0.1) 0%, transparent 20%), radial-gradient(circle at 90% 80%, rgba(236, 72, 153, 0.1) 0%, transparent 20%); } .gradio-container { background: transparent !important; } /* Sidebar Styling */ .sidebar-container { background: var(--bg-card); border-right: 1px solid var(--border); color: var(--text-main); } .nav-item { padding: 12px 15px; border-radius: 8px; color: var(--text-muted); cursor: pointer; transition: all 0.2s; display: flex; align-items: center; gap: 12px; margin-bottom: 5px; font-weight: 500; } .nav-item:hover { background: rgba(63, 66, 241, 0.1); color: var(--text-main); } /* Card Styling */ .gr-box { background: var(--bg-card); border: 1px solid var(--border); border-radius: 16px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); } /* Header Badge */ .anycoder-badge { background: linear-gradient(135deg, var(--primary), var(--secondary)); padding: 8px 16px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; color: white; text-decoration: none; box-shadow: 0 4px 15px rgba(63, 66, 241, 0.3); transition: transform 0.2s; display: inline-block; margin-bottom: 10px; } .anycoder-badge:hover { transform: translateY(-2px); text-decoration: none; color: white; } /* Results Panel */ .data-field { background: rgba(15, 23, 42, 0.5); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid var(--border); transition: border-color 0.3s; } .data-field:hover { border-color: var(--secondary); } .field-label { font-size: 0.8rem; color: var(--text-muted); margin-bottom: 5px; text-transform: uppercase; letter-spacing: 0.5px; display: flex; justify-content: space-between; } .field-value { font-size: 1.1rem; font-weight: 600; color: var(--text-main); } .confidence-badge { font-size: 0.7rem; padding: 2px 6px; background: var(--success); color: #fff; border-radius: 4px; } /* Scanner Animation Overlay (Simulated via HTML component) */ .scanner-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to bottom, transparent, rgba(0, 255, 157, 0.2), transparent); animation: scan 3s linear infinite; z-index: 10; pointer-events: none; } @keyframes scan { 0% { top: -100%; } 100% { top: 100%; } } """ def create_app(): with gr.Blocks() as demo: # --- Sidebar --- with gr.Sidebar(position="left", open=True): gr.Markdown("
Upload a document to automatically extract structured fields.
") gr.HTML("Built with anycoder") # Workspace Grid with gr.Row(): # Left Column: Upload/Preview with gr.Column(scale=1): with gr.Group(): gr.Markdown("
{json.dumps(data, indent=2)}