AidAILine / export_tool.py
J-Barrert's picture
Upload 14 files
585cfd5 verified
Raw
History Blame Contribute Delete
7.1 kB
"""
export_tool.py β€” Assemble and export caregiver data summaries.
Combines selected data (meds, appointments, food chart, and an optional
document summary) into a formatted text block ready for copy, email, or print.
"""
from __future__ import annotations
import textwrap
from datetime import datetime
from typing import Optional
from config import load_patient_config
from med_tracker import get_medications
from appointment_tracker import get_upcoming
from food_tracker import get_food
from profiles import get_profile
# ── Core assembler ────────────────────────────────────────────────────────────
def assemble_export(
include_meds: bool = True,
include_appointments: bool = True,
include_food: bool = True,
document_summary: Optional[str] = None,
custom_note: Optional[str] = None,
profile_id: Optional[str] = None,
) -> str:
"""
Assemble a formatted text export block.
Returns a multi-line string suitable for copy-to-clipboard, email body,
or print.
"""
cfg = load_patient_config()
today = datetime.now().strftime("%B %d, %Y at %I:%M %p")
profile = get_profile(profile_id) if profile_id else None
patient_label = ""
if profile:
patient_label = profile.get("full_name") or profile.get("label") or ""
lines = []
# ── Header ──────────────────────────────────────────────────────────────
lines.append("=" * 60)
lines.append(" CAREGIVER SUMMARY REPORT")
lines.append(f" Generated: {today}")
if patient_label:
lines.append(f" Patient: {patient_label}")
elif cfg.get("patient_name"):
lines.append(f" Patient: {cfg['patient_name']}")
lines.append("=" * 60)
lines.append("")
# ── Custom note ──────────────────────────────────────────────────────────
if custom_note and custom_note.strip():
lines.append("NOTES")
lines.append("-" * 40)
lines.append(custom_note.strip())
lines.append("")
# ── Medications ──────────────────────────────────────────────────────────
if include_meds:
meds = get_medications(filter="current", profile_id=profile_id)
lines.append("CURRENT MEDICATIONS")
lines.append("-" * 40)
if meds:
for med in meds:
parts = [med["name"]]
if med.get("dosage"):
parts.append(med["dosage"])
if med.get("frequency"):
parts.append(f"({med['frequency']})")
lines.append("β€’ " + " ".join(parts))
if med.get("side_effects"):
lines.append(f" ↳ Side effects: {med['side_effects']}")
if med.get("personal_notes"):
lines.append(f" ↳ Notes: {med['personal_notes']}")
else:
lines.append("No current medications on file.")
lines.append("")
# ── Appointments ─────────────────────────────────────────────────────────
if include_appointments:
appts = get_upcoming(profile_id=profile_id)
lines.append("UPCOMING APPOINTMENTS")
lines.append("-" * 40)
if appts:
for appt in appts:
date_str = appt.get("date", "")
time_str = appt.get("time", "")
when = date_str + (f" at {time_str}" if time_str else "")
lines.append(f"β€’ {appt['title']} β€” {when}")
if appt.get("location"):
lines.append(f" Location: {appt['location']}")
if appt.get("notes"):
lines.append(f" Notes: {appt['notes']}")
else:
lines.append("No upcoming appointments.")
lines.append("")
# ── Food Chart ───────────────────────────────────────────────────────────
if include_food:
food_data = get_food(profile_id=profile_id)
lines.append("FOOD CHART")
lines.append("-" * 40)
liked = food_data.get("liked_foods", [])
disliked = food_data.get("disliked_foods", [])
allergies = food_data.get("allergies", [])
if allergies:
lines.append("⚠ Allergies:")
for e in allergies:
note_part = f" ({e['notes']})" if e.get("notes") else ""
lines.append(f" β€’ {e['name']}{note_part}")
if liked:
lines.append("βœ“ Liked Foods:")
for e in liked:
note_part = f" ({e['notes']})" if e.get("notes") else ""
lines.append(f" β€’ {e['name']}{note_part}")
if disliked:
lines.append("βœ— Disliked Foods:")
for e in disliked:
note_part = f" ({e['notes']})" if e.get("notes") else ""
lines.append(f" β€’ {e['name']}{note_part}")
if not allergies and not liked and not disliked:
lines.append("No food data on file.")
lines.append("")
# ── Document Summary ─────────────────────────────────────────────────────
if document_summary and document_summary.strip():
lines.append("DOCUMENT SUMMARY")
lines.append("-" * 40)
# Word-wrap long lines
for para in document_summary.strip().split("\n"):
wrapped = textwrap.fill(para, width=58) if len(para) > 58 else para
lines.append(wrapped)
lines.append("")
# ── Footer ───────────────────────────────────────────────────────────────
lines.append("=" * 60)
lines.append("Built for the Build Small Hackathon β€” Backyard AI Track")
lines.append("All data is stored locally. Nothing leaves this device.")
lines.append("=" * 60)
return "\n".join(lines)
def build_mailto_link(
to: str = "",
subject: str = "Caregiver Summary Report",
body: str = "",
) -> str:
"""
Build a mailto: URL with pre-filled subject and body.
The body is URL-encoded so it works in href attributes.
"""
import urllib.parse
encoded_body = urllib.parse.quote(body)
encoded_subject = urllib.parse.quote(subject)
return f"mailto:{to}?subject={encoded_subject}&body={encoded_body}"