Spaces:
Runtime error
Runtime error
| from __future__ import annotations | |
| import base64 | |
| import io | |
| import os | |
| from datetime import date | |
| from gradio import Server | |
| from fastapi.responses import HTMLResponse | |
| import logic | |
| import storage | |
| import vision | |
| app = Server() | |
| HERE = os.path.dirname(os.path.abspath(__file__)) | |
| def _fmt_qty(q): | |
| if q is None: | |
| return None | |
| return int(q) if float(q).is_integer() else q | |
| def _payload() -> dict: | |
| meds = storage.load_meds() | |
| rows = [] | |
| for i, m in enumerate(meds): | |
| rows.append({ | |
| "i": i, "name": m.drug_name, "dose": m.dose, "instruction": m.frequency_text, | |
| "quantity": _fmt_qty(m.quantity), | |
| "times": [logic.format_time_12h(t) for t in (m.schedule_times or [])], | |
| "run_out": m.run_out_date, "refill_or_expiry": m.refill_or_expiry_date, | |
| "warning": m.refill_warning, "on_track": not m.refill_warning, | |
| }) | |
| timed, as_needed = logic.build_daily_agenda(meds) | |
| schedule = [{"time": logic.format_time_12h(t), "items": items} for t, items in timed] | |
| today = date.today().strftime("%A, %B %d, %Y").replace(" 0", " ") | |
| return {"meds": rows, "schedule": schedule, "as_needed": as_needed, "today": today} | |
| def _decode(data_url: str): | |
| if not data_url or "," not in data_url: | |
| return None | |
| try: | |
| raw = base64.b64decode(data_url.split(",", 1)[1]) | |
| from PIL import Image | |
| return Image.open(io.BytesIO(raw)).convert("RGB") | |
| except Exception: | |
| return None | |
| def state() -> dict: | |
| return _payload() | |
| def read_label(image_data: str = "") -> dict: | |
| img = _decode(image_data) | |
| if img is None: | |
| return {"ok": False, "message": "Upload a photo of the label first."} | |
| try: | |
| raw = vision.extract_label(img) | |
| data = logic.safe_parse(raw) | |
| except Exception as exc: | |
| return {"ok": False, "message": f"Couldn't read the label ({exc}). Enter the details below."} | |
| if not data: | |
| return {"ok": False, "message": "Couldn't read the label clearly — try a sharper, well-lit photo, or enter it below."} | |
| return {"ok": True, "fields": { | |
| "drug_name": data.get("drug_name") or "", "dose": data.get("dose") or "", | |
| "frequency_text": data.get("frequency_text") or "", | |
| "quantity": _fmt_qty(data.get("quantity")) or "", | |
| "refill_or_expiry_date": data.get("refill_or_expiry_date") or ""}} | |
| def save_med(drug_name: str = "", dose: str = "", frequency_text: str = "", | |
| quantity: str = "", refill_or_expiry_date: str = "", index: int = -1) -> dict: | |
| if not (drug_name or "").strip(): | |
| return {"ok": False, "message": "A medication name is required.", **_payload()} | |
| data = {"drug_name": drug_name.strip(), "dose": (dose or "").strip() or None, | |
| "frequency_text": (frequency_text or "").strip() or None, | |
| "quantity": logic._coerce_quantity(quantity), | |
| "refill_or_expiry_date": (refill_or_expiry_date or "").strip() or None} | |
| med = logic.make_medication(data) | |
| meds = storage.load_meds() | |
| if 0 <= int(index) < len(meds): | |
| meds[int(index)] = med | |
| else: | |
| meds.append(med) | |
| storage.save_meds(meds) | |
| return {"ok": True, **_payload()} | |
| def delete_med(index: int = -1) -> dict: | |
| meds = storage.load_meds() | |
| if 0 <= int(index) < len(meds): | |
| meds.pop(int(index)); storage.save_meds(meds) | |
| return {"ok": True, **_payload()} | |
| def clear_all() -> dict: | |
| storage.save_meds([]) | |
| return {"ok": True, **_payload()} | |
| async def homepage(): | |
| with open(os.path.join(HERE, "index.html"), "r", encoding="utf-8") as f: | |
| return f.read() | |
| if __name__ == "__main__": | |
| os.environ.setdefault("GRADIO_SERVER_NAME", "0.0.0.0") | |
| os.environ.setdefault("GRADIO_SERVER_PORT", "7860") | |
| app.launch(show_error=True) | |