Meshari21 commited on
Commit
4ad3476
·
verified ·
1 Parent(s): 254234b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +185 -51
app.py CHANGED
@@ -240,6 +240,7 @@ def get_user_info(username):
240
  else:
241
  return "User info not found."
242
 
 
243
  def get_chat_history(username):
244
  conn = sqlite3.connect("users.db")
245
  c = conn.cursor()
@@ -285,10 +286,12 @@ def generate_pdf_report(session_data):
285
  pdf = FPDF()
286
  pdf.add_page()
287
  pdf.set_font("Arial", size=12)
288
- pdf.cell(200, 10, txt="Patient Session Report", ln=True, align='C')
 
289
  pdf.ln(10)
290
  for key, value in session_data.items():
291
- pdf.multi_cell(0, 10, txt=f"{key.capitalize()}: {value}")
 
292
  reports_dir = "reports"
293
  os.makedirs(reports_dir, exist_ok=True)
294
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
@@ -296,13 +299,33 @@ def generate_pdf_report(session_data):
296
  pdf.output(filename)
297
  return filename
298
 
 
 
 
 
 
299
  # --------------------------
300
  # Helper: Autofill Previous Patient Info
301
  # --------------------------
 
 
 
 
 
 
 
 
 
 
302
  def get_previous_patient_info(selected_patient):
 
 
303
  conn = sqlite3.connect("users.db")
304
  c = conn.cursor()
305
- c.execute("SELECT patient_name, age, gender FROM patient_sessions WHERE patient_name=? ORDER BY session_timestamp DESC LIMIT 1", (selected_patient,))
 
 
 
306
  record = c.fetchone()
307
  conn.close()
308
  if record:
@@ -310,14 +333,6 @@ def get_previous_patient_info(selected_patient):
310
  else:
311
  return "", None, ""
312
 
313
- def get_previous_patients():
314
- conn = sqlite3.connect("users.db")
315
- c = conn.cursor()
316
- c.execute("SELECT DISTINCT patient_name FROM patient_sessions")
317
- records = c.fetchall()
318
- conn.close()
319
- return [r[0] for r in records]
320
-
321
  # --------------------------
322
  # Gradio UI Setup with External CSS
323
  # --------------------------
@@ -489,15 +504,24 @@ with gr.Blocks(css=open("styles.css", "r").read(), theme="soft") as app:
489
 
490
  def handle_generate_report():
491
  try:
 
492
  data = json.loads(session_data_state.value)
493
- except:
494
- return None
495
- pdf_file = generate_pdf_report(data)
496
- data["username"] = user_session.value
497
- data["appointment_date"] = ""
498
- data["pdf_report"] = pdf_file
499
- insert_patient_session(data)
500
- return pdf_file
 
 
 
 
 
 
 
 
501
 
502
  generate_report_btn.click(handle_generate_report, outputs=report_download)
503
 
@@ -516,10 +540,12 @@ with gr.Blocks(css=open("styles.css", "r").read(), theme="soft") as app:
516
  def load_history():
517
  if user_session.value:
518
  history = get_chat_history(user_session.value)
519
- return "\n".join([f"[{h[2]}] {h[0]}\nBot: {h[1]}" for h in history])
 
520
  else:
521
  return "Please log in to view history."
522
 
 
523
  load_history_btn.click(load_history, outputs=history_output)
524
 
525
  with gr.Tab("Book an Appointment"):
@@ -547,17 +573,26 @@ with gr.Blocks(css=open("styles.css", "r").read(), theme="soft") as app:
547
  if not re.fullmatch(r"[A-Za-z ]+", patient_name):
548
  return "Patient name should contain only letters and spaces."
549
  try:
550
- datetime.strptime(appointment_date, "%Y-%m-%d")
 
551
  except ValueError:
552
  return "Appointment date must be in YYYY-MM-DD format."
553
  try:
554
- datetime.strptime(appointment_time, "%H:%M")
555
  except ValueError:
556
  return "Appointment time must be in HH:MM (24-hour) format."
 
 
 
 
 
 
 
557
  confirmation = (f"Appointment booked for {patient_name} with {doctor_name} on {appointment_date} at {appointment_time}.\n\n"
558
  f"Reason: {reason}")
559
  return confirmation
560
 
 
561
  book_button.click(book_appointment,
562
  inputs=[patient_name_appt, doctor_name, appointment_date, appointment_time, reason],
563
  outputs=booking_output)
@@ -579,17 +614,7 @@ with gr.Blocks(css=open("styles.css", "r").read(), theme="soft") as app:
579
 
580
  search_button.click(search_sessions, inputs=[search_name, search_date], outputs=sessions_output)
