Swift-Query / templates /assistant /assistant_data_entry.html
Darshan Kumar R
Deploy to Hugging Face Spaces (Clean)
ed0b977
Raw History Blame Contribute Delete
71.8 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Data Entry - Assistant</title> <link href="https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600;700&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/icon?family=Material+Icons+Outlined" rel="stylesheet" /> <script src="https://cdn.tailwindcss.com?plugins=forms,typography"></script> <script> tailwind.config = { theme: { extend: { colors: { primary: "#e67e22", "background-light": "#fef3e9", }, }, }, }; </script> <style> .glass-effect { backdrop-filter: blur(10px); background: rgba(255, 255, 255, 0.4); } .tab-content { display: none; } .tab-content.active { display: block; } .tab-btn.active { /* Handled by Tailwind classes in JS now (bg-orange-50, text-primary) */ } </style> </head> <body class="bg-background-light min-h-screen p-4 font-sans text-slate-800"> <header class="max-w-7xl mx-auto p-4 glass-effect rounded-xl shadow-lg mb-8 flex justify-between items-center"> <span class="font-bold text-xl">Swift Query Data Entry</span> <div class="flex items-center gap-4"> <span class="text-sm">Logged in as: {{ session['user_name'] }} (Data Entry)</span> <a href="{{ url_for('admin.logout') }}" class="font-medium hover:text-primary">Logout</a> </div> </header> <main class="max-w-7xl mx-auto grid grid-cols-1 md:grid-cols-4 gap-6"> <!-- Patient Selection Sidebar --> <div class="md:col-span-1 bg-white p-4 rounded-xl shadow-lg h-fit"> <h2 class="font-bold mb-4 text-lg border-b pb-2">Select Patient</h2> <!-- Search Form --> <form action="{{ url_for('assistant.data_entry_dashboard') }}" method="get" class="mb-5 relative"> <input type="text" name="q" value="{{ search_query }}" placeholder="Search ID, Name, Phone..." class="w-full pl-10 pr-4 py-3 bg-gray-50 border-gray-200 rounded-xl text-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all outline-none"> <span class="material-icons-outlined absolute left-3 top-1/2 -translate-y-1/2 text-gray-400">search</span> </form> <div class="space-y-2 max-h-[350px] overflow-y-auto pr-1 custom-scrollbar"> {% if patients %} {% for p in patients %} <button onclick="selectPatient('{{ p.id }}', '{{ p.name }}', '{{ p.phone or '' }}')" class="w-full text-left p-4 rounded-xl transition-all duration-200 group relative overflow-hidden mb-2 {% if selected_patient and selected_patient.id == p.id %} bg-gradient-to-r from-orange-50 to-white border-l-4 border-primary shadow-sm {% else %} bg-white hover:bg-gray-50 border border-transparent hover:border-gray-100 hover:shadow-sm {% endif %}"> <div class="flex justify-between items-start"> <div> <span class="block font-bold text-slate-800 text-lg mb-1 group-hover:text-primary transition-colors">{{ p.name }}</span> <span class="text-xs text-gray-500 font-medium bg-gray-100 px-2 py-1 rounded inline-block">ID: {{ p.patient_id or p.id }}</span> </div> {% if p.phone %} <div class="text-gray-400"> <span class="material-icons-outlined text-sm">phone</span> </div> {% endif %} </div> </button> {% endfor %} {% else %} <p class="text-sm text-gray-500 text-center py-4">No patients found.</p> {% endif %} </div> </div> <!-- Data Entry Area --> <div id="entry-area" class="md:col-span-3 bg-white p-8 rounded-2xl shadow-lg border border-gray-100 min-h-[700px] {% if not selected_patient %}hidden{% endif %}"> <div class="flex justify-between items-end mb-8 border-b pb-6"> <div> <h2 class="text-3xl font-bold text-slate-800 mb-1" id="tab-header">Patient Profile</h2> <div class="flex items-center gap-3 text-gray-500"> <span class="font-semibold text-lg text-primary">{{ selected_patient.name if selected_patient else '' }}</span> <span class="text-sm bg-gray-100 px-2 py-1 rounded">ID: {{ selected_patient.patient_id or selected_patient.id if selected_patient else '' }}</span> </div> </div> </div> <!-- Feedback Messages --> {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} <div class="mb-6 p-4 bg-green-50 text-green-700 rounded-xl border border-green-100 flex items-center gap-2"> <span class="material-icons-outlined">check_circle</span> <div> {% for category, message in messages %} <p class="{{ category }}">{{ message }}</p> {% endfor %} </div> </div> {% endif %} {% endwith %} <!-- Horizontal Tabs (Landscape) --> <div class="flex flex-row overflow-x-auto gap-3 mb-8 pb-2 custom-scrollbar border-b border-gray-100"> <button onclick="switchTab('profile')" class="tab-btn active px-6 py-3 rounded-xl font-bold whitespace-nowrap transition-all bg-orange-50 text-primary flex items-center gap-2"> <span class="material-icons-outlined text-lg">person</span> Profile </button> <button onclick="switchTab('summary')" class="tab-btn px-6 py-3 rounded-xl font-bold whitespace-nowrap transition-all text-gray-500 hover:bg-orange-50 hover:text-primary flex items-center gap-2"> <span class="material-icons-outlined text-lg">history_edu</span> History </button> <button onclick="switchTab('consultation')" class="tab-btn px-6 py-3 rounded-xl font-bold whitespace-nowrap transition-all text-gray-500 hover:bg-orange-50 hover:text-primary flex items-center gap-2"> <span class="material-icons-outlined text-lg">medical_services</span> Consultation </button> <button onclick="switchTab('test')" class="tab-btn px-6 py-3 rounded-xl font-bold whitespace-nowrap transition-all text-gray-500 hover:bg-orange-50 hover:text-primary flex items-center gap-2"> <span class="material-icons-outlined text-lg">biotech</span> Reports </button> <button onclick="switchTab('treatment')" class="tab-btn px-6 py-3 rounded-xl font-bold whitespace-nowrap transition-all text-gray-500 hover:bg-orange-50 hover:text-primary flex items-center gap-2"> <span class="material-icons-outlined text-lg">healing</span> Treatments </button> <button onclick="switchTab('billing')" class="tab-btn px-6 py-3 rounded-xl font-bold whitespace-nowrap transition-all text-gray-500 hover:bg-orange-50 hover:text-primary flex items-center gap-2"> <span class="material-icons-outlined text-lg">receipt_long</span> Billing </button> <button onclick="switchTab('insurance')" class="tab-btn px-6 py-3 rounded-xl font-bold whitespace-nowrap transition-all text-gray-500 hover:bg-orange-50 hover:text-primary flex items-center gap-2"> <span class="material-icons-outlined text-lg">verified_user</span> Insurance </button> </div> <!-- Profile (Relaxed) --> <div id="profile" class="tab-content active transition-opacity duration-300"> <h3 class="font-bold text-xl mb-6 text-primary border-b pb-2">Update Patient Profile</h3> <form onsubmit="submitForm(event, 'update_profile')" class="space-y-6 max-w-4xl"> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <div> <label class="block text-sm font-semibold text-gray-700 mb-2">Date of Birth</label> <input type="date" name="dob" value="{{ selected_patient.dob if selected_patient else '' }}" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all"> </div> <div> <label class="block text-sm font-semibold text-gray-700 mb-2">Gender</label> <select name="gender" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all"> <option value="">Select Gender</option> <option value="Male" {% if selected_patient and selected_patient.gender=='Male' %}selected{% endif %}>Male</option> <option value="Female" {% if selected_patient and selected_patient.gender=='Female' %}selected{% endif %}>Female</option> <option value="Other" {% if selected_patient and selected_patient.gender=='Other' %}selected{% endif %}>Other</option> </select> </div> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <div> <label class="block text-sm font-semibold text-gray-700 mb-2">Blood Group</label> <select name="blood_group" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all"> <option value="">Select Blood Group</option> {% for bg in ['A+', 'A-', 'B+', 'B-', 'O+', 'O-', 'AB+', 'AB-'] %} <option value="{{ bg }}" {% if selected_patient and selected_patient.blood_group==bg %}selected{% endif %}>{{ bg }}</option> {% endfor %} </select> </div> <div> <label class="block text-sm font-semibold text-gray-700 mb-2">Phone Number</label> <input type="text" name="phone" value="{{ selected_patient.phone if selected_patient else '' }}" placeholder="Patient Phone" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all"> </div> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <div class="md:col-span-2"> <label class="block text-sm font-semibold text-gray-700 mb-2">Address</label> <input type="text" name="address" value="{{ selected_patient.address if selected_patient else '' }}" placeholder="Full Address" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all"> </div> <div class="md:col-span-2"> <label class="block text-sm font-semibold text-gray-700 mb-2">Emergency Contact</label> <input type="text" name="emergency_contact" value="{{ selected_patient.emergency_contact if selected_patient else '' }}" placeholder="Name & Phone Number" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all"> </div> </div> <div class="pt-4"> <button type="button" onclick="stageRecord('update_profile')" class="bg-blue-600 text-white px-10 py-4 rounded-xl shadow-lg hover:bg-blue-700 transition-all font-bold text-lg w-full md:w-auto transform hover:translate-y-[-2px] flex items-center justify-center gap-2"> <span class="material-icons-outlined">update</span> Stage Profile Update </button> </div> </form> </div> <!-- Medical History --> <div id="summary" class="tab-content"> {% if medical_history %} <div class="mb-10 p-6 bg-gray-50 rounded-2xl border border-gray-100"> <h3 class="font-bold text-lg mb-4 text-slate-700">Recent Medical History</h3> <div class="overflow-x-auto"> <table class="w-full text-left bg-white rounded-xl shadow-sm overflow-hidden border border-gray-100"> <thead class="bg-orange-50 text-primary font-bold text-sm uppercase"> <tr> <th class="p-4">Date</th> <th class="p-4">Condition</th> <th class="p-4">Notes</th> <th class="p-4">Actions</th> </tr> </thead> <tbody class="divide-y divide-gray-100"> {% for h in medical_history %} <tr class="hover:bg-gray-50 transition-colors"> <td class="p-4 text-sm font-medium">{{ h.diagnosis_date }}</td> <td class="p-4 font-bold text-slate-700">{{ h.condition }}</td> <td class="p-4 text-sm text-gray-600 truncate max-w-xs">{{ h.notes }}</td> <td class="p-4 text-sm"> <button onclick='editRecord("summary", "{{ h.id }}", {{ h|tojson }})' class="text-primary hover:text-orange-700 font-bold text-xs bg-orange-50 px-3 py-1 rounded transition-colors"> Edit </button> </td> </tr> {% endfor %} </tbody> </table> </div> </div> {% endif %} <div class="max-w-4xl"> <h3 class="font-bold text-2xl mb-6 text-primary flex items-center gap-2"> <span class="material-icons-outlined">post_add</span> Add Medical History </h3> <!-- Staged Items Area --> <div id="staged-summary" class="hidden mb-6 p-4 bg-orange-50 rounded-xl border border-orange-200"> <h4 class="font-bold text-gray-700 mb-2">Pending Records</h4> <div class="staged-list space-y-2"></div> </div> <form id="form-summary" class="space-y-8"> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <div> <label class="block text-sm font-bold text-gray-500 mb-2">Diagnosis Date</label> <input type="date" name="diagnosis_date" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4" required> </div> <div> <label class="block text-sm font-bold text-gray-500 mb-2">Condition Name</label> <input type="text" name="condition" placeholder="Condition / Disease" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4" required> </div> </div> <div> <label class="block text-sm font-bold text-gray-500 mb-2">Clinical Notes</label> <textarea name="notes" placeholder="General Notes / Outcome" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 h-32"></textarea> </div> <div class="bg-gray-50 p-6 rounded-2xl border border-dashed border-gray-300"> <h4 class="font-bold text-lg text-slate-700 mb-4">Detailed Background</h4> <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> <textarea name="medications_history" placeholder="Medications History" class="w-full rounded-xl border-gray-200 p-4 h-24"></textarea> <textarea name="allergies" placeholder="Allergies & Reactions" class="w-full rounded-xl border-gray-200 p-4 h-24"></textarea> <textarea name="family_history" placeholder="Family History" class="w-full rounded-xl border-gray-200 p-4 h-24"></textarea> </div> </div> <button type="button" onclick="stageRecord('summary')" class="bg-blue-600 text-white px-10 py-4 rounded-xl shadow-lg hover:bg-blue-700 transition-all font-bold text-lg w-full md:w-auto transform hover:translate-y-[-2px] flex items-center justify-center gap-2"> <span class="material-icons-outlined">add_circle</span> Stage Record </button> </form> </div> </div> <!-- Consultation --> <div id="consultation" class="tab-content"> {% if consultations %} <div class="mb-10 p-6 bg-gray-50 rounded-2xl border border-gray-100"> <h3 class="font-bold text-lg mb-4 text-slate-700">Recent Consultations</h3> <div class="overflow-x-auto"> <table class="w-full text-left bg-white rounded-xl shadow-sm overflow-hidden border border-gray-100"> <thead class="bg-orange-50 text-primary font-bold text-sm uppercase"> <tr> <th class="p-4">Date</th> <th class="p-4">Doctor</th> <th class="p-4">Diagnosis</th> <th class="p-4">Actions</th> </tr> </thead> <tbody class="divide-y divide-gray-100"> {% for c in consultations %} <tr class="hover:bg-gray-50 transition-colors"> <td class="p-4 text-sm font-medium">{{ c.date }}</td> <td class="p-4 text-sm">{{ c.doctor_name }}</td> <td class="p-4 font-bold text-slate-700">{{ c.diagnosis }}</td> <td class="p-4 text-sm"> <button onclick='editRecord("consultation", "{{ c.id }}", {{ c|tojson }})' class="text-primary hover:text-orange-700 font-bold text-xs bg-orange-50 px-3 py-1 rounded transition-colors"> Edit </button> </td> </tr> {% endfor %} </tbody> </table> </div> </div> {% endif %} <div class="max-w-4xl"> <h3 class="font-bold text-2xl mb-6 text-primary flex items-center gap-2"> <span class="material-icons-outlined">medical_services</span> Add Consultation </h3> <!-- Staged Items Area --> <div id="staged-consultation" class="hidden mb-6 p-4 bg-orange-50 rounded-xl border border-orange-200"> <h4 class="font-bold text-gray-700 mb-2">Pending Consultations</h4> <div class="staged-list space-y-2"></div> </div> <form id="form-consultation" class="space-y-8"> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <input type="date" name="date" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4" required> <input type="text" name="title" placeholder="Visit Title (e.g. Annual Physical)" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4"> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <input type="text" name="doctor_name" placeholder="Doctor Name" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4"> <input type="text" name="prescription" placeholder="Prescription Summary" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4"> </div> <div class="bg-orange-50 p-6 rounded-2xl border border-orange-100"> <h4 class="font-bold text-lg text-primary mb-4 flex items-center gap-2"><span class="material-icons-outlined">monitor_heart</span> Vitals</h4> <div class="grid grid-cols-2 md:grid-cols-2 lg:grid-cols-4 gap-4"> <input type="text" name="vitals_bp" placeholder="BP (120/80)" class="w-full rounded-lg border-gray-200 p-3 text-sm focus:ring-1 focus:ring-primary"> <input type="text" name="vitals_pulse" placeholder="Pulse (bpm)" class="w-full rounded-lg border-gray-200 p-3 text-sm focus:ring-1 focus:ring-primary"> <input type="text" name="vitals_temp" placeholder="Temp (°F)" class="w-full rounded-lg border-gray-200 p-3 text-sm focus:ring-1 focus:ring-primary"> <input type="text" name="vitals_spo2" placeholder="SpO2 (%)" class="w-full rounded-lg border-gray-200 p-3 text-sm focus:ring-1 focus:ring-primary"> <input type="text" name="vitals_weight" placeholder="Weight (kg)" class="w-full rounded-lg border-gray-200 p-3 text-sm focus:ring-1 focus:ring-primary"> <input type="text" name="vitals_height" placeholder="Height (cm)" class="w-full rounded-lg border-gray-200 p-3 text-sm focus:ring-1 focus:ring-primary"> <input type="text" name="vitals_respiratory_rate" placeholder="Resp Rate" class="w-full rounded-lg border-gray-200 p-3 text-sm focus:ring-1 focus:ring-primary"> <input type="text" name="vitals_bmi" placeholder="BMI" class="w-full rounded-lg border-gray-200 p-3 text-sm focus:ring-1 focus:ring-primary"> </div> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <textarea name="symptoms" placeholder="Symptoms / Complaints" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 h-32" required></textarea> <textarea name="diagnosis" placeholder="Diagnosis" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 h-32" required></textarea> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <textarea name="treatment_given" placeholder="Treatment Given" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 h-32"></textarea> <textarea name="follow_up_plan" placeholder="Follow-up Plan" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 h-32"></textarea> </div> <button type="button" onclick="stageRecord('consultation')" class="bg-blue-600 text-white px-10 py-4 rounded-xl shadow-lg hover:bg-blue-700 transition-all font-bold text-lg w-full md:w-auto transform hover:translate-y-[-2px] flex items-center justify-center gap-2"> <span class="material-icons-outlined">add_circle</span> Stage Consultation </button> </form> </div> </div> <!-- Test Report --> <div id="test" class="tab-content"> {% if test_reports %} <div class="mb-10 p-6 bg-gray-50 rounded-2xl border border-gray-100"> <h3 class="font-bold text-lg mb-4 text-slate-700">Recent Lab/Image Reports</h3> <div class="overflow-x-auto"> <table class="w-full text-left bg-white rounded-xl shadow-sm overflow-hidden border border-gray-100"> <thead class="bg-orange-50 text-primary font-bold text-sm uppercase"> <tr> <th class="p-4">Date</th> <th class="p-4">Test Name</th> <th class="p-4">Result</th> <th class="p-4">Actions</th> </tr> </thead> <tbody class="divide-y divide-gray-100"> {% for t in test_reports %} <tr class="hover:bg-gray-50 transition-colors"> <td class="p-4 text-sm font-medium">{{ t.date }}</td> <td class="p-4 text-sm">{{ t.test_name }}</td> <td class="p-4 text-sm truncate max-w-xs">{{ t.result }}</td> <td class="p-4 text-sm"> <button onclick='editRecord("test", "{{ t.id }}", {{ t|tojson }})' class="text-primary hover:text-orange-700 font-bold text-xs bg-orange-50 px-3 py-1 rounded transition-colors"> Edit </button> </td> </tr> {% endfor %} </tbody> </table> </div> </div> {% endif %} <div class="max-w-4xl"> <h3 class="font-bold text-2xl mb-6 text-primary flex items-center gap-2"> <span class="material-icons-outlined">biotech</span> Add Lab/Image Report </h3> <!-- Staged Items Area --> <div id="staged-test" class="hidden mb-6 p-4 bg-orange-50 rounded-xl border border-orange-200"> <h4 class="font-bold text-gray-700 mb-2">Pending Reports</h4> <div class="staged-list space-y-2"></div> </div> <form id="form-test" enctype="multipart/form-data" class="space-y-8"> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <input type="date" name="date" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4" required> <input type="text" name="test_name" placeholder="Test Name (e.g. CBC, X-Ray)" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4" required> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <textarea name="result" placeholder="Result Summary / Data" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 h-32"></textarea> <textarea name="notes" placeholder="Interpretation / Doctor Notes" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 h-32"></textarea> </div> <div class="text-sm text-orange-600 bg-orange-50 p-2 rounded"> <i class="material-icons-outlined text-sm align-middle">info</i> File upload unavailable in Batch Mode. Use Edit later to attach files. </div> <button type="button" onclick="stageRecord('test')" class="bg-blue-600 text-white px-10 py-4 rounded-xl shadow-lg hover:bg-blue-700 transition-all font-bold text-lg w-full md:w-auto transform hover:translate-y-[-2px] flex items-center justify-center gap-2"> <span class="material-icons-outlined">add_circle</span> Stage Report </button> </form> </div> </div> <!-- Treatment --> <div id="treatment" class="tab-content"> {% if treatments %} <div class="mb-10 p-6 bg-gray-50 rounded-2xl border border-gray-100"> <h3 class="font-bold text-lg mb-4 text-slate-700">Active & Past Treatments</h3> <div class="overflow-x-auto"> <table class="w-full text-left bg-white rounded-xl shadow-sm overflow-hidden border border-gray-100"> <thead class="bg-orange-50 text-primary font-bold text-sm uppercase"> <tr> <th class="p-4">Name</th> <th class="p-4">Start Date</th> <th class="p-4">Status</th> <th class="p-4">Actions</th> </tr> </thead> <tbody class="divide-y divide-gray-100"> {% for t in treatments %} <tr class="hover:bg-gray-50 transition-colors"> <td class="p-4 font-bold text-slate-700">{{ t.treatment_name }}</td> <td class="p-4 text-sm">{{ t.start_date }}</td> <td class="p-4 text-sm"> <span class="px-3 py-1 rounded-full text-xs font-bold {% if t.status == 'Active' %}bg-green-100 text-green-700{% else %}bg-gray-100 text-gray-700{% endif %}"> {{ t.status }} </span> </td> <td class="p-4 text-sm"> <button onclick='editRecord("treatment", "{{ t.id }}", {{ t|tojson }})' class="text-primary hover:text-orange-700 font-bold text-xs bg-orange-50 px-3 py-1 rounded transition-colors"> Edit </button> </td> </tr> {% endfor %} </tbody> </table> </div> </div> {% endif %} <div class="max-w-4xl"> <h3 class="font-bold text-2xl mb-6 text-primary flex items-center gap-2"> <span class="material-icons-outlined">healing</span> Add Treatment Plan </h3> <!-- Staged Items Area --> <div id="staged-treatment" class="hidden mb-6 p-4 bg-orange-50 rounded-xl border border-orange-200"> <h4 class="font-bold text-gray-700 mb-2">Pending Treatments</h4> <div class="staged-list space-y-2"></div> </div> <form id="form-treatment" class="space-y-8"> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <input type="text" name="treatment_name" placeholder="Treatment Name" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4" required> <select name="status" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4"> <option value="Active">Active</option> <option value="Completed">Completed</option> </select> </div> <div class="grid grid-cols-2 gap-8"> <div><label class="block text-sm font-bold text-gray-500 mb-2">Start Date</label><input type="date" name="start_date" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4" required></div> <div><label class="block text-sm font-bold text-gray-500 mb-2">End Date</label><input type="date" name="end_date" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4"></div> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <textarea name="medications_detail" placeholder="Medications Details (Name, Dosage)" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 h-32"></textarea> <textarea name="treatment_goals" placeholder="Treatment Goals" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 h-32"></textarea> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <textarea name="monitoring_plan" placeholder="Monitoring Plan" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 h-32"></textarea> <textarea name="notes" placeholder="Progress Notes" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 h-32"></textarea> </div> <button type="button" onclick="stageRecord('treatment')" class="bg-blue-600 text-white px-10 py-4 rounded-xl shadow-lg hover:bg-blue-700 transition-all font-bold text-lg w-full md:w-auto transform hover:translate-y-[-2px] flex items-center justify-center gap-2"> <span class="material-icons-outlined">add_circle</span> Stage Treatment </button> </form> </div> </div> <!-- Billing --> <div id="billing" class="tab-content"> {% if billings %} <div class="mb-10 p-6 bg-gray-50 rounded-2xl border border-gray-100"> <h3 class="font-bold text-lg mb-4 text-slate-700">Billing History</h3> <div class="overflow-x-auto"> <table class="w-full text-left bg-white rounded-xl shadow-sm overflow-hidden border border-gray-100"> <thead class="bg-orange-50 text-primary font-bold text-sm uppercase"> <tr> <th class="p-4">Date</th> <th class="p-4">Description</th> <th class="p-4">Amount</th> <th class="p-4">Status</th> <th class="p-4">Actions</th> </tr> </thead> <tbody class="divide-y divide-gray-100"> {% for b in billings %} <tr class="hover:bg-gray-50 transition-colors"> <td class="p-4 text-sm">{{ b.date }}</td> <td class="p-4 text-sm font-medium">{{ b.description }}</td> <td class="p-4 font-bold text-slate-800">₹{{ b.amount }}</td> <td class="p-4 text-sm"> <span class="px-3 py-1 rounded-full text-xs font-bold {% if b.status == 'Paid' %}bg-green-100 text-green-700{% elif b.status == 'Pending' %}bg-yellow-100 text-yellow-700{% else %}bg-red-100 text-red-700{% endif %}"> {{ b.status }} </span> </td> <td class="p-4 text-sm"> <button onclick='editRecord("billing", "{{ b.id }}", {{ b|tojson }})' class="text-primary hover:text-orange-700 font-bold text-xs bg-orange-50 px-3 py-1 rounded transition-colors"> Edit </button> </td> </tr> {% endfor %} </tbody> </table> </div> </div> {% endif %} <div class="max-w-4xl"> <h3 class="font-bold text-2xl mb-6 text-primary flex items-center gap-2"> <span class="material-icons-outlined">receipt_long</span> Add Billing Record </h3> <!-- Staged Items Area --> <div id="staged-billing" class="hidden mb-6 p-4 bg-orange-50 rounded-xl border border-orange-200"> <h4 class="font-bold text-gray-700 mb-2">Pending Bills</h4> <div class="staged-list space-y-2"></div> </div> <form id="form-billing" class="space-y-8"> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <input type="date" name="date" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4" required> <input type="number" step="0.01" name="amount" placeholder="Amount (₹)" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4" required> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <input type="text" name="description" placeholder="Description of Charge" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4" required> <select name="status" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4"> <option value="Pending">Pending</option> <option value="Paid">Paid</option> <option value="Insurance Claimed">Insurance Claimed</option> <option value="Overdue">Overdue</option> </select> </div> <button type="button" onclick="stageRecord('billing')" class="bg-blue-600 text-white px-10 py-4 rounded-xl shadow-lg hover:bg-blue-700 transition-all font-bold text-lg w-full md:w-auto transform hover:translate-y-[-2px] flex items-center justify-center gap-2"> <span class="material-icons-outlined">add_circle</span> Stage Bill </button> </form> </div> </div> <!-- Insurance (Relaxed) --> <div id="insurance" class="tab-content"> <h3 class="font-bold text-xl mb-6 text-primary border-b pb-2">Update Insurance Details</h3> <form onsubmit="submitForm(event, 'insurance')" class="space-y-6 max-w-4xl"> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <div> <label class="block text-sm font-semibold text-gray-700 mb-2">Provider Name</label> <input type="text" name="provider" value="{{ insurance.provider if insurance else '' }}" placeholder="e.g. BCBS" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all" required> </div> <div> <label class="block text-sm font-semibold text-gray-700 mb-2">Plan Type</label> <input type="text" name="plan_type" value="{{ insurance.plan_type if insurance else '' }}" placeholder="e.g. PPO Gold" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all"> </div> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <!-- 2 cols instead of 3 for space --> <div> <label class="block text-sm font-semibold text-gray-700 mb-2">Policy Number</label> <input type="text" name="policy_number" value="{{ insurance.policy_number if insurance else '' }}" placeholder="Policy Number" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all" required> </div> <div> <label class="block text-sm font-semibold text-gray-700 mb-2">Group Number</label> <input type="text" name="group_number" value="{{ insurance.group_number if insurance else '' }}" placeholder="Group Number" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all"> </div> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-8"> <div> <label class="block text-sm font-semibold text-gray-700 mb-2">Effective Date</label> <input type="date" name="effective_date" value="{{ insurance.effective_date if insurance else '' }}" placeholder="Effective Date" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all"> </div> <div> <label class="block text-sm font-semibold text-gray-700 mb-2">Deductible</label> <input type="text" name="deductible" value="{{ insurance.deductible if insurance else '' }}" placeholder="Amount" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all"> </div> <div> <label class="block text-sm font-semibold text-gray-700 mb-2">Out of Pocket Max</label> <input type="text" name="oop_max" value="{{ insurance.oop_max if insurance else '' }}" placeholder="Amount" class="w-full rounded-xl border-gray-200 bg-gray-50 p-4 shadow-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all"> </div> </div> <div class="pt-4"> <button type="submit" class="bg-primary text-white px-10 py-4 rounded-xl shadow-lg hover:bg-orange-600 transition-all font-bold text-lg w-full md:w-auto transform hover:translate-y-[-2px]"> Save Insurance Info </button> </div> </form> </div> </div> <!-- Floating Action Buttons --> {% if selected_patient %} <div class="fixed bottom-8 right-8 z-50 flex flex-col gap-4 animate-fade-in-up"> <button onclick="enhanceAllNotes()" class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-4 px-8 rounded-full shadow-2xl flex items-center justify-center gap-3 transform hover:scale-105 transition-all text-lg"> <span class="material-icons-outlined">auto_awesome</span> Enhance All Notes </button> <button onclick="saveAllData()" class="bg-green-600 hover:bg-green-700 text-white font-bold py-4 px-8 rounded-full shadow-2xl flex items-center justify-center gap-3 transform hover:scale-105 transition-all text-lg"> <span class="material-icons-outlined">save</span> Save Complete Record </button> </div> {% endif %} </main> <script> let currentPatientId = "{{ selected_patient.id if selected_patient else '' }}"; async function selectPatient(id, name, phone) { // Visual feedback - Highlight selected sidebar item document.querySelectorAll('button[onclick^="selectPatient"]').forEach(btn => { btn.classList.remove('bg-gradient-to-r', 'from-orange-50', 'to-white', 'border-l-4', 'border-primary', 'shadow-sm'); btn.classList.add('bg-white', 'hover:bg-gray-50'); if (btn.getAttribute('onclick').includes(`'${id}'`)) { btn.classList.remove('bg-white', 'hover:bg-gray-50'); btn.classList.add('bg-gradient-to-r', 'from-orange-50', 'to-white', 'border-l-4', 'border-primary', 'shadow-sm'); } }); // Fetch Data try { // Show loading state if needed (optional) const response = await fetch(`/assistant/get_patient_data/${id}`); if (!response.ok) throw new Error("Failed to fetch data"); const data = await response.json(); renderPatientData(data); currentPatientId = id; // Update URL without reload const url = new URL(window.location.href); url.searchParams.set('patient_id', id); window.history.pushState({}, '', url); } catch (err) { console.error(err); alert("Error loading patient data: " + err.message); } } function renderPatientData(data) { const p = data.user; if (!p) return; // 1. Update Header const headerInfo = document.querySelector('#entry-area .flex.items-center.gap-3'); if (headerInfo) { headerInfo.innerHTML = ` <span class="font-semibold text-lg text-primary">${p.name}</span> <span class="text-sm bg-gray-100 px-2 py-1 rounded">ID: ${p.patient_id || p.id}</span> `; } // Show Entry Area document.getElementById('entry-area').classList.remove('hidden'); // 2. Populate Profile Form const formProfile = document.querySelector('form[onsubmit*="update_profile"]'); if (formProfile) { setVal(formProfile, 'dob', p.dob); setVal(formProfile, 'gender', p.gender); setVal(formProfile, 'blood_group', p.blood_group); setVal(formProfile, 'phone', p.phone); setVal(formProfile, 'address', p.address); setVal(formProfile, 'emergency_contact', p.emergency_contact); } // 3. Populate Insurance Form const formIns = document.querySelector('form[onsubmit*="insurance"]'); if (formIns) { const ins = data.insurance || {}; setVal(formIns, 'provider', ins.provider); setVal(formIns, 'plan_type', ins.plan_type); setVal(formIns, 'policy_number', ins.policy_number); setVal(formIns, 'group_number', ins.group_number); setVal(formIns, 'effective_date', ins.effective_date); setVal(formIns, 'deductible', ins.deductible); setVal(formIns, 'oop_max', ins.oop_max); } // 4. Render Tables renderTable('summary', data.medical_history, (item) => ` <td class="p-4 text-sm font-medium">${item.diagnosis_date || '-'}</td> <td class="p-4 font-bold text-slate-700">${item.condition || '-'}</td> <td class="p-4 text-sm text-gray-600 truncate max-w-xs">${item.notes || '-'}</td> <td class="p-4 text-sm"> <button onclick='editRecord("summary", "${item.id}", ${JSON.stringify(item)})' class="text-primary hover:text-orange-700 font-bold text-xs bg-orange-50 px-3 py-1 rounded transition-colors">Edit</button> </td> `); renderTable('consultation', data.consultations, (item) => ` <td class="p-4 text-sm font-medium">${item.date || '-'}</td> <td class="p-4 text-sm">${item.doctor_name || '-'}</td> <td class="p-4 font-bold text-slate-700">${item.diagnosis || '-'}</td> <td class="p-4 text-sm"> <button onclick='editRecord("consultation", "${item.id}", ${JSON.stringify(item)})' class="text-primary hover:text-orange-700 font-bold text-xs bg-orange-50 px-3 py-1 rounded transition-colors">Edit</button> </td> `); renderTable('test', data.test_reports, (item) => ` <td class="p-4 text-sm font-medium">${item.date || '-'}</td> <td class="p-4 text-sm">${item.test_name || '-'}</td> <td class="p-4 text-sm truncate max-w-xs">${item.result || '-'}</td> <td class="p-4 text-sm"> <button onclick='editRecord("test", "${item.id}", ${JSON.stringify(item)})' class="text-primary hover:text-orange-700 font-bold text-xs bg-orange-50 px-3 py-1 rounded transition-colors">Edit</button> </td> `); renderTable('treatment', data.treatments, (item) => ` <td class="p-4 font-bold text-slate-700">${item.treatment_name || '-'}</td> <td class="p-4 text-sm">${item.start_date || '-'}</td> <td class="p-4 text-sm"> <span class="px-3 py-1 rounded-full text-xs font-bold ${item.status === 'Active' ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-700'}">${item.status}</span> </td> <td class="p-4 text-sm"> <button onclick='editRecord("treatment", "${item.id}", ${JSON.stringify(item)})' class="text-primary hover:text-orange-700 font-bold text-xs bg-orange-50 px-3 py-1 rounded transition-colors">Edit</button> </td> `); renderTable('billing', data.billings, (item) => ` <td class="p-4 text-sm">${item.date || '-'}</td> <td class="p-4 text-sm font-medium">${item.description || '-'}</td> <td class="p-4 font-bold text-slate-800">$${item.amount || '0'}</td> <td class="p-4 text-sm"> <span class="px-3 py-1 rounded-full text-xs font-bold ${item.status === 'Paid' ? 'bg-green-100 text-green-700' : (item.status === 'Pending' ? 'bg-yellow-100 text-yellow-700' : 'bg-red-100 text-red-700')}">${item.status}</span> </td> <td class="p-4 text-sm"> <button onclick='editRecord("billing", "${item.id}", ${JSON.stringify(item)})' class="text-primary hover:text-orange-700 font-bold text-xs bg-orange-50 px-3 py-1 rounded transition-colors">Edit</button> </td> `); // 5. Show Save Button (if not already shown) let saveBtnContainer = document.querySelector('#save-btn-container'); if (!saveBtnContainer) { // Inject if missing (because page loaded without patient first) const btnHtml = ` <div class="fixed bottom-8 right-8 z-50 flex flex-col gap-4 animate-fade-in-up" id="save-btn-container"> <button onclick="enhanceAllNotes()" class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-4 px-8 rounded-full shadow-2xl flex items-center justify-center gap-3 transform hover:scale-105 transition-all text-lg"> <span class="material-icons-outlined">auto_awesome</span> Enhance All Notes </button> <button onclick="saveAllData()" class="bg-green-600 hover:bg-green-700 text-white font-bold py-4 px-8 rounded-full shadow-2xl flex items-center justify-center gap-3 transform hover:scale-105 transition-all text-lg"> <span class="material-icons-outlined">save</span> Save Complete Record </button> </div>`; document.body.insertAdjacentHTML('beforeend', btnHtml); } // 6. Reset Staged Areas document.querySelectorAll('.staged-list').forEach(el => el.innerHTML = ''); document.querySelectorAll('[id^="staged-"]').forEach(el => el.classList.add('hidden')); stagedData = { summary: [], consultation: [], test: [], treatment: [], billing: [], update_profile: [] }; // 7. Reset Add Forms ['form-summary', 'form-consultation', 'form-test', 'form-treatment', 'form-billing'].forEach(id => { const f = document.getElementById(id); if (f) f.reset(); }); } function setVal(form, name, val) { const inp = form.querySelector(`[name="${name}"]`); if (inp) inp.value = val || ''; } function renderTable(tabId, items, rowHtmlFn) { const container = document.getElementById(tabId); if (!container) return; const tableBody = container.querySelector('tbody'); const tableWrapper = container.querySelector('.mb-10'); // The div wrapping the table header/body if (items && items.length > 0) { if (tableBody) { tableBody.innerHTML = items.map(rowHtmlFn).join(''); } if (tableWrapper) tableWrapper.classList.remove('hidden'); // Ensure table is visible } else { // Hide table if empty if (tableWrapper) tableWrapper.classList.add('hidden'); } } function switchTab(tabId) { // Hide all contents document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active')); // Deactivate all buttons document.querySelectorAll('.tab-btn').forEach(el => { el.classList.remove('active', 'bg-orange-50', 'text-primary'); el.classList.add('text-gray-600'); }); // Show selected content document.getElementById(tabId).classList.add('active'); // Update Header Name const titles = { 'profile': 'Patient Profile', 'summary': 'Medical History', 'consultation': 'Consultations', 'test': 'Lab & Test Reports', 'treatment': 'Treatment Plans', 'billing': 'Billing & Invoices', 'insurance': 'Insurance Details' }; const header = document.getElementById('tab-header'); if (header) header.innerText = titles[tabId] || 'Entry'; // Activate button const buttons = document.querySelectorAll('.tab-btn'); buttons.forEach(btn => { if (btn.getAttribute('onclick').includes(tabId)) { btn.classList.add('active', 'bg-orange-50', 'text-primary'); btn.classList.remove('text-gray-600'); } }); } function submitForm(event, type) { // Check if it's a direct submit or just preventing default if (event.target.action.includes('edit_record')) { // Let the form submit naturally if action is set to edit_record return; } event.preventDefault(); if (!currentPatientId) { alert("Please select a patient first"); return; } const form = event.target; if (type === 'update_profile') { form.action = `/assistant/update_profile/${currentPatientId}`; } else if (type === 'insurance') { form.action = `/assistant/update_insurance/${currentPatientId}`; } else { form.action = `/assistant/add_record/${type}/${currentPatientId}`; } form.method = "POST"; form.submit(); } function editRecord(type, id, data) { console.log("Editing", type, id, data); // 1. Find the active tab's form const tab = document.getElementById(type); if (!tab) return; const form = tab.querySelector('form'); if (!form) return; // 2. Populate Fields using name attribute for (const [key, value] of Object.entries(data)) { // Find input/select/textarea with matching name const field = form.querySelector(`[name="${key}"]`); if (field) { field.value = value; } } // 3. Update Form Action to Edit Route form.action = `/assistant/edit_record/${type}/${id}`; form.onsubmit = null; // Removing the add_record handler // 4. Update Button Text const btn = form.querySelector('button[type="submit"]'); if (btn) { btn.innerText = "Update Record"; btn.classList.remove('bg-primary'); btn.classList.add('bg-green-600', 'hover:bg-green-700'); } // 5. Scroll to Form form.scrollIntoView({ behavior: 'smooth', block: 'center' }); // 6. Highlight form.classList.add('ring-4', 'ring-green-100', 'rounded-xl'); setTimeout(() => form.classList.remove('ring-4', 'ring-green-100'), 2000); } // Initialize Staged Data let stagedData = { summary: [], consultation: [], test: [], treatment: [], billing: [], update_profile: [] }; function stageRecord(type) { const form = document.getElementById(`form-${type}`); if (!form) { if (type === 'update_profile') { const pForm = document.querySelector('form[onsubmit*="update_profile"]'); if (pForm) stageProfile(pForm); return; } console.error("Form not found for " + type); return; } if (!form.reportValidity()) return; const formData = new FormData(form); const data = Object.fromEntries(formData.entries()); // Add to Staged Data if (!stagedData[type]) stagedData[type] = []; stagedData[type].push(data); // Update UI renderStagedItems(type); // Clear Form form.reset(); // Visual feedback on button const btn = form.querySelector('button[type="button"]'); if (btn) { const originalText = btn.innerHTML; btn.innerHTML = `<span class="material-icons-outlined">check</span> Staged!`; btn.classList.add('bg-green-600', 'text-white'); btn.classList.remove('bg-blue-600'); setTimeout(() => { btn.innerHTML = originalText; btn.classList.remove('bg-green-600'); btn.classList.add('bg-blue-600'); }, 1500); } } function stageProfile(form) { if (!form.reportValidity()) return; const formData = new FormData(form); const data = Object.fromEntries(formData.entries()); // Overwrite profile staging stagedData['update_profile'] = [data]; // Feedback const btn = form.querySelector('button'); if (btn) { const originalText = btn.innerHTML; btn.innerHTML = `<span class="material-icons-outlined">check</span> Staged!`; btn.classList.add('bg-green-600'); setTimeout(() => { btn.innerHTML = originalText; btn.classList.remove('bg-green-600'); }, 1500); } } function renderStagedItems(type) { const container = document.getElementById(`staged-${type}`); if (!container) return; const list = container.querySelector('.staged-list'); list.innerHTML = ''; if (stagedData[type].length > 0) { container.classList.remove('hidden'); } else { container.classList.add('hidden'); } stagedData[type].forEach((item, index) => { const div = document.createElement('div'); div.className = "flex justify-between items-center bg-white p-3 rounded-lg shadow-sm text-sm border-l-4 border-blue-500 animate-[fadeIn_0.3s_ease-in-out]"; let label = item.test_name || item.condition || item.diagnosis || item.treatment_name || (item.amount ? `$${item.amount}` : 'Record'); let date = item.date || item.diagnosis_date || item.start_date || ''; if (date) label += ` (${date})`; div.innerHTML = ` <div class="flex items-center gap-2"> <span class="material-icons-outlined text-gray-400 text-sm">circle</span> <span class="font-medium text-gray-800">${label}</span> </div> <button onclick="removeStaged('${type}', ${index})" class="text-red-400 hover:text-red-600 hover:bg-red-50 p-1 rounded-full transition-colors" title="Remove"> <span class="material-icons-outlined text-lg">close</span> </button> `; list.appendChild(div); }); } function removeStaged(type, index) { stagedData[type].splice(index, 1); renderStagedItems(type); } async function saveAllData() { if (!currentPatientId) { alert("No patient selected!"); return; } const payload = {}; // 1. Collect Staged Lists for (const [key, list] of Object.entries(stagedData)) { if (key === 'update_profile') continue; if (list && list.length > 0) { payload[key] = list; } } // 2. Profile Logic if (stagedData['update_profile'] && stagedData['update_profile'].length > 0) { payload.profile = stagedData['update_profile'][0]; } else { const pForm = document.querySelector('form[onsubmit*="update_profile"]'); if (pForm) { const fd = new FormData(pForm); payload.profile = Object.fromEntries(fd.entries()); } } // 3. Insurance direct const iForm = document.querySelector('form[onsubmit*="insurance"]'); if (iForm) { const fd = new FormData(iForm); payload.insurance = Object.fromEntries(fd.entries()); } if (Object.keys(payload).length === 0) { alert("No data staged or info to save."); return; } // Send to Backend try { const btn = document.querySelector('button[onclick="saveAllData()"]'); const originalText = btn.innerHTML; btn.innerHTML = `<span class="material-icons-outlined animate-spin">refresh</span> Saving...`; btn.disabled = true; const response = await fetch(`/assistant/save_complete_record/${currentPatientId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const result = await response.json(); if (result.success) { btn.innerHTML = `<span class="material-icons-outlined">check_circle</span> Saved!`; btn.classList.replace('bg-green-600', 'bg-green-800'); setTimeout(() => { window.location.href = result.redirect || `/assistant/data_entry_dashboard?q=${currentPatientId}`; }, 1000); } else { alert("Error: " + result.message); btn.innerHTML = originalText; btn.disabled = false; } } catch (err) { console.error(err); alert("An error occurred while saving."); const btn = document.querySelector('button[onclick="saveAllData()"]'); if (btn) btn.disabled = false; } } async function enhanceAllNotes() { if (!currentPatientId) { alert("Please select a patient first."); return; } if (!confirm("Are you sure you want to enhance all clinical notes for this patient? This action will overwrite existing notes with AI-improved versions.")) { return; } const btn = document.querySelector('button[onclick="enhanceAllNotes()"]'); const originalHtml = btn.innerHTML; btn.innerHTML = `<span class="material-icons-outlined animate-spin">refresh</span> Enhancing...`; btn.disabled = true; try { const response = await fetch(`/api/enhancer/enhance_patient/${currentPatientId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, }); const result = await response.json(); if (response.ok) { alert(`Enhancement complete! ${result.changes.length} fields were updated.`); window.location.reload(); // Reload to see the changes } else { throw new Error(result.error || "An unknown error occurred."); } } catch (error) { console.error("Enhancement error:", error); alert("An error occurred during enhancement: " + error.message); btn.innerHTML = originalHtml; btn.disabled = false; } } // Initialize on Load document.addEventListener('DOMContentLoaded', () => { if (currentPatientId) { // Trigger async fetch to ensure data is rendered correctly even on SSR // This fixes issues where Jinja rendering might be incomplete or when auto-select occurs selectPatient(currentPatientId, '', ''); } }); </script> </body> </html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Data Entry - Assistant</title>
<link href="https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Outlined" rel="stylesheet" />
<script src="https://cdn.tailwindcss.com?plugins=forms,typography"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: "#e67e22",
"background-light": "#fef3e9",
},
},
},
};
</script>
<style>
.glass-effect {
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.4);
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
.tab-btn.active {
/* Handled by Tailwind classes in JS now (bg-orange-50, text-primary) */
}
</style>
</head>
<body class="bg-background-light min-h-screen p-4 font-sans text-slate-800">
<header class="max-w-7xl mx-auto p-4 glass-effect rounded-xl shadow-lg mb-8 flex justify-between items-center">
<span class="font-bold text-xl">Swift Query Data Entry</span>
<div class="flex items-center gap-4">
<span class="text-sm">Logged in as: {{ session['user_name'] }} (Data Entry)</span>
<a href="{{ url_for('admin.logout') }}" class="font-medium hover:text-primary">Logout</a>
</div>
</header>
<main class="max-w-7xl mx-auto grid grid-cols-1 md:grid-cols-4 gap-6">
<!-- Patient Selection Sidebar -->
<div class="md:col-span-1 bg-white p-4 rounded-xl shadow-lg h-fit">
<h2 class="font-bold mb-4 text-lg border-b pb-2">Select Patient</h2>
<!-- Search Form -->
<form action="{{ url_for('assistant.data_entry_dashboard') }}" method="get" class="mb-5 relative">
<input type="text" name="q" value="{{ search_query }}" placeholder="Search ID, Name, Phone..."
class="w-full pl-10 pr-4 py-3 bg-gray-50 border-gray-200 rounded-xl text-sm focus:ring-2 focus:ring-primary focus:border-transparent transition-all outline-none">
<span
class="material-icons-outlined absolute left-3 top-1/2 -translate-y-1/2 text-gray-400">search</span>
</form>
<div class="space-y-2 max-h-[350px] overflow-y-auto pr-1 custom-scrollbar">
{% if patients %}
{% for p in patients %}
<button onclick="selectPatient('{{ p.id }}', '{{ p.name }}', '{{ p.phone or '' }}')" class="w-full text-left p-4 rounded-xl transition-all duration-200 group relative overflow-hidden mb-2
{% if selected_patient and selected_patient.id == p.id %}
bg-gradient-to-r from-orange-50 to-white border-l-4 border-primary shadow-sm
{% else %}
bg-white hover:bg-gray-50 border border-transparent hover:border-gray-100 hover:shadow-sm
{% endif %}">
<div class="flex justify-between items-start">
<div>
<span
class="block font-bold text-slate-800 text-lg mb-1 group-hover:text-primary transition-colors">{{
p.name }}</span>
<span
class="text-xs text-gray-500 font-medium bg-gray-100 px-2 py-1 rounded inline-block">ID:
{{ p.patient_id or p.id }}</span>
</div>
{% if p.phone %}
<div class="text-gray-400">
<span class="material-icons-outlined text-sm">phone</span>
</div>
{% endif %}
</div>
</button>
{% endfor %}
{% else %}
<p class="text-sm text-gray-500 text-center py-4">No patients found.</p>
{% endif %}
</div>
</div>
<!-- Data Entry Area -->
<div id="entry-area"
class="md:col-span-3 bg-white p-8 rounded-2xl shadow-lg border border-gray-100 min-h-[700px] {% if not selected_patient %}hidden{% endif %}">
<div class="flex justify-between items-end mb-8 border-b pb-6">
<div>
<h2 class="text-3xl font-bold text-slate-800 mb-1" id="tab-header">Patient Profile</h2>
<div class="flex items-center gap-3 text-gray-500">
<span class="font-semibold text-lg text-primary">{{ selected_patient.name if selected_patient
else '' }}</span>