Fix bugs, add auto-refresh, quick-complete tasks, and every-N-day routines
- Fix bot auth: merge duplicate on_ready handlers so session restore runs (#13) - Fix push notifications: pass Uint8Array directly as applicationServerKey (#6) - Show specific conflict reason on schedule save instead of generic error (#17) - Add inline checkmark button to complete tasks on routines timeline (#18) - Add visibility-change + 60s polling auto-refresh to routines, meds, tasks (#15) - Add every-N-day routine scheduling: schema, API, scheduler, and UI (#16) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -661,17 +661,20 @@ def register(app):
|
||||
continue
|
||||
steps = postgres.select("routine_steps", where={"routine_id": r["id"]})
|
||||
total_duration = sum(s.get("duration_minutes") or 0 for s in steps)
|
||||
result.append(
|
||||
{
|
||||
"routine_id": r["id"],
|
||||
"routine_name": r.get("name", ""),
|
||||
"routine_icon": r.get("icon", ""),
|
||||
"days": sched.get("days", []),
|
||||
"time": sched.get("time"),
|
||||
"remind": sched.get("remind", True),
|
||||
"total_duration_minutes": total_duration,
|
||||
}
|
||||
)
|
||||
entry = {
|
||||
"routine_id": r["id"],
|
||||
"routine_name": r.get("name", ""),
|
||||
"routine_icon": r.get("icon", ""),
|
||||
"days": sched.get("days", []),
|
||||
"time": sched.get("time"),
|
||||
"remind": sched.get("remind", True),
|
||||
"total_duration_minutes": total_duration,
|
||||
"frequency": sched.get("frequency", "weekly"),
|
||||
}
|
||||
if sched.get("frequency") == "every_n_days":
|
||||
entry["interval_days"] = sched.get("interval_days")
|
||||
entry["start_date"] = str(sched.get("start_date")) if sched.get("start_date") else None
|
||||
result.append(entry)
|
||||
return flask.jsonify(result), 200
|
||||
|
||||
def _get_routine_duration_minutes(routine_id):
|
||||
@@ -745,7 +748,10 @@ def register(app):
|
||||
|
||||
@app.route("/api/routines/<routine_id>/schedule", methods=["PUT"])
|
||||
def api_setRoutineSchedule(routine_id):
|
||||
"""Set when this routine should run. Body: {days: ["mon","tue",...], time: "08:00", remind: true}"""
|
||||
"""Set when this routine should run.
|
||||
Body: {days, time, remind, frequency?, interval_days?, start_date?}
|
||||
frequency: 'weekly' (default, uses days) or 'every_n_days' (uses interval_days + start_date)
|
||||
"""
|
||||
user_uuid = _auth(flask.request)
|
||||
if not user_uuid:
|
||||
return flask.jsonify({"error": "unauthorized"}), 401
|
||||
@@ -758,15 +764,18 @@ def register(app):
|
||||
if not data:
|
||||
return flask.jsonify({"error": "missing body"}), 400
|
||||
|
||||
# Check for schedule conflicts
|
||||
new_days = data.get("days", [])
|
||||
new_time = data.get("time")
|
||||
has_conflict, conflict_msg = _check_schedule_conflicts(
|
||||
user_uuid, new_days, new_time, exclude_routine_id=routine_id,
|
||||
new_routine_id=routine_id,
|
||||
)
|
||||
if has_conflict:
|
||||
return flask.jsonify({"error": conflict_msg}), 409
|
||||
frequency = data.get("frequency", "weekly")
|
||||
|
||||
# Check for schedule conflicts (only for weekly — interval conflicts checked at reminder time)
|
||||
if frequency == "weekly":
|
||||
new_days = data.get("days", [])
|
||||
new_time = data.get("time")
|
||||
has_conflict, conflict_msg = _check_schedule_conflicts(
|
||||
user_uuid, new_days, new_time, exclude_routine_id=routine_id,
|
||||
new_routine_id=routine_id,
|
||||
)
|
||||
if has_conflict:
|
||||
return flask.jsonify({"error": conflict_msg}), 409
|
||||
|
||||
existing = postgres.select_one("routine_schedules", {"routine_id": routine_id})
|
||||
schedule_data = {
|
||||
@@ -774,6 +783,9 @@ def register(app):
|
||||
"days": json.dumps(data.get("days", [])),
|
||||
"time": data.get("time"),
|
||||
"remind": data.get("remind", True),
|
||||
"frequency": frequency,
|
||||
"interval_days": data.get("interval_days"),
|
||||
"start_date": data.get("start_date"),
|
||||
}
|
||||
if existing:
|
||||
result = postgres.update(
|
||||
|
||||
Reference in New Issue
Block a user