File size: 32,027 Bytes
e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 202b9dc 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 202b9dc e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 7aa8ed5 80949f1 7aa8ed5 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 e14091f 80949f1 7aa8ed5 80949f1 7aa8ed5 80949f1 e14091f 80949f1 e14091f 80949f1 7aa8ed5 80949f1 7aa8ed5 80949f1 7aa8ed5 80949f1 202b9dc 80949f1 202b9dc 80949f1 202b9dc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 |
import sqlite3
import gradio as gr
import pandas as pd
import time
from datetime import datetime, timedelta
import random
import string
import os
# ---------------------------
# DATABASE SETUP
# ---------------------------
def get_db_connection():
"""Create a database connection with proper error handling"""
try:
conn = sqlite3.connect("hospital.db", check_same_thread=False)
conn.row_factory = sqlite3.Row # Return rows as dictionaries
return conn
except sqlite3.Error as e:
print(f"Database connection error: {e}")
return None
conn = get_db_connection()
cursor = conn.cursor()
# Create tables with improved schema
cursor.execute('''CREATE TABLE IF NOT EXISTS doctors (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
specialty TEXT,
avg_consultation_time INTEGER DEFAULT 15, -- in minutes
available BOOLEAN DEFAULT 1
)''')
cursor.execute('''CREATE TABLE IF NOT EXISTS patients (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
phone TEXT NOT NULL,
email TEXT,
symptoms TEXT,
priority INTEGER DEFAULT 3, -- 1=emergency, 2=urgent, 3=normal
doctor_id INTEGER,
queue_number INTEGER,
token TEXT UNIQUE,
registration_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
estimated_start_time TIMESTAMP,
status TEXT DEFAULT 'Waiting',
completed_time TIMESTAMP,
notes TEXT,
FOREIGN KEY (doctor_id) REFERENCES doctors(id)
)''')
cursor.execute('''CREATE TABLE IF NOT EXISTS appointments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_name TEXT NOT NULL,
phone TEXT NOT NULL,
email TEXT,
doctor_id INTEGER,
appointment_date TEXT,
appointment_time TEXT,
reason TEXT,
status TEXT DEFAULT 'Scheduled',
FOREIGN KEY (doctor_id) REFERENCES doctors(id)
)''')
cursor.execute('''CREATE TABLE IF NOT EXISTS notifications (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER,
message TEXT,
sent_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (patient_id) REFERENCES patients(id)
)''')
conn.commit()
# Seed doctors if table is empty
cursor.execute("SELECT COUNT(*) FROM doctors")
if cursor.fetchone()[0] == 0:
doctors = [
("Dr. Smith", "General Medicine", 15, 1),
("Dr. Lee", "Pediatrics", 20, 1),
("Dr. Patel", "Cardiology", 25, 1),
("Dr. Johnson", "Orthopedics", 20, 1),
("Dr. Garcia", "Dermatology", 15, 1)
]
cursor.executemany("INSERT INTO doctors (name, specialty, avg_consultation_time, available) VALUES (?, ?, ?, ?)", doctors)
conn.commit()
# ---------------------------
# HELPER FUNCTIONS
# ---------------------------
def generate_token():
"""Generate a unique alphanumeric token for patients"""
token = ''.join(random.choices(string.ascii_uppercase + string.digits, k=6))
return token
def calculate_wait_time(doctor_id, queue_position):
"""Calculate estimated wait time based on doctor's avg consultation time and queue position"""
cursor.execute("SELECT avg_consultation_time FROM doctors WHERE id=?", (doctor_id,))
avg_time = cursor.fetchone()[0]
# Count how many patients are currently in consultation (usually just 1)
cursor.execute("SELECT COUNT(*) FROM patients WHERE doctor_id=? AND status='In Consultation'", (doctor_id,))
in_consultation = cursor.fetchone()[0]
# Calculate wait time: (patients ahead + in consultation) * avg time
wait_minutes = (queue_position - 1 + in_consultation) * avg_time
# Add some randomness to make it realistic (Β±20%)
variation = random.uniform(0.8, 1.2)
wait_minutes = int(wait_minutes * variation)
return wait_minutes
def format_wait_time(minutes):
"""Format wait time into hours and minutes"""
if minutes < 60:
return f"{minutes} minutes"
hours = minutes // 60
mins = minutes % 60
return f"{hours} hour{'s' if hours > 1 else ''} {mins} minutes"
def update_all_wait_times():
"""Update estimated wait times for all waiting patients"""
# Get all waiting patients
cursor.execute("""
SELECT p.id, p.doctor_id, p.queue_number
FROM patients p
WHERE p.status='Waiting'
ORDER BY p.doctor_id, p.queue_number
""")
waiting_patients = cursor.fetchall()
# Group by doctor
for doctor_id in set([p[1] for p in waiting_patients]):
# Get all patients for this doctor
doctor_patients = [p for p in waiting_patients if p[1] == doctor_id]
# Update wait time for each patient
for patient in doctor_patients:
wait_minutes = calculate_wait_time(doctor_id, patient[2])
estimated_time = datetime.now() + timedelta(minutes=wait_minutes)
cursor.execute(
"UPDATE patients SET estimated_start_time=? WHERE id=?",
(estimated_time.strftime('%Y-%m-%d %H:%M:%S'), patient[0])
)
conn.commit()
# ---------------------------
# CORE FUNCTIONS
# ---------------------------
def register_patient(name, phone, email, symptoms, priority, doctor_name):
"""Register a new patient with improved data validation and wait time estimation"""
# Input validation
if not name or not phone or not doctor_name:
return "Error: Name, phone number, and doctor selection are required."
try:
# Get doctor details
cursor.execute("SELECT id, available FROM doctors WHERE name=?", (doctor_name,))
doctor_result = cursor.fetchone()
if not doctor_result:
return f"Error: Doctor {doctor_name} not found."
doctor_id, is_available = doctor_result
if not is_available:
return f"Sorry, {doctor_name} is currently not available. Please select another doctor."
# Check if patient with same phone is already in queue
cursor.execute("SELECT id FROM patients WHERE phone=? AND status IN ('Waiting', 'In Consultation')", (phone,))
if cursor.fetchone():
return "This phone number is already registered in the active queue."
# Get next queue number
cursor.execute("SELECT MAX(queue_number) FROM patients WHERE doctor_id=?", (doctor_id,))
last_queue = cursor.fetchone()[0]
next_queue = 1 if last_queue is None else last_queue + 1
# Generate unique token
token = generate_token()
while True:
# Check if token already exists
cursor.execute("SELECT id FROM patients WHERE token=?", (token,))
if not cursor.fetchone():
break
token = generate_token() # Generate new token if exists
# Calculate estimated wait time
wait_minutes = calculate_wait_time(doctor_id, next_queue)
estimated_time = datetime.now() + timedelta(minutes=wait_minutes)
# Insert patient
cursor.execute("""
INSERT INTO patients
(name, phone, email, symptoms, priority, doctor_id, queue_number, token, estimated_start_time, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (name, phone, email, symptoms, priority, doctor_id, next_queue, token,
estimated_time.strftime('%Y-%m-%d %H:%M:%S'), 'Waiting'))
conn.commit()
# Get patient ID for notification
patient_id = cursor.lastrowid
# Add welcome notification
notification_msg = f"Welcome {name}! You are registered with {doctor_name}. Your token is {token} and queue number is {next_queue}."
cursor.execute("INSERT INTO notifications (patient_id, message) VALUES (?, ?)",
(patient_id, notification_msg))
conn.commit()
# Update wait times for all patients
update_all_wait_times()
# Format response
wait_time_str = format_wait_time(wait_minutes)
return f"Registered successfully!\n\nYour token: {token}\nQueue number: {next_queue}\nDoctor: {doctor_name}\nEstimated wait time: {wait_time_str}"
except Exception as e:
conn.rollback()
return f"An error occurred: {str(e)}"
def check_status(phone_or_token):
"""Check patient status by phone or token"""
if not phone_or_token:
return "Please enter a phone number or token."
try:
# Try to find by token first (more specific)
cursor.execute("""
SELECT
p.id, p.name, p.token, p.queue_number, p.status, p.estimated_start_time,
d.name as doctor_name, d.specialty
FROM patients p
JOIN doctors d ON p.doctor_id = d.id
WHERE p.token=? AND p.status IN ('Waiting', 'In Consultation')
LIMIT 1
""", (phone_or_token,))
result = cursor.fetchone()
# If not found by token, try phone
if not result:
cursor.execute("""
SELECT
p.id, p.name, p.token, p.queue_number, p.status, p.estimated_start_time,
d.name as doctor_name, d.specialty
FROM patients p
JOIN doctors d ON p.doctor_id = d.id
WHERE p.phone=? AND p.status IN ('Waiting', 'In Consultation')
ORDER BY p.id DESC LIMIT 1
""", (phone_or_token,))
result = cursor.fetchone()
if not result:
return "No active registration found. If you've already completed your visit or haven't registered yet, please check with reception."
# Format estimated time
estimated_time = datetime.strptime(result[5], '%Y-%m-%d %H:%M:%S') if result[5] else None
now = datetime.now()
if estimated_time and estimated_time > now:
time_diff = estimated_time - now
wait_minutes = int(time_diff.total_seconds() / 60)
wait_str = format_wait_time(wait_minutes)
else:
wait_str = "You should be called soon"
status_info = f"""
Patient: {result[1]}
Token: {result[2]}
Queue #: {result[3]}
Status: {result[4]}
Doctor: {result[6]} ({result[7]})
"""
if result[4] == 'Waiting':
status_info += f"Estimated wait: {wait_str}"
# Get any notifications
cursor.execute("""
SELECT message FROM notifications
WHERE patient_id=?
ORDER BY sent_time DESC LIMIT 1
""", (result[0],))
notification = cursor.fetchone()
if notification:
status_info += f"\n\nNotification: {notification[0]}"
return status_info
except Exception as e:
return f"Error checking status: {str(e)}"
def get_doctor_queue(doctor_name):
"""Get current queue for a specific doctor"""
try:
cursor.execute("SELECT id FROM doctors WHERE name=?", (doctor_name,))
doctor_id = cursor.fetchone()[0]
cursor.execute("""
SELECT
id, name, queue_number, priority,
strftime('%H:%M', registration_time) as reg_time,
status, phone, token
FROM patients
WHERE doctor_id=? AND status IN ('Waiting', 'In Consultation')
ORDER BY
CASE status
WHEN 'In Consultation' THEN 0
ELSE 1
END,
priority, queue_number
""", (doctor_id,))
rows = cursor.fetchall()
# Convert to list of lists for gradio dataframe
result = []
for row in rows:
# Format priority as text
priority_text = {1: "Emergency", 2: "Urgent", 3: "Normal"}.get(row[3], "Normal")
result.append([row[0], row[1], row[2], priority_text, row[4], row[5], row[6], row[7]])
return result
except Exception as e:
print(f"Error getting doctor queue: {e}")
return []
def get_doctor_availability():
"""Get the list of available doctors with their specialties"""
cursor.execute("""
SELECT id, name, specialty, available
FROM doctors
ORDER BY name
""")
doctors = cursor.fetchall()
# Format for display
result = []
for doc in doctors:
status = "Available" if doc[3] else "Unavailable"
result.append([doc[0], doc[1], doc[2], status])
return result
def toggle_doctor_availability(doctor_id):
"""Toggle a doctor's availability status"""
try:
if not doctor_id:
return "Please select a doctor."
cursor.execute("SELECT available FROM doctors WHERE id=?", (doctor_id,))
current_status = cursor.fetchone()[0]
# Toggle status
new_status = 0 if current_status else 1
cursor.execute("UPDATE doctors SET available=? WHERE id=?", (new_status, doctor_id))
conn.commit()
status_text = "available" if new_status else "unavailable"
return f"Doctor status updated to {status_text}"
except Exception as e:
conn.rollback()
return f"Error updating status: {str(e)}"
def call_next(doctor_name):
"""Call the next patient in queue with notifications"""
try:
cursor.execute("SELECT id FROM doctors WHERE name=?", (doctor_name,))
doctor_id = cursor.fetchone()[0]
# First check if any patient is currently in consultation
cursor.execute("""
SELECT id, name
FROM patients
WHERE doctor_id=? AND status='In Consultation'
LIMIT 1
""", (doctor_id,))
current_patient = cursor.fetchone()
if current_patient:
return f"{current_patient[1]} is currently in consultation. Please complete their visit before calling the next patient."
# Find next patient based on priority and queue number
cursor.execute("""
SELECT id, name, token, queue_number, phone
FROM patients
WHERE doctor_id=? AND status='Waiting'
ORDER BY priority, queue_number ASC
LIMIT 1
""", (doctor_id,))
patient = cursor.fetchone()
if not patient:
return "No patients waiting."
# Update patient status
cursor.execute("UPDATE patients SET status='In Consultation' WHERE id=?", (patient[0],))
# Create notification
notification_msg = f"It's your turn! Please proceed to {doctor_name}'s room immediately."
cursor.execute("INSERT INTO notifications (patient_id, message) VALUES (?, ?)",
(patient[0], notification_msg))
conn.commit()
# Update wait times for all remaining patients
update_all_wait_times()
# Return formatted message
return f"Now calling: {patient[1]} (Token: {patient[2]}, Queue #: {patient[3]})"
except Exception as e:
conn.rollback()
return f"Error calling next patient: {str(e)}"
def complete_patient(patient_id, notes=""):
"""Mark patient consultation as completed with optional notes"""
try:
if not patient_id:
return "Please select a patient to mark as completed."
# Update patient status and add completion time
cursor.execute(
"UPDATE patients SET status='Completed', completed_time=?, notes=? WHERE id=?",
(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), notes, patient_id)
)
# Get patient info for confirmation
cursor.execute("SELECT name, token FROM patients WHERE id=?", (patient_id,))
patient = cursor.fetchone()
conn.commit()
# Update wait times for all remaining patients
update_all_wait_times()
return f"Patient {patient[0]} (Token: {patient[1]}) marked as completed."
except Exception as e:
conn.rollback()
return f"Error completing patient visit: {str(e)}"
def schedule_appointment(name, phone, email, doctor_name, date, time, reason):
"""Schedule a future appointment"""
try:
# Validate inputs
if not name or not phone or not doctor_name or not date or not time:
return "Error: Name, phone, doctor, date and time are required fields."
# Get doctor ID
cursor.execute("SELECT id FROM doctors WHERE name=?", (doctor_name,))
doctor_result = cursor.fetchone()
if not doctor_result:
return f"Error: Doctor {doctor_name} not found."
doctor_id = doctor_result[0]
# Check if time slot is available
cursor.execute("""
SELECT COUNT(*) FROM appointments
WHERE doctor_id=? AND appointment_date=? AND appointment_time=? AND status='Scheduled'
""", (doctor_id, date, time))
if cursor.fetchone()[0] > 0:
return f"Sorry, {doctor_name} is already booked at {time} on {date}. Please select another time."
# Insert appointment
cursor.execute("""
INSERT INTO appointments
(patient_name, phone, email, doctor_id, appointment_date, appointment_time, reason, status)
VALUES (?, ?, ?, ?, ?, ?, ?, 'Scheduled')
""", (name, phone, email, doctor_id, date, time, reason))
conn.commit()
return f"Appointment scheduled successfully for {name} with {doctor_name} on {date} at {time}."
except Exception as e:
conn.rollback()
return f"Error scheduling appointment: {str(e)}"
def get_appointments(date=None, doctor_name=None):
"""Get list of appointments by date and/or doctor"""
try:
query = """
SELECT
a.id, a.patient_name, a.phone, a.appointment_time,
d.name as doctor_name, a.reason, a.status
FROM appointments a
JOIN doctors d ON a.doctor_id = d.id
WHERE 1=1
"""
params = []
if date:
query += " AND a.appointment_date = ?"
params.append(date)
if doctor_name and doctor_name != "All Doctors":
query += " AND d.name = ?"
params.append(doctor_name)
query += " ORDER BY a.appointment_time"
cursor.execute(query, params)
appointments = cursor.fetchall()
# Format for display
result = []
for appt in appointments:
result.append([appt[0], appt[1], appt[2], appt[3], appt[4], appt[5], appt[6]])
return result
except Exception as e:
print(f"Error getting appointments: {e}")
return []
def get_daily_stats():
"""Get daily statistics for the dashboard"""
try:
today = datetime.now().strftime('%Y-%m-%d')
# Total patients today
cursor.execute("""
SELECT COUNT(*) FROM patients
WHERE date(registration_time) = ?
""", (today,))
total_patients = cursor.fetchone()[0]
# Waiting patients
cursor.execute("SELECT COUNT(*) FROM patients WHERE status='Waiting'")
waiting_patients = cursor.fetchone()[0]
# In consultation
cursor.execute("SELECT COUNT(*) FROM patients WHERE status='In Consultation'")
in_consultation = cursor.fetchone()[0]
# Completed today
cursor.execute("""
SELECT COUNT(*) FROM patients
WHERE status='Completed' AND date(completed_time) = ?
""", (today,))
completed_today = cursor.fetchone()[0]
# Average wait time today
cursor.execute("""
SELECT AVG(
(julianday(completed_time) - julianday(registration_time)) * 24 * 60
) FROM patients
WHERE status='Completed' AND date(completed_time) = ?
""", (today,))
avg_wait_time = cursor.fetchone()[0]
avg_wait_formatted = f"{int(avg_wait_time)} minutes" if avg_wait_time else "N/A"
return {
"total_patients": total_patients,
"waiting": waiting_patients,
"in_consultation": in_consultation,
"completed": completed_today,
"avg_wait_time": avg_wait_formatted
}
except Exception as e:
print(f"Error getting stats: {e}")
return {
"total_patients": 0,
"waiting": 0,
"in_consultation": 0,
"completed": 0,
"avg_wait_time": "N/A"
}
# ---------------------------
# GRADIO INTERFACE
# ---------------------------
def get_doctor_names():
"""Get list of available doctor names"""
cursor.execute("SELECT name FROM doctors WHERE available=1 ORDER BY name")
doctors = [row[0] for row in cursor.fetchall()]
return doctors
def get_all_doctor_names():
"""Get list of all doctor names regardless of availability"""
cursor.execute("SELECT name FROM doctors ORDER BY name")
doctors = [row[0] for row in cursor.fetchall()]
return doctors
# Create the Gradio interface with theme and improved UI
theme = gr.themes.Soft(
primary_hue="blue",
secondary_hue="indigo",
)
with gr.Blocks(theme=theme, title="Hospital Queue Management System") as demo:
gr.Markdown("# π₯ Hospital Queue Management System")
# Dashboard Tab
with gr.Tab("π Dashboard"):
gr.Markdown("### Today's Statistics")
with gr.Row():
total_count = gr.Textbox(label="Total Patients Today")
waiting_count = gr.Textbox(label="Currently Waiting")
consulting_count = gr.Textbox(label="In Consultation")
completed_count = gr.Textbox(label="Completed Today")
avg_wait = gr.Textbox(label="Average Wait Time")
refresh_stats_btn = gr.Button("Refresh Statistics")
def update_dashboard():
stats = get_daily_stats()
return [
stats["total_patients"],
stats["waiting"],
stats["in_consultation"],
stats["completed"],
stats["avg_wait_time"]
]
refresh_stats_btn.click(
fn=update_dashboard,
inputs=[],
outputs=[total_count, waiting_count, consulting_count, completed_count, avg_wait]
)
# Initialize dashboard
demo.load(
fn=update_dashboard,
inputs=[],
outputs=[total_count, waiting_count, consulting_count, completed_count, avg_wait]
)
# Patient Registration Tab
with gr.Tab("β Register Patient"):
gr.Markdown("### New Patient Registration")
with gr.Row():
name = gr.Textbox(label="Patient Name*", placeholder="Enter full name")
phone = gr.Textbox(label="Phone Number*", placeholder="Enter phone number")
with gr.Row():
email = gr.Textbox(label="Email (Optional)", placeholder="Enter email address")
priority = gr.Dropdown(
choices=[
{"label": "Normal", "value": 3},
{"label": "Urgent", "value": 2},
{"label": "Emergency", "value": 1}
],
label="Priority",
value=3
)
symptoms = gr.Textbox(
label="Symptoms/Reason for Visit",
placeholder="Briefly describe the symptoms or reason for visit",
lines=3
)
# Fixed dropdown: Use the actual list rather than the function
doctor = gr.Dropdown(
choices=get_doctor_names(), # Call the function to get its return value
label="Select Doctor*",
info="Only shows available doctors"
)
register_btn = gr.Button("Register Patient", variant="primary")
register_output = gr.Textbox(label="Registration Details", lines=6)
register_btn.click(
fn=register_patient,
inputs=[name, phone, email, symptoms, priority, doctor],
outputs=register_output
)
# Status Check Tab
with gr.Tab("π Check My Status"):
gr.Markdown("### Patient Status Lookup")
phone_lookup = gr.Textbox(
label="Enter Your Phone Number or Token",
placeholder="Enter phone number or 6-digit token",
info="You can use either your phone number or token to check your status"
)
check_btn = gr.Button("Check Status", variant="primary")
status_output = gr.Textbox(label="Your Status", lines=8)
check_btn.click(fn=check_status, inputs=phone_lookup, outputs=status_output)
# Doctor Panel Tab
with gr.Tab("π©Ί Doctor Panel"):
gr.Markdown("### Manage Patient Queue")
with gr.Row():
# Fixed dropdown: Use the actual list rather than the function
doc_select = gr.Dropdown(
choices=get_all_doctor_names(), # Call the function to get its return value
label="Select Doctor",
info="Select doctor to view their queue"
)
with gr.Column():
call_btn = gr.Button("Call Next Patient", variant="primary")
call_output = gr.Textbox(label="Now Calling", lines=2)
queue_table = gr.Dataframe(
headers=["ID", "Name", "Queue #", "Priority", "Reg. Time", "Status", "Phone", "Token"],
datatype=["number", "str", "number", "str", "str", "str", "str", "str"],
interactive=False,
label="Current Queue"
)
with gr.Row():
selected_patient_id = gr.Number(label="Patient ID", precision=0)
patient_notes = gr.Textbox(label="Consultation Notes", lines=2)
complete_btn = gr.Button("Complete Visit")
complete_output = gr.Textbox(label="Result")
refresh_btn = gr.Button("Refresh Queue")
# Set up event handlers
call_btn.click(fn=call_next, inputs=doc_select, outputs=call_output)
complete_btn.click(
fn=complete_patient,
inputs=[selected_patient_id, patient_notes],
outputs=complete_output
)
refresh_btn.click(
fn=lambda d: get_doctor_queue(d),
inputs=doc_select,
outputs=queue_table
)
# Update queue when doctor selection changes
doc_select.change(
fn=lambda d: get_doctor_queue(d),
inputs=doc_select,
outputs=queue_table
)
# Appointment Scheduling Tab
with gr.Tab("π
Schedule Appointment"):
gr.Markdown("### Schedule a Future Appointment")
with gr.Row():
appt_name = gr.Textbox(label="Patient Name*", placeholder="Enter full name")
appt_phone = gr.Textbox(label="Phone Number*", placeholder="Enter phone number")
with gr.Row():
appt_email = gr.Textbox(label="Email (Optional)", placeholder="Enter email address")
# Fixed dropdown: Use the actual list rather than the function
appt_doctor = gr.Dropdown(
choices=get_all_doctor_names(), # Call the function to get its return value
label="Select Doctor*"
)
with gr.Row():
appt_date = gr.Textbox(
label="Appointment Date*",
placeholder="YYYY-MM-DD",
info="Enter date in YYYY-MM-DD format"
)
appt_time = gr.Dropdown(
choices=[
"09:00 AM", "09:30 AM", "10:00 AM", "10:30 AM", "11:00 AM", "11:30 AM",
"01:00 PM", "01:30 PM", "02:00 PM", "02:30 PM", "03:00 PM", "03:30 PM",
"04:00 PM", "04:30 PM"
],
label="Appointment Time*"
)
appt_reason = gr.Textbox(
label="Reason for Appointment",
placeholder="Briefly describe the reason for appointment",
lines=3
)
schedule_btn = gr.Button("Schedule Appointment", variant="primary")
schedule_output = gr.Textbox(label="Appointment Details")
schedule_btn.click(
fn=schedule_appointment,
inputs=[appt_name, appt_phone, appt_email, appt_doctor, appt_date, appt_time, appt_reason],
outputs=schedule_output
)
# Appointment List
gr.Markdown("### View Appointments")
with gr.Row():
view_date = gr.Textbox(
label="Date (YYYY-MM-DD)",
placeholder="Leave empty for all dates",
value=datetime.now().strftime('%Y-%m-%d')
)
view_doctor = gr.Dropdown(
choices=["All Doctors"] + get_all_doctor_names(),
label="Doctor",
value="All Doctors"
)
view_btn = gr.Button("View Appointments")
appointments_table = gr.Dataframe(
headers=["ID", "Patient Name", "Phone", "Time", "Doctor", "Reason", "Status"],
interactive=False,
label="Appointments"
)
view_btn.click(
fn=get_appointments,
inputs=[view_date, view_doctor],
outputs=appointments_table
)
# Admin Panel Tab
with gr.Tab("βοΈ Admin Panel"):
gr.Markdown("### Doctor Availability Management")
doctors_table = gr.Dataframe(
headers=["ID", "Name", "Specialty", "Status"],
interactive=False,
label="Doctors"
)
with gr.Row():
doctor_id = gr.Number(label="Doctor ID", precision=0)
toggle_btn = gr.Button("Toggle Availability")
toggle_output = gr.Textbox(label="Result")
refresh_doctors_btn = gr.Button("Refresh Doctor List")
# Set up event handlers
toggle_btn.click(
fn=toggle_doctor_availability,
inputs=doctor_id,
outputs=toggle_output
)
refresh_doctors_btn.click(
fn=get_doctor_availability,
inputs=[],
outputs=doctors_table
)
# Initialize doctors table
demo.load(
fn=get_doctor_availability,
inputs=[],
outputs=doctors_table
)
# System Maintenance Section
gr.Markdown("### System Maintenance")
with gr.Row():
backup_btn = gr.Button("Backup Database")
backup_output = gr.Textbox(label="Backup Status")
def backup_database():
"""Create a backup of the database"""
try:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_file = f"hospital_backup_{timestamp}.db"
# Create connection to new file
backup_conn = sqlite3.connect(backup_file)
# Copy data
conn.backup(backup_conn)
backup_conn.close()
return f"Backup created successfully: {backup_file}"
except Exception as e:
return f"Backup failed: {str(e)}"
backup_btn.click(fn=backup_database, inputs=[], outputs=backup_output)
# Launch the app
if __name__ == "__main__":
demo.launch(share=False) |