Skip to content

Add workout scheduling#327

Open
Skydler wants to merge 3 commits intocyberjunky:masterfrom
Skydler:feature/workout-scheduling
Open

Add workout scheduling#327
Skydler wants to merge 3 commits intocyberjunky:masterfrom
Skydler:feature/workout-scheduling

Conversation

@Skydler
Copy link

@Skydler Skydler commented Mar 3, 2026

Added endpoint for scheduling workouts. Happy to help!

Summary by CodeRabbit

  • New Features

    • Interactive workout scheduling: browse workouts, pick one, enter a date, and schedule in a single flow.
    • Scheduling option added to the Activities & Workouts menu for quick access.
  • Bug Fixes

    • Minor improvements to error message formatting and handling for clearer feedback.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

Walkthrough

Adds a new scheduling feature: a Garmin.schedule_workout(workout_id, date_str) method that posts a date payload to the Garmin schedule endpoint, and an interactive demo flow schedule_workout_data(...) that lists workouts, prompts for selection and date, and calls the API.

Changes

Cohort / File(s) Summary
Core API Enhancement
garminconnect/__init__.py
Adds `Garmin.schedule_workout(workout_id: int
Demo UI Integration
demo.py
Adds schedule_workout_data(api: Garmin) interactive flow: lists workouts, accepts index and date input, calls api.schedule_workout. Registers new dispatch key "scheduled_workout" and exposes menu option "s" under Activities & Workouts. Minor formatting/exception-path tweaks.

Sequence Diagram

sequenceDiagram
    actor User
    participant Demo as Demo UI
    participant Garmin as Garmin Client
    participant Server as Garmin Connect Server

    User->>Demo: Choose "s" (schedule workout)
    Demo->>Garmin: get_workouts()
    Garmin->>Server: GET /workouts
    Server-->>Garmin: 200 OK + workout list
    Garmin-->>Demo: workout list

    Demo->>User: Show workouts
    User->>Demo: Select index & enter date (YYYY-MM-DD)

    Demo->>Garmin: schedule_workout(workout_id, date_str)
    Note over Garmin: validate workout_id and date_str
    Garmin->>Server: POST /workouts/{id}/schedule { "date": date_str }
    Server-->>Garmin: 200/201 confirmation
    Garmin-->>Demo: scheduled response

    Demo->>User: Display result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add workout scheduling' directly and clearly describes the main change: adding a new workout scheduling feature to the API and demo interface.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@demo.py`:
- Around line 2314-2322: The code is calling a non-existent method
api.scheduled_workout and unconditionally printing success; change the call to
the correct method api.schedule_workout (matching Garmin.schedule_workout) and
capture its return value from call_and_display (e.g., result =
call_and_display(..., method_name="schedule_workout", api_call_desc=...)); only
print "✅ Workout scheduled successfully!" if the captured result indicates
success (truthy/expected success structure) to prevent false-positive messages.
- Around line 2280-2287: get_workouts() is annotated as returning a dict but
callers (variables named workouts used with enumerate, slicing, or indexing)
expect a list; normalize the response immediately after calling
api.get_workouts() by checking its type and converting to a list: if workouts is
a dict, extract the actual list payload (e.g., workouts =
workouts.get("workouts") or workouts.get("items") if present) and if no list key
exists wrap the dict in [workouts]; otherwise ensure workouts is a list (e.g.,
if not isinstance(workouts, list): workouts = list(workouts)). Apply this
normalization at every call site that assigns to workouts (the calls to
api.get_workouts() that subsequently use enumerate, slicing like [:10] or [-1])
so downstream code can safely use list operations.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between edcf79f and dddf0b9.

📒 Files selected for processing (2)
  • demo.py
  • garminconnect/__init__.py

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
demo.py (1)

2314-2323: ⚠️ Potential issue | 🟠 Major

Only show success when scheduling actually succeeds.

Line 2314 ignores the (success, result) returned by call_and_display, and Line 2322 always prints success even on API failure. Also, method labels should match schedule_workout for accurate diagnostics.

🐛 Proposed fix
-            call_and_display(
+            success, _ = call_and_display(
                 api.schedule_workout,
                 workout_id,
                 schedule_date,
-                method_name="scheduled_workout",
-                api_call_desc=f"api.scheduled_workout({workout_id}, '{schedule_date}') - {workout_name}",
+                method_name="schedule_workout",
+                api_call_desc=f"api.schedule_workout({workout_id}, '{schedule_date}') - {workout_name}",
             )
-
-            print("✅ Workout scheduled successfully!")
+            if success:
+                print("✅ Workout scheduled successfully!")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demo.py` around lines 2314 - 2323, call_and_display currently returns
(success, result) but the code ignores it and always prints success; change the
call to capture the result from call_and_display (e.g., success, result =
call_and_display(...)) and only print "✅ Workout scheduled successfully!" when
success is truthy; also update the method_name and api_call_desc to use the
actual method name "schedule_workout" and a matching api_call_desc (e.g.,
f"api.schedule_workout({workout_id}, '{schedule_date}') - {workout_name}") so
diagnostics reflect the real API call; keep the call target api.schedule_workout
and variables workout_id, schedule_date, workout_name unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@demo.py`:
- Around line 2314-2323: call_and_display currently returns (success, result)
but the code ignores it and always prints success; change the call to capture
the result from call_and_display (e.g., success, result = call_and_display(...))
and only print "✅ Workout scheduled successfully!" when success is truthy; also
update the method_name and api_call_desc to use the actual method name
"schedule_workout" and a matching api_call_desc (e.g.,
f"api.schedule_workout({workout_id}, '{schedule_date}') - {workout_name}") so
diagnostics reflect the real API call; keep the call target api.schedule_workout
and variables workout_id, schedule_date, workout_name unchanged.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dddf0b9 and b653ebf.

📒 Files selected for processing (2)
  • demo.py
  • garminconnect/__init__.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant