Allow scheduling multiple medications at once, remove time conflicts

- Multi-med creation form: add any number of medication cards in one session, each with independent name/dosage/unit/frequency/times settings
- Submit button labels dynamically (Add 1 / Add N Medications)
- Removed all schedule conflict checking — medications can now coexist at the same time slot as each other and as routines

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 19:38:44 -06:00
parent 33db2629e3
commit 4c4ff5add3
2 changed files with 263 additions and 255 deletions

View File

@@ -145,56 +145,6 @@ def register(app):
meds = postgres.select("medications", where={"user_uuid": user_uuid}, order_by="name")
return flask.jsonify(meds), 200
def _time_str_to_minutes(time_str):
"""Convert 'HH:MM' to minutes since midnight."""
parts = time_str.split(":")
return int(parts[0]) * 60 + int(parts[1])
def _get_routine_duration_minutes(routine_id):
"""Get total duration of a routine from its steps."""
steps = postgres.select("routine_steps", where={"routine_id": routine_id})
total = sum(s.get("duration_minutes", 0) or 0 for s in steps)
return max(total, 1)
def _check_med_schedule_conflicts(user_uuid, new_times, new_days=None, exclude_med_id=None):
"""Check if the proposed medication schedule conflicts with existing routines or medications.
Returns (has_conflict, conflict_message) tuple.
"""
if not new_times:
return False, None
# Check conflicts with routines (duration-aware)
user_routines = postgres.select("routines", {"user_uuid": user_uuid})
for r in user_routines:
sched = postgres.select_one("routine_schedules", {"routine_id": r["id"]})
if not sched or not sched.get("time"):
continue
routine_days = sched.get("days", [])
if isinstance(routine_days, str):
routine_days = json.loads(routine_days)
if new_days and not any(d in routine_days for d in new_days):
continue
routine_start = _time_str_to_minutes(sched["time"])
routine_dur = _get_routine_duration_minutes(r["id"])
for t in new_times:
med_start = _time_str_to_minutes(t)
# Med falls within routine time range
if routine_start <= med_start < routine_start + routine_dur:
return True, f"Time conflicts with routine: {r.get('name', 'Unnamed routine')}"
# Check conflicts with other medications
user_meds = postgres.select("medications", {"user_uuid": user_uuid, "active": True})
for med in user_meds:
if med["id"] == exclude_med_id:
continue
med_times = med.get("times", [])
if isinstance(med_times, str):
med_times = json.loads(med_times)
if any(t in med_times for t in new_times):
return True, f"Time conflicts with medication: {med.get('name', 'Unnamed medication')}"
return False, None
@app.route("/api/medications", methods=["POST"])
def api_addMedication():
"""Add a medication. Body: {name, dosage, unit, frequency, times?, days_of_week?, interval_days?, start_date?, notes?}"""
@@ -214,15 +164,6 @@ def register(app):
if not data.get("start_date") or not data.get("interval_days"):
return flask.jsonify({"error": "every_n_days frequency requires both start_date and interval_days"}), 400
# Check for schedule conflicts
new_times = data.get("times", [])
new_days = data.get("days_of_week", [])
has_conflict, conflict_msg = _check_med_schedule_conflicts(
user_uuid, new_times, new_days
)
if has_conflict:
return flask.jsonify({"error": conflict_msg}), 409
row = {
"id": str(uuid.uuid4()),
"user_uuid": user_uuid,
@@ -283,16 +224,6 @@ def register(app):
"days_of_week", "interval_days", "start_date", "next_dose_date",
]
# Check for schedule conflicts if times are being updated
if "times" in data:
new_times = data.get("times", [])
new_days = data.get("days_of_week") or existing.get("days_of_week", [])
has_conflict, conflict_msg = _check_med_schedule_conflicts(
user_uuid, new_times, new_days, exclude_med_id=med_id
)
if has_conflict:
return flask.jsonify({"error": conflict_msg}), 409
updates = {k: v for k, v in data.items() if k in allowed}
if not updates:
return flask.jsonify({"error": "no valid fields to update"}), 400