Spaces:
Runtime error
Runtime error
Download templates/assistant/assistant_data_entry.html from Darshankumarr03/Swift-Query: direct link, hf CLI and curl.
- Browser
- Download file 71.8 kB
-
https://huggingface.co/spaces/Darshankumarr03/Swift-Query/resolve/main/templates/assistant/assistant_data_entry.html
- Command line
-
hf download hf://spaces/Darshankumarr03/Swift-Query/templates/assistant/assistant_data_entry.html
-
curl -L -o assistant_data_entry.html https://huggingface.co/spaces/Darshankumarr03/Swift-Query/resolve/main/templates/assistant/assistant_data_entry.html
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>
<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>