581
 
582
- def handle_login(username, password):
583
- if login_user(username, password):
584
- user_session.value = username
585
- prev_choices = get_previous_patients()
586
- return (f"Welcome, {username}!",
587
- gr.update(visible=True),
588
- gr.update(visible=False),
589
- gr.update(visible=True),
590
- gr.update(choices=prev_choices))
591
- else:
592
- return "Invalid credentials.", gr.update(), gr.update(), gr.update(), gr.update()
593
 
594
  def handle_register(username, password, full_name, email):
595
  return register_user(username, password, full_name, email)
@@ -600,9 +625,7 @@ with gr.Blocks(css=open("styles.css", "r").read(), theme="soft") as app:
600
  def back_to_login_page():
601
  return gr.update(visible=True), gr.update(visible=False)
602
 
603
- login_btn.click(handle_login,
604
- inputs=[username_login, password_login],
605
- outputs=[login_output, main_panel, login_page, header_row])
606
  go_to_register.click(go_to_register_page, outputs=[login_page, register_page])
607
  register_btn.click(handle_register,
608
  inputs=[new_username, new_password, full_name, email],
@@ -610,19 +633,26 @@ with gr.Blocks(css=open("styles.css", "r").read(), theme="soft") as app:
610
  back_to_login.click(back_to_login_page, outputs=[login_page, register_page])
611
 
612
 
613
- # Toggle profile function
614
- def toggle_profile(user, current_visible):
615
- if not user:
 
 
 
616
  return gr.update(visible=False), False, ""
617
  new_visible = not current_visible
618
- info = get_user_info(user) if new_visible else ""
619
  return gr.update(visible=new_visible), new_visible, info
 
 
 
 
620
 
621
 
622
  # Connect profile button click with correct input order:
623
  profile_button.click(
624
  toggle_profile,
625
- inputs=[user_session, profile_visible],
626
  outputs=[profile_info_box, profile_visible, profile_info]
627
  )
628
 
@@ -632,20 +662,124 @@ with gr.Blocks(css=open("styles.css", "r").read(), theme="soft") as app:
632
  if login_user(username, password):
633
  user_session.value = username
634
  prev_choices = get_previous_patients()
635
- return (f"Welcome, {username}!",
636
- gr.update(visible=True), # main_panel visible
637
- gr.update(visible=False), # login_page hidden
638
- gr.update(visible=True), # header_row visible
639
- gr.update(choices=prev_choices)) # update dropdown choices
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
640
  else:
641
- return "Invalid credentials.", gr.update(), gr.update(), gr.update(), gr.update()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
642
 
643
 
644
- # Connect login button click:
645
  login_btn.click(
646
- handle_login,
647
- inputs=[username_login, password_login],
648
- outputs=[login_output, main_panel, login_page, header_row, previous_patient]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
649
  )
650
 
651
  def main():
 
240
  else:
241
  return "User info not found."
242
 
243
+
244
  def get_chat_history(username):
245
  conn = sqlite3.connect("users.db")
246
  c = conn.cursor()
 
286
  pdf = FPDF()
287
  pdf.add_page()
288
  pdf.set_font("Arial", size=12)
289
+ # Use safe_text to ensure the title is safe for latin-1 encoding
290
+ pdf.cell(200, 10, txt=safe_text("Patient Session Report"), ln=True, align='C')
291
  pdf.ln(10)
292
  for key, value in session_data.items():
293
+ # Convert each line to a safe text version before writing it
294
+ pdf.multi_cell(0, 10, txt=safe_text(f"{key.capitalize()}: {value}"))
295
  reports_dir = "reports"
296
  os.makedirs(reports_dir, exist_ok=True)
297
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
 
299
  pdf.output(filename)
300
  return filename
301
 
302
+
303
+ def safe_text(txt):
304
+ # Encode the text to latin-1, replacing characters that can't be encoded
305
+ return txt.encode("latin-1", "replace").decode("latin-1")
306
+
307
  # --------------------------
308
  # Helper: Autofill Previous Patient Info
309
  # --------------------------
310
+ def get_previous_patients():
311
+ # Use the current logged-in user from user_session.value
312
+ username = user_session.value
313
+ conn = sqlite3.connect("users.db")
314
+ c = conn.cursor()
315
+ c.execute("SELECT DISTINCT patient_name FROM patient_sessions WHERE username=?", (username,))
316
+ records = c.fetchall()
317
+ conn.close()
318
+ return [r[0] for r in records]
319
+
320
  def get_previous_patient_info(selected_patient):
321
+ # Use the current logged-in user from user_session.value
322
+ username = user_session.value
323
  conn = sqlite3.connect("users.db")
324
  c = conn.cursor()
325
+ c.execute(
326
+ "SELECT patient_name, age, gender FROM patient_sessions WHERE username=? AND patient_name=? ORDER BY session_timestamp DESC LIMIT 1",
327
+ (username, selected_patient)
328
+ )
329
  record = c.fetchone()
330
  conn.close()
331
  if record:
 
333
  else:
334
  return "", None, ""
335
 
 
 
 
 
 
 
 
 
336
  # --------------------------
337
  # Gradio UI Setup with External CSS
338
  # --------------------------
 
504
 
505
  def handle_generate_report():
506
  try:
507
+ # Try to load session data and generate the PDF report.
508
  data = json.loads(session_data_state.value)
509
+ pdf_file = generate_pdf_report(data)
510
+ data["username"] = user_session.value
511
+ data["appointment_date"] = ""
512
+ data["pdf_report"] = pdf_file
513
+ insert_patient_session(data)
514
+ return pdf_file
515
+ except Exception as e:
516
+ # Create an error file that contains the error message.
517
+ error_msg = f"Error generating PDF report: {str(e)}"
518
+ reports_dir = "reports"
519
+ os.makedirs(reports_dir, exist_ok=True)
520
+ error_filename = f"{reports_dir}/error_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
521
+ with open(error_filename, "w", encoding="utf-8") as f:
522
+ f.write(error_msg)
523
+ return error_filename
524
+
525
 
526
  generate_report_btn.click(handle_generate_report, outputs=report_download)
527
 
 
540
  def load_history():
541
  if user_session.value:
542
  history = get_chat_history(user_session.value)
543
+ chat_history_text = "\n".join([f"[{h[2]}] {h[0]}\nBot: {h[1]}" for h in history])
544
+ return f"Username: {user_session.value}\n\n{chat_history_text}"
545
  else:
546
  return "Please log in to view history."
547
 
548
+
549
  load_history_btn.click(load_history, outputs=history_output)
550
 
551
  with gr.Tab("Book an Appointment"):
 
573
  if not re.fullmatch(r"[A-Za-z ]+", patient_name):
574
  return "Patient name should contain only letters and spaces."
575
  try:
576
+ # Parse the appointment date and time strings
577
+ appointment_date_obj = datetime.strptime(appointment_date, "%Y-%m-%d")
578
  except ValueError:
579
  return "Appointment date must be in YYYY-MM-DD format."
580
  try:
581
+ appointment_time_obj = datetime.strptime(appointment_time, "%H:%M")
582
  except ValueError:
583
  return "Appointment time must be in HH:MM (24-hour) format."
584
+
585
+ # Combine date and time into a single datetime object
586
+ appointment_datetime = datetime.combine(appointment_date_obj.date(), appointment_time_obj.time())
587
+ now = datetime.now()
588
+ if appointment_datetime <= now:
589
+ return "Appointment date/time has already passed. Please select a future date and time."
590
+
591
  confirmation = (f"Appointment booked for {patient_name} with {doctor_name} on {appointment_date} at {appointment_time}.\n\n"
592
  f"Reason: {reason}")
593
  return confirmation
594
 
595
+
596
  book_button.click(book_appointment,
597
  inputs=[patient_name_appt, doctor_name, appointment_date, appointment_time, reason],
598
  outputs=booking_output)
 
614
 
615
  search_button.click(search_sessions, inputs=[search_name, search_date], outputs=sessions_output)
616
 
617
+
 
 
 
 
 
 
 
 
 
 
618
 
619
  def handle_register(username, password, full_name, email):
620
  return register_user(username, password, full_name, email)
 
625
  def back_to_login_page():
626
  return gr.update(visible=True), gr.update(visible=False)
627
 
628
+
 
 
629
  go_to_register.click(go_to_register_page, outputs=[login_page, register_page])
630
  register_btn.click(handle_register,
631
  inputs=[new_username, new_password, full_name, email],
 
633
  back_to_login.click(back_to_login_page, outputs=[login_page, register_page])
634
 
635
 
636
+
637
+
638
+
639
+ def toggle_profile(current_visible):
640
+ #print("toggle_profile called with user:", user_session.value) # Debug print
641
+ if not user_session.value:
642
  return gr.update(visible=False), False, ""
643
  new_visible = not current_visible
644
+ info = get_user_info(user_session.value) if new_visible else ""
645
  return gr.update(visible=new_visible), new_visible, info
646
+
647
+
648
+
649
+
650
 
651
 
652
  # Connect profile button click with correct input order:
653
  profile_button.click(
654
  toggle_profile,
655
+ inputs=[profile_visible],
656
  outputs=[profile_info_box, profile_visible, profile_info]
657
  )
658
 
 
662
  if login_user(username, password):
663
  user_session.value = username
664
  prev_choices = get_previous_patients()
665
+ # Return 27 outputs now: existing 20 plus 7 more for sessions and booking tabs.
666
+ return (
667
+ f"Welcome, {username}!", # login_output
668
+ gr.update(visible=True), # main_panel
669
+ gr.update(visible=False), # login_page
670
+ gr.update(visible=True), # header_row
671
+ gr.update(choices=prev_choices), # previous_patient
672
+ "", # patient_name_input
673
+ None, # age_input
674
+ None, # gender_input
675
+ "", # symptoms_input
676
+ "", # diagnosis_textbox
677
+ "", # diagnosis_conf_html
678
+ "", # medication_textbox
679
+ "", # medication_conf_html
680
+ "", # therapy_textbox
681
+ "", # therapy_conf_html
682
+ "", # summary_textbox
683
+ "", # explanation_textbox
684
+ gr.update(visible=False), # generate_report_btn
685
+ None, # report_download
686
+ "", # session_data_state
687
+ "", # search_name (Patient Sessions tab)
688
+ "", # search_date (Patient Sessions tab)
689
+ "", # booking_output (Book an Appointment tab)
690
+ "", # patient_name_appt (Booking tab field)
691
+ "", # appointment_date (Booking tab field)
692
+ "", # appointment_time (Booking tab field)
693
+ "" # reason (Booking tab field)
694
+ )
695
  else:
696
+ # On failure, clear those fields as well.
697
+ return (
698
+ "Invalid credentials.", # login_output
699
+ gr.update(), # main_panel
700
+ gr.update(), # login_page
701
+ gr.update(), # header_row
702
+ gr.update(choices=[], value=""), # previous_patient (cleared)
703
+ "", # patient_name_input
704
+ None, # age_input
705
+ None, # gender_input
706
+ "", # symptoms_input
707
+ "", # diagnosis_textbox
708
+ "", # diagnosis_conf_html
709
+ "", # medication_textbox
710
+ "", # medication_conf_html
711
+ "", # therapy_textbox
712
+ "", # therapy_conf_html
713
+ "", # summary_textbox
714
+ "", # explanation_textbox
715
+ gr.update(visible=False), # generate_report_btn
716
+ None, # report_download
717
+ "", # session_data_state
718
+ "", # search_name
719
+ "", # search_date
720
+ "", # booking_output
721
+ "", # patient_name_appt
722
+ "", # appointment_date
723
+ "", # appointment_time
724
+ "" # reason
725
+ )
726
+
727
+
728
+
729
 
730
 
 
731
  login_btn.click(
732
+ handle_login,
733
+ inputs=[username_login, password_login],
734
+ outputs=[
735
+ login_output, main_panel, login_page, header_row, previous_patient,
736
+ patient_name_input, age_input, gender_input, symptoms_input,
737
+ diagnosis_textbox, diagnosis_conf_html,
738
+ medication_textbox, medication_conf_html,
739
+ therapy_textbox, therapy_conf_html,
740
+ summary_textbox, explanation_textbox,
741
+ generate_report_btn, report_download, session_data_state,
742
+ search_name, search_date, booking_output, patient_name_appt, appointment_date, appointment_time, reason
743
+ ]
744
+ )
745
+
746
+ def handle_logout():
747
+ user_session.value = ""
748
+ return (
749
+ gr.update(visible=False), # Hide main_panel
750
+ gr.update(visible=True), # Show login_page
751
+ gr.update(visible=False), # Hide header_row
752
+ gr.update(visible=False), # Hide profile_info_box
753
+ False, # Reset profile_visible
754
+ "", # Clear profile_info
755
+ "", # Clear login_output
756
+ "", # Clear history_output
757
+ "", # Clear username_login textbox
758
+ "", # Clear password_login textbox
759
+ "", # Clear new_username textbox (register page)
760
+ "", # Clear new_password textbox (register page)
761
+ "", # Clear full_name textbox (register page)
762
+ "" # Clear email textbox (register page)
763
+ )
764
+
765
+ logout_button.click(
766
+ handle_logout,
767
+ outputs=[
768
+ main_panel,
769
+ login_page,
770
+ header_row,
771
+ profile_info_box,
772
+ profile_visible,
773
+ profile_info,
774
+ login_output,
775
+ history_output,
776
+ username_login,
777
+ password_login,
778
+ new_username,
779
+ new_password,
780
+ full_name,
781
+ email
782
+ ]
783
  )
784
 
785
  def main():