Aligning activity-backend with frontend schema#9
Conversation
📝 WalkthroughWalkthroughAdds frontend-aligned activity models and mapping helpers, updates routes to accept/return frontend payloads and compute GPS-derived metrics, persists start/end times via the Supabase client, and adds README and API/curl documentation. Changes
Sequence DiagramssequenceDiagram
participant Frontend
participant Routes as Route Handler
participant Transform as Transform Logic
participant Supabase as Database
Frontend->>Routes: POST /activities (FrontendActivityCreate)
Routes->>Transform: _parse_iso(start_time/end_time)
Routes->>Transform: _to_location_points(gps_path)
Transform->>Transform: _compute_metrics_from_locations(locations)
Routes->>Supabase: create_activity(..., start_time, end_time, distance, elevation, gps_path)
Supabase-->>Routes: created activity record
Routes->>Transform: _activity_to_frontend(record)
Transform-->>Routes: FrontendActivityResponse
Routes-->>Frontend: FrontendActivityResponse
sequenceDiagram
participant Frontend
participant Routes as Route Handler
participant Supabase as Database
participant Transform as Transform Logic
Frontend->>Routes: GET /activities/{id}
Routes->>Supabase: fetch activity and locations
Supabase-->>Routes: backend activity record + locations
Routes->>Transform: _activity_to_frontend(activity)
Transform->>Transform: _to_frontend_locations(locations)
Transform-->>Routes: FrontendLocation[]
Routes-->>Frontend: FrontendActivityResponse
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
There was a problem hiding this comment.
Pull request overview
This PR aligns the activity-backend API with the frontend schema expectations to eliminate the need for manual data transformation on the frontend. The backend now accepts and returns data structures that match what the Flutter frontend expects.
Changes:
- Introduced frontend-compatible schemas (
FrontendActivityCreate,FrontendActivityResponse,FrontendActivityUpdate,FrontendLocation) inmodels.py - Added helper functions to convert between backend and frontend schemas and compute metrics (distance, elevation gain, pace) from GPS location data
- Updated all activity endpoints to accept frontend schemas and return frontend-compatible responses
- Added
start_timeandend_timeparameters to thecreate_activitymethod insupabase_client.py - Added comprehensive documentation for API schemas and curl test examples
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 20 comments.
Show a summary per file
| File | Description |
|---|---|
| activity-backend/models.py | Added frontend-compatible schema models (FrontendLocation, FrontendActivityCreate, FrontendActivityUpdate, FrontendActivityResponse) |
| activity-backend/routes/activities.py | Added conversion helper functions and updated all endpoints to use frontend schemas; server now computes metrics from location data |
| activity-backend/services/supabase_client.py | Updated create_activity method signature to accept start_time and end_time parameters |
| activity-backend/README.md | Updated deployment instructions to use python main.py with environment variables |
| activity-backend/FRONTEND_ACTIVITY_API_SCHEMA.md | New documentation describing the alignment between frontend and backend API schemas |
| activity-backend/CURL_TESTS.md | New documentation with curl examples for testing the aligned API endpoints |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| start_dt = _parse_iso(data.start_time) | ||
| end_dt = _parse_iso(data.end_time) | ||
| duration_seconds = max(0, int((end_dt - start_dt).total_seconds())) | ||
| metrics = _compute_metrics_from_locations([loc.model_dump() for loc in data.locations]) |
There was a problem hiding this comment.
The endpoint doesn't validate that the locations list is not empty. If a user submits an activity with an empty locations array, the metrics will all be 0 (distance, elevation gain), but the activity will still be created. While this might be intentional for some use cases (manual entry), it could also result in invalid or meaningless activities. Consider adding validation to require at least a minimum number of location points or documenting this behavior.
| start_time: str | ||
| end_time: str |
There was a problem hiding this comment.
The FrontendActivityResponse schema requires start_time and end_time to be non-optional strings, but the _activity_to_frontend function uses fallbacks including datetime.utcnow().isoformat() when these fields are missing. If the database doesn't have these fields for older activities, this could create inconsistent or incorrect timestamps. Consider either making these fields optional in the response schema or ensuring all activities in the database have these fields populated.
| start_time: str | |
| end_time: str | |
| start_time: Optional[str] = None | |
| end_time: Optional[str] = None |
| - Backend returns: an object `{ items: [ActivityResponse], total: int }`. | ||
| - Data provenance: list comes from backend store; pagination mismatch means frontend currently ignores `total` and expects bare array. | ||
|
|
||
| ## GET /activities/{id} | ||
| - Frontend expects response shaped like `Activity.fromJson` (includes type, distance, duration, start_time, end_time, pace metrics, locations, etc.). | ||
| - Backend returns `ActivityResponse` (fields: id, user_id, name, activity_type, gps_path, duration_seconds, distance_meters, elevation_gain_meters, visibility, description, created_at). |
There was a problem hiding this comment.
Lines 33 and 38 state that the backend returns the old schema, but this PR changes the backend to return FrontendActivityResponse (an array for lists, and the frontend-compatible shape for individual activities). This documentation is now outdated and should be updated to reflect the new response format.
| "calories": activity.get("calories"), | ||
| "is_public": (activity.get("visibility") == "public"), | ||
| "created_at": created_at, | ||
| "locations": _to_frontend_locations(activity.get("id"), gps_path), |
There was a problem hiding this comment.
The _to_frontend_locations function receives activity.get("id") which could be None, potentially causing issues when setting activity_id in the location objects. While the frontend schema allows activity_id to be None, this might not be the intended behavior for responses. Consider handling the case where activity.get("id") is None.
| except Exception: | ||
| avg_pace = None |
There was a problem hiding this comment.
The error handling catches a generic Exception and sets avg_pace to None, which could mask other errors. While division errors are unlikely here (given the conditional check), this broad exception handling could hide unexpected issues. Consider being more specific about which exceptions to catch or at least logging the exception for debugging.
| except Exception: | |
| avg_pace = None | |
| except (TypeError, ZeroDivisionError) as exc: | |
| logger.exception("Failed to compute average pace", exc_info=exc) |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
28/01/2026 1406 HKT
Aligning activity-backend with frontend schema
Summary by CodeRabbit
Documentation
Chores
New Features
✏️ Tip: You can customize this high-level summary in your review settings.