Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -177,11 +177,9 @@ twilio_client = TwilioClient(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_PHONE
|
|
| 177 |
|
| 178 |
# Patient Info and State Management
|
| 179 |
def get_patient_info():
|
| 180 |
-
patient_id = unquote(os.
|
| 181 |
-
patient_name = unquote(os.
|
| 182 |
-
|
| 183 |
-
return patient_id, patient_name
|
| 184 |
-
return None, None
|
| 185 |
|
| 186 |
patient_id, patient_name = get_patient_info()
|
| 187 |
patient_id_state = gr.State(value=patient_id)
|
|
@@ -204,46 +202,6 @@ def follow_up_scheduler():
|
|
| 204 |
sf_client.update_record("FollowUpPlan__c", plan["Id"], {"Status__c": "Sent"})
|
| 205 |
time.sleep(86400) # Run daily
|
| 206 |
|
| 207 |
-
# Automated Follow-up
|
| 208 |
-
def send_automated_followup(patient_id, action_type):
|
| 209 |
-
if not patient_id:
|
| 210 |
-
return "Please log in to receive follow-ups."
|
| 211 |
-
patients = sf_client.query_records(f"SELECT Phone__c, Name, ConsentGiven__c FROM Patient__c WHERE Id = '{patient_id}'")
|
| 212 |
-
if not patients or not patients[0]["ConsentGiven__c"]:
|
| 213 |
-
return "No patient found or consent not given."
|
| 214 |
-
patient = patients[0]
|
| 215 |
-
consent = sf_client.query_records(f"SELECT Method__c FROM Consent__c WHERE Patient__c = '{patient_id}' ORDER BY CreatedDate DESC LIMIT 1")
|
| 216 |
-
consent_method = consent[0]["Method__c"] if consent else "SMS"
|
| 217 |
-
message_templates = {
|
| 218 |
-
"consent": f"Hello {patient['Name']}, thank you for registering!",
|
| 219 |
-
"daily": f"Hi {patient['Name']}, your daily follow-up check-in.",
|
| 220 |
-
"appointment": f"Dear {patient['Name']}, your appointment is confirmed."
|
| 221 |
-
}
|
| 222 |
-
message = message_templates.get(action_type, f"Hi {patient['Name']}, an action was performed.")
|
| 223 |
-
if twilio_client.send_message(patient["Phone__c"], message, method=consent_method.lower()):
|
| 224 |
-
sf_client.create_record("MessageLog__c", {
|
| 225 |
-
"Patient__c": patient_id, "MessageText__c": message,
|
| 226 |
-
"Direction__c": "Outbound", "Timestamp__c": datetime.utcnow().isoformat()
|
| 227 |
-
})
|
| 228 |
-
return f"Follow-up sent for {action_type}!"
|
| 229 |
-
return "Failed to send follow-up."
|
| 230 |
-
|
| 231 |
-
# Update Patient Profile
|
| 232 |
-
def update_patient_profile(patient_id, height, weight, emergency_name, emergency_number, emergency_relationship):
|
| 233 |
-
if not patient_id:
|
| 234 |
-
return "Please log in to update your profile."
|
| 235 |
-
update_data = {}
|
| 236 |
-
if height is not None and height != "": update_data["Height__c"] = float(height)
|
| 237 |
-
if weight is not None and weight != "": update_data["Weight__c"] = float(weight)
|
| 238 |
-
if emergency_name: update_data["EmergencyContactName__c"] = emergency_name
|
| 239 |
-
if emergency_number: update_data["EmergencyContactNumber__c"] = emergency_number
|
| 240 |
-
if emergency_relationship: update_data["EmergencyContactRelationship__c"] = emergency_relationship
|
| 241 |
-
if update_data:
|
| 242 |
-
if sf_client.update_record("Patient__c", patient_id, update_data):
|
| 243 |
-
return "Profile updated successfully!"
|
| 244 |
-
return "Failed to update profile."
|
| 245 |
-
return "No changes made."
|
| 246 |
-
|
| 247 |
# Schedule Appointment
|
| 248 |
def schedule_appointment(patient_id, doctor_name, appointment_date, time_slot, reason, special_requests):
|
| 249 |
if not all([patient_id, doctor_name, appointment_date, time_slot]):
|
|
@@ -262,57 +220,18 @@ def schedule_appointment(patient_id, doctor_name, appointment_date, time_slot, r
|
|
| 262 |
if special_requests: appointment_data["SpecialRequests__c"] = special_requests
|
| 263 |
result = sf_client.create_record("Appointment__c", appointment_data)
|
| 264 |
if result:
|
| 265 |
-
send_automated_followup(patient_id, "appointment")
|
| 266 |
return f"Appointment scheduled with {doctor_name} on {appointment_date} at {time_slot}:00!"
|
| 267 |
return "Failed to schedule appointment."
|
| 268 |
|
| 269 |
-
# View Risk Dashboard
|
| 270 |
-
def view_risk_dashboard(patient_id):
|
| 271 |
-
if not patient_id:
|
| 272 |
-
return pd.DataFrame(), "Please log in to view your risk dashboard."
|
| 273 |
-
symptom_logs = sf_client.query_records(f"SELECT ResponseText__c, RiskScore__c, Severity__c, Sentiment__c FROM SymptomLog__c WHERE Patient__c = '{patient_id}'")
|
| 274 |
-
if symptom_logs:
|
| 275 |
-
df = pd.DataFrame([
|
| 276 |
-
{"Response": log["ResponseText__c"], "Risk Score": log["RiskScore__c"],
|
| 277 |
-
"Severity": log["Severity__c"], "Sentiment": log["Sentiment__c"]}
|
| 278 |
-
for log in symptom_logs
|
| 279 |
-
])
|
| 280 |
-
high_risk = df[df["Severity"] == "High"].to_dict('records') if not df.empty and "Severity" in df else []
|
| 281 |
-
return df, high_risk if high_risk else "No high-risk cases."
|
| 282 |
-
return pd.DataFrame(), "No symptom logs available."
|
| 283 |
-
|
| 284 |
-
# Escalate Case
|
| 285 |
-
def escalate_case(patient_id, response_text):
|
| 286 |
-
if not patient_id or not response_text:
|
| 287 |
-
return "Please log in and provide a response text."
|
| 288 |
-
analysis = hf_client.analyze_response(response_text)
|
| 289 |
-
if analysis and analysis["risk_level"] == "High":
|
| 290 |
-
case_data = {
|
| 291 |
-
"RelatedPatient__c": patient_id, "Priority__c": "High",
|
| 292 |
-
"Description__c": f"High-risk response: {response_text}"
|
| 293 |
-
}
|
| 294 |
-
if sf_client.create_record("Case__c", case_data):
|
| 295 |
-
patient = sf_client.query_records(f"SELECT Phone__c FROM Patient__c WHERE Id = '{patient_id}'")
|
| 296 |
-
if patient:
|
| 297 |
-
twilio_client.send_message(patient[0]["Phone__c"], "Your case is escalated. A doctor will contact you.")
|
| 298 |
-
return "Case escalated successfully!"
|
| 299 |
-
return "No high-risk case detected or escalation failed."
|
| 300 |
-
|
| 301 |
# Gradio Interface
|
| 302 |
with gr.Blocks(theme=gr.themes.Soft(), title="HealthPortal - Patient Care") as demo:
|
| 303 |
gr.Markdown("# HealthPortal - Patient Care System")
|
| 304 |
patient_id_state = gr.State(value=patient_id)
|
| 305 |
patient_name_state = gr.State(value=patient_name)
|
| 306 |
|
| 307 |
-
def get_welcome_message(pid):
|
| 308 |
-
if pid:
|
| 309 |
-
patient = sf_client.query_records(f"SELECT Name FROM Patient__c WHERE Id = '{pid}'")
|
| 310 |
-
return f"## Welcome back, {patient[0]['Name'] if patient else 'Guest'}!" if patient else "## Welcome, Guest!"
|
| 311 |
-
return "## Welcome, Guest!"
|
| 312 |
-
|
| 313 |
with gr.Tabs():
|
| 314 |
with gr.Tab("Home"):
|
| 315 |
-
gr.Markdown(
|
| 316 |
if not patient_id_state.value:
|
| 317 |
gr.Markdown("**You are not logged in.** Please log in or register to access your personalized dashboard.")
|
| 318 |
with gr.Row():
|
|
@@ -357,51 +276,6 @@ with gr.Blocks(theme=gr.themes.Soft(), title="HealthPortal - Patient Care") as d
|
|
| 357 |
outputs=appt_output
|
| 358 |
)
|
| 359 |
|
| 360 |
-
with gr.Tab("Health Records"):
|
| 361 |
-
if not patient_id_state.value:
|
| 362 |
-
gr.Markdown("Please log in to view or update your health records.")
|
| 363 |
-
else:
|
| 364 |
-
gr.Markdown("## Health Records")
|
| 365 |
-
patient_data = sf_client.query_records(f"SELECT Name, Height__c, Weight__c, EmergencyContactName__c, EmergencyContactNumber__c, EmergencyContactRelationship__c FROM Patient__c WHERE Id = '{patient_id_state.value}'")
|
| 366 |
-
if patient_data:
|
| 367 |
-
patient = patient_data[0]
|
| 368 |
-
height_input = gr.Number(label="Height", value=patient.get("Height__c", 0), interactive=True)
|
| 369 |
-
weight_input = gr.Number(label="Weight", value=patient.get("Weight__c", 0), interactive=True)
|
| 370 |
-
emergency_name_input = gr.Textbox(label="Emergency Contact Name", value=patient.get("EmergencyContactName__c", ""))
|
| 371 |
-
emergency_number_input = gr.Textbox(label="Emergency Contact Number", value=patient.get("EmergencyContactNumber__c", ""))
|
| 372 |
-
emergency_rel_input = gr.Textbox(label="Emergency Contact Relationship", value=patient.get("EmergencyContactRelationship__c", ""))
|
| 373 |
-
update_button = gr.Button("Update Profile")
|
| 374 |
-
update_output = gr.Textbox(label="Result")
|
| 375 |
-
update_button.click(
|
| 376 |
-
fn=update_patient_profile,
|
| 377 |
-
inputs=[patient_id_state, height_input, weight_input, emergency_name_input, emergency_number_input, emergency_rel_input],
|
| 378 |
-
outputs=update_output
|
| 379 |
-
)
|
| 380 |
-
|
| 381 |
-
with gr.Tab("Follow-up"):
|
| 382 |
-
if not patient_id_state.value:
|
| 383 |
-
gr.Markdown("Please log in to submit feedback or escalate cases.")
|
| 384 |
-
else:
|
| 385 |
-
gr.Markdown("## Follow-up")
|
| 386 |
-
survey_questions = ["How was your visit?", "Any discomfort?", "Staff satisfaction?"]
|
| 387 |
-
survey_question_input = gr.Dropdown(survey_questions, label="Select Question", value=survey_questions[0])
|
| 388 |
-
survey_answer_input = gr.Textbox(label="Your Answer", lines=4)
|
| 389 |
-
survey_button = gr.Button("Submit Survey")
|
| 390 |
-
survey_output = gr.Textbox(label="Result")
|
| 391 |
-
survey_button.click(
|
| 392 |
-
fn=lambda pid, q, a: submit_survey(pid, q, a) or send_automated_followup(pid, "daily"),
|
| 393 |
-
inputs=[patient_id_state, survey_question_input, survey_answer_input],
|
| 394 |
-
outputs=survey_output
|
| 395 |
-
)
|
| 396 |
-
escalate_response_input = gr.Textbox(label="Response for Escalation", lines=4)
|
| 397 |
-
escalate_button = gr.Button("Escalate Case")
|
| 398 |
-
escalate_output = gr.Textbox(label="Result")
|
| 399 |
-
escalate_button.click(
|
| 400 |
-
fn=escalate_case,
|
| 401 |
-
inputs=[patient_id_state, escalate_response_input],
|
| 402 |
-
outputs=escalate_output
|
| 403 |
-
)
|
| 404 |
-
|
| 405 |
# Launch with Scheduler
|
| 406 |
if __name__ == "__main__":
|
| 407 |
import threading
|
|
|
|
| 177 |
|
| 178 |
# Patient Info and State Management
|
| 179 |
def get_patient_info():
|
| 180 |
+
patient_id = unquote(requests.utils.urlparse(os.environ.get("QUERY_STRING", "")).query.split("patientId=")[1].split("&")[0] if "patientId=" in os.environ.get("QUERY_STRING", "") else "")
|
| 181 |
+
patient_name = unquote(requests.utils.urlparse(os.environ.get("QUERY_STRING", "")).query.split("patientName=")[1].split("&")[0] if "patientName=" in os.environ.get("QUERY_STRING", "") else "")
|
| 182 |
+
return patient_id, patient_name
|
|
|
|
|
|
|
| 183 |
|
| 184 |
patient_id, patient_name = get_patient_info()
|
| 185 |
patient_id_state = gr.State(value=patient_id)
|
|
|
|
| 202 |
sf_client.update_record("FollowUpPlan__c", plan["Id"], {"Status__c": "Sent"})
|
| 203 |
time.sleep(86400) # Run daily
|
| 204 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
# Schedule Appointment
|
| 206 |
def schedule_appointment(patient_id, doctor_name, appointment_date, time_slot, reason, special_requests):
|
| 207 |
if not all([patient_id, doctor_name, appointment_date, time_slot]):
|
|
|
|
| 220 |
if special_requests: appointment_data["SpecialRequests__c"] = special_requests
|
| 221 |
result = sf_client.create_record("Appointment__c", appointment_data)
|
| 222 |
if result:
|
|
|
|
| 223 |
return f"Appointment scheduled with {doctor_name} on {appointment_date} at {time_slot}:00!"
|
| 224 |
return "Failed to schedule appointment."
|
| 225 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
# Gradio Interface
|
| 227 |
with gr.Blocks(theme=gr.themes.Soft(), title="HealthPortal - Patient Care") as demo:
|
| 228 |
gr.Markdown("# HealthPortal - Patient Care System")
|
| 229 |
patient_id_state = gr.State(value=patient_id)
|
| 230 |
patient_name_state = gr.State(value=patient_name)
|
| 231 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 232 |
with gr.Tabs():
|
| 233 |
with gr.Tab("Home"):
|
| 234 |
+
gr.Markdown("## Welcome to Your Dashboard!")
|
| 235 |
if not patient_id_state.value:
|
| 236 |
gr.Markdown("**You are not logged in.** Please log in or register to access your personalized dashboard.")
|
| 237 |
with gr.Row():
|
|
|
|
| 276 |
outputs=appt_output
|
| 277 |
)
|
| 278 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 279 |
# Launch with Scheduler
|
| 280 |
if __name__ == "__main__":
|
| 281 |
import threading
|