Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -652,7 +652,7 @@ def doctor_dashboard():
|
|
| 652 |
logger.info("Accessed doctor dashboard, setting role to doctor.")
|
| 653 |
return render_template('doctor_dashboard.html')
|
| 654 |
|
| 655 |
-
|
| 656 |
@app.route('/submit_feedback', methods=['POST'])
|
| 657 |
def submit_feedback():
|
| 658 |
ai_enabled = bool(model) # Check if model is initialized
|
|
@@ -681,7 +681,6 @@ def submit_feedback():
|
|
| 681 |
age = None # Store as None if not provided
|
| 682 |
|
| 683 |
care_plan_text = "" # This will store the extracted text from PDF
|
| 684 |
-
care_plan_format = None # This will store the detected format
|
| 685 |
|
| 686 |
if 'care_plan_pdf' in request.files:
|
| 687 |
pdf_file = request.files['care_plan_pdf']
|
|
@@ -694,25 +693,35 @@ def submit_feedback():
|
|
| 694 |
logger.info(f"Processing uploaded PDF: {pdf_file.filename}")
|
| 695 |
care_plan_text = extract_text_from_pdf(pdf_file)
|
| 696 |
|
| 697 |
-
# If extraction resulted in an error message,
|
| 698 |
-
|
| 699 |
-
|
| 700 |
-
logger.warning(f"PDF text extraction failed or empty: {care_plan_text}")
|
| 701 |
-
else:
|
| 702 |
-
care_plan_format = extract_care_plan_format(care_plan_text)
|
| 703 |
-
logger.info(f"Extracted text length: {len(care_plan_text)}. Format found: {care_plan_format is not None}")
|
| 704 |
else:
|
| 705 |
logger.info("No PDF file uploaded or file is empty.")
|
| 706 |
|
| 707 |
-
# Determine the initial status based on feedback and original plan
|
| 708 |
# Pass "" for updated_plan initially, as it hasn't been generated yet for status check
|
| 709 |
initial_status = determine_patient_status(care_plan_text, "", feedback)
|
| 710 |
logger.info(f"Initial status determined based on feedback/original plan: {initial_status}")
|
| 711 |
|
| 712 |
-
|
| 713 |
generated_plan_text = "" # This will store the AI-generated or fallback plan
|
| 714 |
final_status_to_save = initial_status # Start with initial status
|
| 715 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 716 |
# Only generate AI plan if AI is enabled AND status isn't immediate emergency based on feedback
|
| 717 |
# If feedback triggers "emergency", the generated_plan_text is a fixed emergency plan.
|
| 718 |
if final_status_to_save == 'emergency':
|
|
@@ -725,82 +734,69 @@ def submit_feedback():
|
|
| 725 |
f"- Gender: {gender}\n\n"
|
| 726 |
"ASSESSMENT:\n"
|
| 727 |
f"- Emergency symptoms reported: {feedback}. Immediate medical attention required.\n\n"
|
| 728 |
-
"
|
| 729 |
-
"
|
| 730 |
-
"-
|
| 731 |
-
"
|
| 732 |
-
"-
|
| 733 |
-
"
|
| 734 |
-
"-
|
| 735 |
-
|
| 736 |
-
|
| 737 |
-
|
| 738 |
-
"
|
| 739 |
-
"
|
| 740 |
-
"-
|
| 741 |
-
"
|
|
|
|
| 742 |
)
|
| 743 |
-
# For emergency, the generated plan text *is* the final plan to save/send.
|
| 744 |
# Status remains 'emergency', which was already set as final_status_to_save.
|
| 745 |
|
| 746 |
|
| 747 |
elif ai_enabled: # AI is enabled and initial status is not emergency
|
| 748 |
-
|
| 749 |
-
if not care_plan_format or not care_plan_format.strip():
|
| 750 |
-
logger.info("Using default care plan format as extraction failed or returned empty.")
|
| 751 |
-
care_plan_format = """
|
| 752 |
-
PATIENT INFORMATION:
|
| 753 |
-
- Name: [Patient Name]
|
| 754 |
-
- Age: [Age]
|
| 755 |
-
- Gender: [Gender] (no other parameter other than these three should be there , not even contact number i want only three Name)
|
| 756 |
-
ASSESSMENT:
|
| 757 |
-
- [Summary of patient's current condition based on feedback and previous plan]
|
| 758 |
-
DAILY CARE PLAN:
|
| 759 |
-
Morning:
|
| 760 |
-
- [Morning activities/medications/checks]
|
| 761 |
-
Afternoon:
|
| 762 |
-
- [Afternoon activities/medications/checks]
|
| 763 |
-
Night:
|
| 764 |
-
- [Night activities/medications/sleep instructions/checks]
|
| 765 |
-
MEDICATIONS:
|
| 766 |
-
- [List of medications, dosage, frequency, and time, including PRN (as needed) instructions] {hey please give it by general sense dont response like i am not physician etc , give , if you dont know still appropriate medicates pelase give)}
|
| 767 |
-
- DIET AND HYDRATION
|
| 768 |
-
- Physical activity and exercise
|
| 769 |
-
SYMPTOM MANAGEMENT:
|
| 770 |
-
- [Short instructions for managing specific symptoms (e.g., pain, nausea, shortness of breath), non-pharmacological interventions]
|
| 771 |
-
""" # Enhanced default format
|
| 772 |
|
|
|
|
| 773 |
prompt = f"""
|
| 774 |
-
You are
|
| 775 |
-
|
| 776 |
-
Patient Information
|
|
|
|
|
|
|
| 777 |
Name: {name}
|
| 778 |
Age: {age if age is not None else 'N/A'}
|
| 779 |
Gender: {gender}
|
| 780 |
-
|
|
|
|
| 781 |
{feedback}
|
| 782 |
-
|
|
|
|
| 783 |
{care_plan_text if care_plan_text and "[No readable text found" not in care_plan_text and "[Error extracting PDF text" not in care_plan_text and "[PDF Content Unavailable" not in care_plan_text else "No previous care plan provided or could not be read."}
|
| 784 |
-
|
| 785 |
-
|
| 786 |
-
|
| 787 |
-
|
| 788 |
-
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
|
| 795 |
-
|
| 796 |
-
|
| 797 |
-
|
| 798 |
-
|
| 799 |
-
|
| 800 |
-
|
| 801 |
-
|
| 802 |
-
|
|
|
|
|
|
|
| 803 |
"""
|
|
|
|
|
|
|
|
|
|
| 804 |
logger.info("Sending prompt to AI model...")
|
| 805 |
|
| 806 |
try:
|
|
@@ -809,22 +805,18 @@ Hospital Contact: (Not provided) (it is useless abd vague okay and also in any s
|
|
| 809 |
generated_plan_text = response.text.strip()
|
| 810 |
|
| 811 |
# Remove markdown code block formatting if present
|
| 812 |
-
if generated_plan_text.startswith('```')
|
| 813 |
-
# Find the first newline after ``` to potentially strip language name
|
| 814 |
first_newline_after_code = generated_plan_text.find('\n')
|
| 815 |
if first_newline_after_code != -1:
|
| 816 |
-
|
| 817 |
-
|
| 818 |
-
|
| 819 |
-
|
| 820 |
-
|
| 821 |
-
|
| 822 |
-
generated_plan_text = generated_plan_text[3:].strip()
|
| 823 |
else:
|
| 824 |
-
|
| 825 |
-
generated_plan_text = generated_plan_text[3:].strip()
|
| 826 |
|
| 827 |
-
# Strip ending ```
|
| 828 |
if generated_plan_text.endswith('```'):
|
| 829 |
generated_plan_text = generated_plan_text[:-3].strip()
|
| 830 |
|
|
@@ -832,8 +824,6 @@ Hospital Contact: (Not provided) (it is useless abd vague okay and also in any s
|
|
| 832 |
logger.info(f"AI Response received. Length: {len(generated_plan_text)}")
|
| 833 |
|
| 834 |
# Re-determine the final status using the generated plan as well.
|
| 835 |
-
# This is important because the AI might infer severity the keyword matching missed initially,
|
| 836 |
-
# or the generated plan text itself might contain explicit strong status indicators.
|
| 837 |
final_status_to_save = determine_patient_status(care_plan_text, generated_plan_text, feedback)
|
| 838 |
logger.info(f"Final status determined after AI generation: {final_status_to_save}")
|
| 839 |
|
|
@@ -872,6 +862,7 @@ Hospital Contact: (Not provided) (it is useless abd vague okay and also in any s
|
|
| 872 |
|
| 873 |
|
| 874 |
# Create and store patient record in the database
|
|
|
|
| 875 |
new_patient = Patient(
|
| 876 |
name=name,
|
| 877 |
age=age,
|
|
@@ -889,15 +880,12 @@ Hospital Contact: (Not provided) (it is useless abd vague okay and also in any s
|
|
| 889 |
logger.info(f"Patient {patient_id} added to DB with status: {final_status_to_save}.")
|
| 890 |
|
| 891 |
# Generate PDF for downloading using the stored data
|
| 892 |
-
# Note: We pass the patient object directly to the PDF generator for simplicity
|
| 893 |
-
# and to include feedback in the PDF
|
| 894 |
pdf_buffer = generate_care_plan_pdf(new_patient.to_dict(), new_patient.updated_plan, new_patient.status)
|
| 895 |
pdf_buffer.seek(0) # Ensure buffer is at the start before base64 encoding
|
| 896 |
pdf_base64 = base64.b64encode(pdf_buffer.getvalue()).decode('utf-8')
|
| 897 |
logger.info("PDF generated and base64 encoded.")
|
| 898 |
|
| 899 |
# Send care plan via WhatsApp (using the final saved data)
|
| 900 |
-
# Note: We pass the patient object directly to the WhatsApp function
|
| 901 |
whatsapp_sent, whatsapp_message = send_whatsapp_care_plan(new_patient.to_dict(), new_patient.updated_plan, new_patient.status)
|
| 902 |
logger.info(f"WhatsApp message attempt sent: {whatsapp_sent}, message: {whatsapp_message}")
|
| 903 |
|
|
@@ -910,7 +898,8 @@ Hospital Contact: (Not provided) (it is useless abd vague okay and also in any s
|
|
| 910 |
'status': new_patient.status, # Return the final determined status
|
| 911 |
'whatsapp_sent': whatsapp_sent,
|
| 912 |
'whatsapp_message': whatsapp_message,
|
| 913 |
-
'ai_error': not ai_enabled or (ai_error_message is not None) # Indicate if AI was not enabled or failed
|
|
|
|
| 914 |
})
|
| 915 |
|
| 916 |
except Exception as e:
|
|
@@ -920,6 +909,9 @@ Hospital Contact: (Not provided) (it is useless abd vague okay and also in any s
|
|
| 920 |
'success': False,
|
| 921 |
'error': f'An unexpected server error occurred: {str(e)}'
|
| 922 |
}), 500
|
|
|
|
|
|
|
|
|
|
| 923 |
|
| 924 |
# --- New routes for Doctor Dashboard actions ---
|
| 925 |
|
|
|
|
| 652 |
logger.info("Accessed doctor dashboard, setting role to doctor.")
|
| 653 |
return render_template('doctor_dashboard.html')
|
| 654 |
|
| 655 |
+
# --- START: Modified submit_feedback function (includes optimized prompt logic) ---
|
| 656 |
@app.route('/submit_feedback', methods=['POST'])
|
| 657 |
def submit_feedback():
|
| 658 |
ai_enabled = bool(model) # Check if model is initialized
|
|
|
|
| 681 |
age = None # Store as None if not provided
|
| 682 |
|
| 683 |
care_plan_text = "" # This will store the extracted text from PDF
|
|
|
|
| 684 |
|
| 685 |
if 'care_plan_pdf' in request.files:
|
| 686 |
pdf_file = request.files['care_plan_pdf']
|
|
|
|
| 693 |
logger.info(f"Processing uploaded PDF: {pdf_file.filename}")
|
| 694 |
care_plan_text = extract_text_from_pdf(pdf_file)
|
| 695 |
|
| 696 |
+
# If extraction resulted in an error message, the variable will contain it.
|
| 697 |
+
# This error message will be passed to the AI as "Previous Care Plan Details".
|
| 698 |
+
logger.info(f"Extracted text length: {len(care_plan_text)}. Begins with: {care_plan_text[:100]}...")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 699 |
else:
|
| 700 |
logger.info("No PDF file uploaded or file is empty.")
|
| 701 |
|
| 702 |
+
# Determine the initial status based on feedback and original plan text
|
| 703 |
# Pass "" for updated_plan initially, as it hasn't been generated yet for status check
|
| 704 |
initial_status = determine_patient_status(care_plan_text, "", feedback)
|
| 705 |
logger.info(f"Initial status determined based on feedback/original plan: {initial_status}")
|
| 706 |
|
|
|
|
| 707 |
generated_plan_text = "" # This will store the AI-generated or fallback plan
|
| 708 |
final_status_to_save = initial_status # Start with initial status
|
| 709 |
|
| 710 |
+
# --- Define the NEW, FIXED Care Plan Structure for the AI Output ---
|
| 711 |
+
# Removed 'Emergency Contacts' and 'Red Flags' sections, added 'PHYSICAL ACTIVITY AND EXERCISE'
|
| 712 |
+
required_care_plan_structure = """
|
| 713 |
+
PATIENT INFORMATION:
|
| 714 |
+
ASSESSMENT:
|
| 715 |
+
DAILY CARE PLAN:
|
| 716 |
+
Morning:
|
| 717 |
+
Afternoon:
|
| 718 |
+
Night:
|
| 719 |
+
MEDICATIONS:
|
| 720 |
+
DIET AND HYDRATION:
|
| 721 |
+
PHYSICAL ACTIVITY AND EXERCISE:
|
| 722 |
+
SYMPTOM MANAGEMENT:
|
| 723 |
+
"""
|
| 724 |
+
|
| 725 |
# Only generate AI plan if AI is enabled AND status isn't immediate emergency based on feedback
|
| 726 |
# If feedback triggers "emergency", the generated_plan_text is a fixed emergency plan.
|
| 727 |
if final_status_to_save == 'emergency':
|
|
|
|
| 734 |
f"- Gender: {gender}\n\n"
|
| 735 |
"ASSESSMENT:\n"
|
| 736 |
f"- Emergency symptoms reported: {feedback}. Immediate medical attention required.\n\n"
|
| 737 |
+
"DAILY CARE PLAN:\n" # Using the new structure headings
|
| 738 |
+
"Morning:\n"
|
| 739 |
+
"- Seek immediate medical evaluation.\n"
|
| 740 |
+
"Afternoon:\n"
|
| 741 |
+
"- Follow instructions from emergency services.\n"
|
| 742 |
+
"Night:\n"
|
| 743 |
+
"- Remain under medical supervision if advised.\n\n"
|
| 744 |
+
"MEDICATIONS:\n"
|
| 745 |
+
"- Specific medicines and dosage usage based on symptoms (ex : for fever paramcetamol 1-1-1)\n\n"
|
| 746 |
+
"DIET AND HYDRATION:\n"
|
| 747 |
+
"- Do not consume food or drink unless advised by medical professionals.\n\n"
|
| 748 |
+
"PHYSICAL ACTIVITY AND EXERCISE:\n"
|
| 749 |
+
"- Rest completely and avoid any physical activity until evaluated by medical professionals.\n\n"
|
| 750 |
+
"SYMPTOM MANAGEMENT:\n"
|
| 751 |
+
"- Focus on seeking professional help. Do not attempt home management of emergency symptoms.\n"
|
| 752 |
)
|
|
|
|
| 753 |
# Status remains 'emergency', which was already set as final_status_to_save.
|
| 754 |
|
| 755 |
|
| 756 |
elif ai_enabled: # AI is enabled and initial status is not emergency
|
| 757 |
+
logger.info("AI is enabled and status is not emergency. Generating plan via AI.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 758 |
|
| 759 |
+
# --- MODIFIED AND OPTIMIZED AI PROMPT (This is the key change) ---
|
| 760 |
prompt = f"""
|
| 761 |
+
You are an expert AI assistant specialized in generating concise, structured patient care plans.
|
| 762 |
+
|
| 763 |
+
Based on the following Patient Information, Patient Feedback, and Previous Care Plan (if available), generate a NEW care plan.
|
| 764 |
+
|
| 765 |
+
--- Patient Information ---
|
| 766 |
Name: {name}
|
| 767 |
Age: {age if age is not None else 'N/A'}
|
| 768 |
Gender: {gender}
|
| 769 |
+
|
| 770 |
+
--- Patient Feedback/Symptoms Update ---
|
| 771 |
{feedback}
|
| 772 |
+
|
| 773 |
+
--- Previous Care Plan Details (if available) ---
|
| 774 |
{care_plan_text if care_plan_text and "[No readable text found" not in care_plan_text and "[Error extracting PDF text" not in care_plan_text and "[PDF Content Unavailable" not in care_plan_text else "No previous care plan provided or could not be read."}
|
| 775 |
+
|
| 776 |
+
--- Instructions for Generating the New Care Plan ---
|
| 777 |
+
1. Generate the care plan using ONLY the exact section headings and sub-sections listed in the "Required Care Plan Structure" below. Maintain the order.
|
| 778 |
+
2. Fill in the details for each section based on the provided information. Prioritize addressing the latest feedback while incorporating relevant, SAFE, and appropriate details from the previous plan.
|
| 779 |
+
3. Be specific, actionable, and tailored to the patient's situation as described.
|
| 780 |
+
4. Keep the content concise. Aim for a few sentences or bullet points per sub-section (e.g., Morning, Afternoon, Night) and per main section (e.g., ASSESSMENT, MEDICATIONS, DIET, EXERCISE, SYMPTOM MANAGEMENT). Do NOT exceed 4 sentences/points per section/sub-section if possible, but prioritize clarity and necessary instructions.
|
| 781 |
+
5. Regarding MEDICATIONS:
|
| 782 |
+
- If the previous plan listed specific prescribed medications, include them with dosage and timing if possible.
|
| 783 |
+
- If specific medications are not available in the previous plan, list the *types* of medications commonly used for the patient's condition (if implied by the feedback/previous plan, e.g., "Blood pressure medication", "Pain relief").
|
| 784 |
+
- You MAY mention common, over-the-counter examples for specific symptoms if the feedback implies them (e.g., "Paracetamol for fever or mild pain"), but *always* emphasize consulting a doctor for specific prescriptions and dosage. Avoid recommending prescription drugs you are not explicitly told about.
|
| 785 |
+
- *Crucially, do NOT make up prescription drug names or dosages.*
|
| 786 |
+
- *Crucially, do NOT use phrases like "Medications to be determined by physician", "Doctor will provide", "Not provided", "(Unknown)", etc.* List what is known or infer likely categories.
|
| 787 |
+
6. For PHYSICAL ACTIVITY AND EXERCISE, provide concrete examples or recommendations suitable for someone with the patient's condition and current status (e.g., "Gentle walking 15 mins daily", "Light stretching exercises", "Avoid strenuous activity"). Tailor this to the patient's feedback (e.g., if deteriorating, recommend rest).
|
| 788 |
+
7. Do NOT include sections like "Red Flags", "Emergency Contacts", "Contact Number", "Doctor's Name", "Hospital Contact", or "Primary Caregiver".
|
| 789 |
+
8. Do NOT use any vague placeholders like "(To be added)", "(Not provided)", or "(Unknown)" anywhere in the plan. If information is truly unavailable and you cannot infer a reasonable default (like suggesting a type of medication), omit the specific detail rather than using a placeholder.
|
| 790 |
+
9. Do NOT include any introductory phrases (e.g., "Here is the plan", "Based on your feedback") or concluding remarks outside the plan structure. Provide ONLY the structured content.
|
| 791 |
+
10. Ensure the plan's tone and content are appropriate for the patient's determined status (Deteriorating, Improving, Stable). For deteriorating status, emphasize caution and monitoring. For improving, suggest gradual progression if appropriate.
|
| 792 |
+
11. Review the feedback and previous plan carefully to determine the most likely current STATUS (e.g., Emergency, Deteriorating, Improving, Stable) and ensure the plan content aligns with that status.
|
| 793 |
+
|
| 794 |
+
--- Required Care Plan Structure (Use ONLY these exact sections and sub-sections in this order) ---
|
| 795 |
+
{required_care_plan_structure}
|
| 796 |
"""
|
| 797 |
+
# --- END OF MODIFIED AI PROMPT ---
|
| 798 |
+
|
| 799 |
+
|
| 800 |
logger.info("Sending prompt to AI model...")
|
| 801 |
|
| 802 |
try:
|
|
|
|
| 805 |
generated_plan_text = response.text.strip()
|
| 806 |
|
| 807 |
# Remove markdown code block formatting if present
|
| 808 |
+
if generated_plan_text.startswith('```'):
|
|
|
|
| 809 |
first_newline_after_code = generated_plan_text.find('\n')
|
| 810 |
if first_newline_after_code != -1:
|
| 811 |
+
# Check if there's a language name before the newline
|
| 812 |
+
potential_lang = generated_plan_text[3:first_newline_after_code].strip()
|
| 813 |
+
if re.match(r'^[a-zA-Z0-9]+$', potential_lang): # Simple check for language name
|
| 814 |
+
generated_plan_text = generated_plan_text[first_newline_after_code:].strip()
|
| 815 |
+
else:
|
| 816 |
+
generated_plan_text = generated_plan_text[3:].strip()
|
|
|
|
| 817 |
else:
|
| 818 |
+
generated_plan_text = generated_plan_text[3:].strip()
|
|
|
|
| 819 |
|
|
|
|
| 820 |
if generated_plan_text.endswith('```'):
|
| 821 |
generated_plan_text = generated_plan_text[:-3].strip()
|
| 822 |
|
|
|
|
| 824 |
logger.info(f"AI Response received. Length: {len(generated_plan_text)}")
|
| 825 |
|
| 826 |
# Re-determine the final status using the generated plan as well.
|
|
|
|
|
|
|
| 827 |
final_status_to_save = determine_patient_status(care_plan_text, generated_plan_text, feedback)
|
| 828 |
logger.info(f"Final status determined after AI generation: {final_status_to_save}")
|
| 829 |
|
|
|
|
| 862 |
|
| 863 |
|
| 864 |
# Create and store patient record in the database
|
| 865 |
+
# Ensure original_plan is stored even if it contains error messages from PDF extraction
|
| 866 |
new_patient = Patient(
|
| 867 |
name=name,
|
| 868 |
age=age,
|
|
|
|
| 880 |
logger.info(f"Patient {patient_id} added to DB with status: {final_status_to_save}.")
|
| 881 |
|
| 882 |
# Generate PDF for downloading using the stored data
|
|
|
|
|
|
|
| 883 |
pdf_buffer = generate_care_plan_pdf(new_patient.to_dict(), new_patient.updated_plan, new_patient.status)
|
| 884 |
pdf_buffer.seek(0) # Ensure buffer is at the start before base64 encoding
|
| 885 |
pdf_base64 = base64.b64encode(pdf_buffer.getvalue()).decode('utf-8')
|
| 886 |
logger.info("PDF generated and base64 encoded.")
|
| 887 |
|
| 888 |
# Send care plan via WhatsApp (using the final saved data)
|
|
|
|
| 889 |
whatsapp_sent, whatsapp_message = send_whatsapp_care_plan(new_patient.to_dict(), new_patient.updated_plan, new_patient.status)
|
| 890 |
logger.info(f"WhatsApp message attempt sent: {whatsapp_sent}, message: {whatsapp_message}")
|
| 891 |
|
|
|
|
| 898 |
'status': new_patient.status, # Return the final determined status
|
| 899 |
'whatsapp_sent': whatsapp_sent,
|
| 900 |
'whatsapp_message': whatsapp_message,
|
| 901 |
+
'ai_error': not ai_enabled or (ai_error_message is not None), # Indicate if AI was not enabled or failed
|
| 902 |
+
'ai_error_message': ai_error_message # Include the specific error message if applicable
|
| 903 |
})
|
| 904 |
|
| 905 |
except Exception as e:
|
|
|
|
| 909 |
'success': False,
|
| 910 |
'error': f'An unexpected server error occurred: {str(e)}'
|
| 911 |
}), 500
|
| 912 |
+
# --- END: Modified submit_feedback function ---
|
| 913 |
+
|
| 914 |
+
|
| 915 |
|
| 916 |
# --- New routes for Doctor Dashboard actions ---
|
| 917 |
|